github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/network/common.go (about) 1 // The package network provides data holders and utilities to describe Artificial Neural Network 2 package network 3 4 import ( 5 "errors" 6 "fmt" 7 "github.com/yaricom/goNEAT/neat/utils" 8 "math" 9 ) 10 11 var ( 12 // The error to be raised when maximal number of network activation attempts exceeded 13 NetErrExceededMaxActivationAttempts = errors.New("maximal network activation attempts exceeded.") 14 // The error to be raised when unsupported sensors data array size provided 15 NetErrUnsupportedSensorsArraySize = errors.New("the sensors array size is unsupported by network solver") 16 // The error to be raised when depth calculation failed due to the loop in network 17 NetErrDepthCalculationFailedLoopDetected = errors.New("depth can not be determined for network with loop") 18 ) 19 20 // Defines network solver interface which describes neural network structures with methods to run activation waves through 21 // them. 22 type NetworkSolver interface { 23 // Propagates activation wave through all network nodes provided number of steps in forward direction. 24 // Returns true if activation wave passed from all inputs to outputs. 25 ForwardSteps(steps int) (bool, error) 26 27 // Propagates activation wave through all network nodes provided number of steps by recursion from output nodes 28 // Returns true if activation wave passed from all inputs to outputs. 29 RecursiveSteps() (bool, error) 30 31 // Attempts to relax network given amount of steps until giving up. The network considered relaxed when absolute 32 // value of the change at any given point is less than maxAllowedSignalDelta during activation waves propagation. 33 // If maxAllowedSignalDelta value is less than or equal to 0, the method will return true without checking for relaxation. 34 Relax(maxSteps int, maxAllowedSignalDelta float64) (bool, error) 35 36 // Flushes network state by removing all current activations. Returns true if network flushed successfully or 37 // false in case of error. 38 Flush() (bool, error) 39 40 // Set sensors values to the input nodes of the network 41 LoadSensors(inputs []float64) error 42 // Read output values from the output nodes of the network 43 ReadOutputs() []float64 44 45 // Returns the total number of neural units in the network 46 NodeCount() int 47 // Returns the total number of links between nodes in the network 48 LinkCount() int 49 } 50 51 // NNodeType defines the type of NNode to create 52 type NodeType byte 53 54 // Predefined NNode types 55 const ( 56 // The neuron type 57 NeuronNode NodeType = iota 58 // The sensor type 59 SensorNode 60 ) 61 62 // Returns human readable NNode type name for given constant value 63 func NodeTypeName(nType NodeType) string { 64 switch nType { 65 case NeuronNode: 66 return "NEURON" 67 case SensorNode: 68 return "SENSOR" 69 default: 70 return "!!! UNKNOWN NODE TYPE !!!" 71 } 72 } 73 74 // NeuronType defines the type of neuron to create 75 type NodeNeuronType byte 76 77 // These are NNode layer type 78 const ( 79 // The node is in hidden layer 80 HiddenNeuron NodeNeuronType = iota 81 // The node is in input layer 82 InputNeuron 83 // The node is in output layer 84 OutputNeuron 85 // The node is bias 86 BiasNeuron 87 ) 88 89 // Returns human readable neuron type name for given constant 90 func NeuronTypeName(nlayer NodeNeuronType) string { 91 switch nlayer { 92 case HiddenNeuron: 93 return "HIDN" 94 case InputNeuron: 95 return "INPT" 96 case OutputNeuron: 97 return "OUTP" 98 case BiasNeuron: 99 return "BIAS" 100 default: 101 return "!!! UNKNOWN NEURON TYPE !!!" 102 } 103 } 104 105 // Returns neuron node type from its name 106 func NeuronTypeByName(name string) (NodeNeuronType, error) { 107 switch name { 108 case "HIDN": 109 return HiddenNeuron, nil 110 case "INPT": 111 return InputNeuron, nil 112 case "OUTP": 113 return OutputNeuron, nil 114 case "BIAS": 115 return BiasNeuron, nil 116 default: 117 return math.MaxInt8, errors.New("Unknown neuron type name: " + name) 118 } 119 } 120 121 // Method to calculate activation for specified neuron node based on it's ActivationType field value. 122 // Will return error and set -0.0 activation if unsupported activation type requested. 123 func ActivateNode(node *NNode, a *utils.NodeActivatorsFactory) error { 124 out, err := a.ActivateByType(node.ActivationSum, node.Params, node.ActivationType) 125 if err == nil { 126 node.setActivation(out) 127 } 128 return err 129 } 130 131 // Method to activate neuron module presented by provided node. As a result of execution the activation values of all 132 // input nodes will be processed by corresponding activation function and corresponding activation values of output nodes 133 // will be set. Will panic if unsupported activation type requested. 134 func ActivateModule(module *NNode, a *utils.NodeActivatorsFactory) error { 135 inputs := make([]float64, len(module.Incoming)) 136 for i, v := range module.Incoming { 137 inputs[i] = v.InNode.GetActiveOut() 138 } 139 140 outputs, err := a.ActivateModuleByType(inputs, module.Params, module.ActivationType) 141 if err != nil { 142 return err 143 } 144 if len(outputs) != len(module.Outgoing) { 145 return fmt.Errorf( 146 "number of output parameters [%d] returned by module activator doesn't match "+ 147 "the number of output neurons of the module [%d]", len(outputs), len(module.Outgoing)) 148 } 149 // set outputs 150 for i, out := range outputs { 151 module.Outgoing[i].OutNode.setActivation(out) 152 module.Outgoing[i].OutNode.isActive = true // activate output node 153 } 154 return nil 155 }