-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathneural_structure.py
109 lines (88 loc) · 2.72 KB
/
neural_structure.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import numpy as np
from structures import Individual, Node, NodeType, Link
class NeuralStructure:
def __init__(self, indiv, includeDisabled = False):
self.nodemap = {}
self.outputNids = []
#read in every node and create a logical node
for n in indiv.nodes:
self.nodemap[n.nid] = LogicalNode()
#if it's an output node, log it's id
if(n.nodeType == NodeType.OUTPUT):
self.outputNids.append(n.nid)
#if it's a bias node, set it's value to 1
elif(n.nodeType == NodeType.BIAS):
self.nodemap[n.nid].setCache(1)
self.nodemap[n.nid].inputVal = True
#if it's an input node, mark it as such
elif(n.nodeType == NodeType.INPUT):
self.nodemap[n.nid].inputVal = True
#read in every link and create dependencies from them
for l in indiv.links:
if includeDisabled or l.enabled:
# if not l.path.end in self.nodemap:
# if not includeDisabled:
# raise Exception("neural structure error")
# else:
# self.nodemap[l.path.end] = LogicalNode()
self.nodemap[l.path.end].addDependency(Dependency(l.path.start, l.weight))
def resetCache(self):
for _, n in self.nodemap.items():
n.cached = False
def ComputeOutputs(self, input):
self.resetCache()
#load inputs
for i in range(len(input)):
self.nodemap[i].setCache(input[i])
#create outputs
outputmap = [0] * len(self.outputNids)
for o in range(len(self.outputNids)):
outputmap[o] = self.nodemap[self.outputNids[o]].getOutput(self.nodemap)
return outputmap
## bad use of this structure, find a better way
## check if it's looping or impossible to calculate
def IsNodeValid(self, nid: int):
logicalNode = self.nodemap[nid]
if logicalNode.inputVal:
return True
if logicalNode.cached or len(logicalNode.dependencies) == 0:
return False
logicalNode.cached = True
for d in logicalNode.dependencies:
if not self.IsNodeValid(d.nid):
return False
# this is to make it not repeat.
logicalNode.inputVal = True
return True
class Dependency:
nid = 0
weight = 0.0
def __init__(self, i, w):
self.nid = i
self.weight = w
def __str__(self):
return(f"{self.nid} {self.weight}")
class LogicalNode:
inputVal = False
cached = False
cachedOutput = 0
dependencies = []
def __init__(self):
self.inputVal = False
self.cached = False
self.cachedOutput = 0
self.dependencies = []
def addDependency(self, d: Dependency):
self.dependencies.append(d)
def setCache(self, n):
self.cachedOutput = n
self.cached = True
def getOutput(self, nodemap):
if not self.cached and not self.inputVal:
self.computeNode(nodemap)
return self.cachedOutput
def computeNode(self, nodemap):
sum = 0
for dep in self.dependencies:
sum += nodemap[dep.nid].getOutput(nodemap) * dep.weight
self.setCache(np.tanh(sum))