-
Notifications
You must be signed in to change notification settings - Fork 3
/
IntuitivePhysics.py
138 lines (97 loc) · 6.47 KB
/
IntuitivePhysics.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
from NeuralNetPhiR import NeuralNetPhiR
from NeuralNetPhiO import NeuralNetPhiO
from PrimitivesPhysics import PrimitivesPhysics
from CapsuleNetwork import CapsuleNetwork
from PhysicsMemory import PhysicsMemory
from PhysicsMemory import PhysicsMemoryMode
from RelationTriplet import RelationTriplet
from HyperParameters import HyperParameters
from Observation import Observation
from AttributePool import AttributePool
import numpy as np
class IntuitivePhysics:
def __init__(self, capsNet : CapsuleNetwork):
self._neuralNetPhiR : NeuralNetPhiR = None
self._neuralNetPhiO : NeuralNetPhiO = None
self._capsuleNetwork : CapsuleNetwork = capsNet
self._physicsMemory : PhysicsMemory = PhysicsMemory()
self._neuralNetPhiR = NeuralNetPhiR(None, None, capsNet.getName() + "-IP-PhiR", False, True, (RelationTriplet.tripletLength(), HyperParameters.DegreesOfFreedom))
self._neuralNetPhiO = NeuralNetPhiO(None, None, capsNet.getName() + "-IP-PhiO", False, True, (self.getAggregateDimension(), HyperParameters.MaximumAttributeCount * 2))
def getAggregateDimension(self):
return HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + HyperParameters.DegreesOfFreedom * 4
def aggregate(self, effects : list, external : list, observation : Observation):
# effects # List of Effect Vectors
# external # External Effect Vector
# observation # Original Observation
aggregated = [0.0] * self.getAggregateDimension()
# Attributes
for attr, value in observation.getOutputs().items():
pos = self._capsuleNetwork.getAttributePool().getAttributeOrder(attr)
if pos > -1:
aggregated[pos] = value
# Symbols
if observation.getCapsule().getOrderID() < HyperParameters.MaximumSymbolCount:
aggregated[HyperParameters.MaximumAttributeCount + observation.getCapsule().getOrderID()] = 1.0
# Velocities
for i in range(HyperParameters.MaximumAttributeCount):
aggregated[HyperParameters.MaximumSymbolCount + HyperParameters.MaximumAttributeCount + i] = 0.5
for attr, value in observation.getVelocities(HyperParameters.TimeStep).items():
pos = self._capsuleNetwork.getAttributePool().getAttributeOrder(attr)
if pos > -1:
aggregated[HyperParameters.MaximumAttributeCount + HyperParameters.MaximumSymbolCount + pos] = (value + 1.0) * 0.5
# Static/Dynamic + Rigid/Elastic
DQ, DS = observation.getCapsule().getPhysicalProperties()
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount] = DQ[0]
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 1] = DQ[1]
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 2] = DQ[2]
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 3] = DS[0]
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 4] = DS[1]
aggregated[HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 5] = DS[2]
# Effects
offset = HyperParameters.MaximumAttributeCount * 2 + HyperParameters.MaximumSymbolCount + 2 * HyperParameters.DegreesOfFreedom
for i in range(HyperParameters.DegreesOfFreedom):
summed = 0.0
for effect in effects:
summed = summed + ((effect[i] * 2.0) - 1.0)
aggregated[offset + i] = (summed + 1.0) * 0.5
# External Effects
for i in range(HyperParameters.DegreesOfFreedom):
aggregated[offset + HyperParameters.DegreesOfFreedom + i] = external[i]
return aggregated # Object Attributes + Symbol + Velocities + Static/Dynamic + Rigid/Elastic + Effects + External Effects
def fillMemorySynthetically(self, primitivesPhysics : PrimitivesPhysics, extraTraining : int = 0):
self._physicsMemory.setSyntheticPhysics(primitivesPhysics, self._capsuleNetwork.getAttributePool())
if self._neuralNetPhiR.hasTraining() is False:
self.trainPhiR()
for i in range(extraTraining):
self.trainPhiR()
if self._neuralNetPhiO.hasTraining() is False:
self.trainPhiO()
for i in range(extraTraining):
self.trainPhiO()
def trainPhiR(self, showDebugOutput : bool = True):
self._physicsMemory.setMode(PhysicsMemoryMode.PhiR)
self._neuralNetPhiR.trainFromData(self._physicsMemory, showDebugOutput)
def trainPhiO(self, showDebugOutput : bool = True):
self._physicsMemory.setMode(PhysicsMemoryMode.PhiO)
self._neuralNetPhiO.trainFromData(self._physicsMemory, showDebugOutput)
def predict(self, observations : dict, external : list):
newObservations = {}
for caps, obsList in observations.items():
newObservations[caps] = []
for receiverObs in obsList:
effects = []
for senderObs in [x for senderObsList in observations.values() for x in senderObsList]:
if senderObs != receiverObs:
triplet, distance = RelationTriplet.generate(senderObs, receiverObs, self._capsuleNetwork.getAttributePool(), self._capsuleNetwork)
effects.append(self._neuralNetPhiR.forwardPass(triplet))
aggregated = self.aggregate(effects, external, receiverObs)
result = self._neuralNetPhiO.forwardPass(aggregated)
attributes = RelationTriplet.mapAttributes(self._capsuleNetwork.getAttributePool(), caps, result)
accelerations = RelationTriplet.mapAttributes(self._capsuleNetwork.getAttributePool(), caps, result, HyperParameters.MaximumAttributeCount)
newObs = Observation(caps, receiverObs.getTakenRoute(), receiverObs.getInputObservations(), attributes, receiverObs.getProbability())
newObs.linkPreviousObservation(receiverObs)
for attr, accel in accelerations.items():
accelerations[attr] = ((accel * 2.0) - 1.0) * HyperParameters.AccelerationScale
newObs.setAccelerations(accelerations)
newObservations[caps].append(newObs)
return newObservations