-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconscious_decisions_block.py
More file actions
291 lines (246 loc) · 11.5 KB
/
Copy pathconscious_decisions_block.py
File metadata and controls
291 lines (246 loc) · 11.5 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
import pickle
import random
from decision_by_prediction_block import DecisionByPredictionBlock
from internal_state import BiologyCultureFeelings, InternalState
# Pathos multiprocessing import
from pathos.multiprocessing import Pool
# Detect system import
from detect_system import DetectSystem
## \defgroup Intentions Intentions related classes
#
# These are the set of classes that support decision making
# for intentions creation
# @{
##
# The Conscious Decisions Block is in charge of 'rationally' evaluating
# current internal state and goals in order to make decisions. The quotes in
# 'rationally' stand for the agent trying to choose what he thinks is the best
# course of action according to past experiences, but not what is really
# best in the mathematical sense (objective function). The result from
# the last decision taken can be fed back for evaluation and evolution of its
# behaviour
#
class ConsciousDecisionsBlock():
## Input size
INPUT_SIZE = 9
## Class constructor
def __init__(self):
# Desired state
self.desired_state = InternalState()
self.desired_state.set_state([0.5,1,1])
# Initial internal state
self.internal_state = InternalState([0.5,0.5,0.5])
# Decision by prediction network
self.decision_prediction_block = DecisionByPredictionBlock()
self.decision_prediction_block.set_desired_state(self.desired_state)
self.decision_prediction_block.set_internal_state(self.internal_state)
# DEFAULT TRAINING, IT CAN LATER BE OVERRIDEN
# Create a random training set so that the net can learn the relation prediction = (ei + choice.bcf)/2
# We require a minimum of 18 points
training_set = []
# 3.2.4.1 todo: parallelize
# Helper method, used to execute in parallel
def __generate_training(index):
ei = [random.random(), random.random(), random.random()]
choice_bcf = [random.random(), random.random(), random.random()]
prediction = [ei_j / 2.0 + choice_bcf_j / 2.0 for ei_j, choice_bcf_j in zip(ei, choice_bcf)]
return ei + choice_bcf, prediction
# Init thread's pool, with the determined processor number
pool = Pool(DetectSystem().cpu_count())
# Parallel execution
training_set = pool.map(__generate_training, range(20))
# for index in range(20):
# ei = [random.random(), random.random(), random.random()]
# choice_bcf = [random.random(), random.random(), random.random()]
# prediction = [ei_j / 2.0 + choice_bcf_j / 2.0 for ei_j, choice_bcf_j in zip(ei, choice_bcf)]
# training_set.append((ei + choice_bcf, prediction))
# Remodel predictive net
self.decision_prediction_block.remodel_predictive_net(training_set)
self._inputs = None
self._new_inputs = False
self.decision = None
self._last_decision_type = None
self._last_selected_input = None
self._last_decision_internal_state = None
## Set desired state
# @param desired_state InternalState. Desired internal state
# @retval result Boolean. True if desired state correctly set, False in any other case
def set_desired_state(self, desired_state):
if desired_state.__class__ == InternalState:
self.desired_state = desired_state
return True
return False
## Get desired state
# @retval desired_state InternalState. Stored desired state
def get_desired_state(self):
return self.desired_state
## Set internal state
# @param internal_state InternalState. New internal state.
# @retval result Boolean. True if internal state correctly set, False in any other case
def set_internal_state(self, internal_state):
if internal_state.__class__ == InternalState:
self.internal_state = internal_state
return True
return False
## Get internal state
# @retval internal_state InternalState. Stored internal state
def get_internal_state(self):
return self.internal_state
## Get last decision type
# @retval last_decision_type Enumeration with values 'BIOLOGY_ALARM', 'FREE_WILL' or 'PREDICTED'
def get_last_decision_type(self):
return self._last_decision_type
## Set conscious decisions block inputs
# @param inputs: vector of inputs of the form [bcf, bcf, bcf]
# (1st input, 2nd input, 3rd input)
def set_inputs(self, inputs):
self._inputs = inputs
self._new_inputs = True
## Get block inputs
# @retval inputs vector of the form [bcf, bcf, bcf]
def get_inputs(self):
return self._inputs
## Get decision
# @ret_val decision Integer. Index of the selected input.
def get_decision(self):
self._calc_decision()
return self.decision
def _calc_decision(self):
if not self._new_inputs:
return
# If there is a biology alarm, make best decision for biology
if self.internal_state.biology_alarm():
self._make_best_biology_decision()
self._last_decision_type = "BIOLOGY_ALARM"
# Else, make either a decision by simulation or
# a random (Free-will like) decision
else:
predicted_decision = self._decision_by_prediction()
free_will_decision = self._free_will_decision()
self.decision = self._select_predicted_or_free_will(predicted_decision, free_will_decision)
self._new_inputs = False
# Store last selected input
self._last_selected_input = self._inputs[self.decision].get_state()
# Store internal state of last decision
self._last_decision_internal_state = self.internal_state.get_state()
def _make_best_biology_decision(self):
# Biology in alarm due to violated upper threshold
index_best_biology = 0
if self.internal_state.biology_up_alarm():
# Select option with the lowest biology val
for index in range(len(self._inputs)):
if self._inputs[index].get_biology() < self._inputs[index_best_biology].get_biology():
index_best_biology = index
# Biology in alarm due to violated lower threshold
else:
# Select option with the geatest biology val
for index in range(len(self._inputs)):
if self._inputs[index].get_biology() > self._inputs[index_best_biology].get_biology():
index_best_biology = index
self.decision = index_best_biology
self._new_inputs = False
def _decision_by_prediction(self):
prediction_inputs = [self._inputs[0].get_state(), self._inputs[1].get_state(), self._inputs[2].get_state()]
self.decision_prediction_block.set_internal_state(self.internal_state)
self.decision_prediction_block.set_desired_state(self.desired_state)
self.decision_prediction_block.set_inputs(prediction_inputs)
return self.decision_prediction_block.get_output()
## If free will really exists, it is no random for the person who decides. But it can't be
# predicted by others, i.e., for an external observer, its result is a random one. And that's what we are,
# external observers of the kernel
def _free_will_decision(self):
return random.randint(0,2)
## Most of the time, decisions are not concerned with free will, but with previous experiences
def _select_predicted_or_free_will(self, predicted_decision, free_will_decision):
rand_number = random.random()
if rand_number > 0.90:
self._last_decision_type = "FREE_WILL"
return free_will_decision
else:
self._last_decision_type = "PREDICTED"
return predicted_decision
## Train predictive network
# @param training_set Vector of the form [ [bcf_is bcf_i], bcf_o ]
# where bcf_is is the internal state BCF
# and bcf_i is the input BCF
# and bcf_o is the expected or predicted new internal state bcf
def training(self, training_set ):
self.decision_prediction_block.remodel_predictive_net(training_set)
## Feedback a new internal state to prediction network
# @param new_internal_state InternalState. New internal state after making a decision and acting on environment
def feedback(self, new_internal_state):
if not self.set_internal_state(new_internal_state):
return
# Only the prediction network can be affected by feedback
if self._last_decision_type != "PREDICTED":
return
predictive_net_training_data = [(self._last_decision_internal_state + self._last_selected_input,
self.internal_state.get_state())]
self.decision_prediction_block.remodel_predictive_net(predictive_net_training_data)
@classmethod
## Serialize object and store in given file
# @param cls CulturalNetwork class
# @param obj CulturalNetwork object to be serialized
# @param name Name of the file where the serialization is to be stored
def serialize(cls, obj, name):
pickle.dump(obj, open(name, "wb"))
@classmethod
## Deserialize object stored in given file
# @param cls CulturalNetwork class
# @param name Name of the file where the object is serialize
def deserialize(cls, name):
try:
retval = pickle.load(open(name, "rb"))
except IOError:
retval = ConsciousDecisionsBlock()
return retval
## @}
#
# Tests
if __name__ == '__main__':
cdb = ConsciousDecisionsBlock()
# FREE WILL DECISIONS 20% of the time
# Inputs
i0 = BiologyCultureFeelings([0.5,0.9,0.9])
i1 = BiologyCultureFeelings([0.5,0.9,0.9])
i2 = BiologyCultureFeelings([0.4,0.7,0.9])
inputs = [i0, i1, i2]
cdb.set_inputs(inputs)
cdb.internal_state.set_state([0.5,0.5,0.5])
# Show free will decisions
print('-'*60)
print('FREE WILL')
print 'Inputs: ', inputs[0].get_state(), inputs[1].get_state(), inputs[2].get_state()
for i in range(10):
cdb.set_inputs(inputs)
d = cdb.get_decision()
print "Decision is: ", d, " made by ", cdb.get_last_decision_type()
# BIOLOGY ALARMS
cdb.internal_state.set_state([0.9,1,1])
cdb.set_inputs(inputs)
print('-' * 60)
print 'BIOLOGY ALARM'
print 'Internal state: ', cdb.internal_state.get_state()
print 'Decision is: ', cdb.get_decision(), ' made by ', cdb.get_last_decision_type()
cdb.internal_state.set_state([0.1, 1, 1])
cdb.set_inputs(inputs)
print 'Internal state: ', cdb.internal_state.get_state()
print 'Decision is: ', cdb.get_decision(), ' made by ', cdb.get_last_decision_type()
# FEEDBACK TEST
test = True
internal_state = InternalState()
cdb.internal_state.set_state([0.5, 1, 1])
while test:
print 'FEEDBACK TEST'
print('-'*60)
i0.set_state(input('Enter input #0 ([B,C,F]): '))
i1.set_state(input('Enter input #1 ([B,C,F]): '))
i2.set_state(input('Enter input #2 ([B,C,F]): '))
cdb.set_inputs([i0, i1, i2])
print "Internal state: ", cdb.internal_state.get_state()
print "Decision: ", cdb.get_decision(), " made by ", cdb.get_last_decision_type()
internal_state.set_state(input('Feedback new internal state ([B,C,F]): '))
cdb.feedback(internal_state)
cdb.set_inputs([i0, i1, i2])
print "New decision would be: ", cdb.get_decision(), " made by ", cdb.get_last_decision_type()
test = input("Continue testing? (True/False): " )