6
6
7
7
from lcs import Perception
8
8
from . import Configuration , Condition , Effect , PMark , matching
9
+ from . import ProbabilityEnhancedAttribute
9
10
10
11
11
12
logger = logging .getLogger (__name__ )
@@ -139,21 +140,26 @@ def fitness(self):
139
140
@property
140
141
def specified_unchanging_attributes (self ) -> List [int ]:
141
142
"""
142
- Determines the number of specified unchanging attributes in
143
- the classifier. An unchanging attribute is one that is anticipated
144
- not to change in the effect part.
143
+ Determines the specified unchanging attributes in the classifier.
144
+ An unchanging attribute is one that is anticipated not to change
145
+ in the effect part.
145
146
146
147
Returns
147
148
-------
148
149
List[int]
149
- list specified unchanging attributes indices
150
+ list of specified unchanging attributes indices
150
151
"""
151
152
indices = []
152
153
153
154
for idx , (cpi , epi ) in enumerate (zip (self .condition , self .effect )):
154
- if cpi != self .cfg .classifier_wildcard and \
155
- epi == self .cfg .classifier_wildcard :
156
- indices .append (idx )
155
+ if isinstance (epi , ProbabilityEnhancedAttribute ):
156
+ if cpi != self .cfg .classifier_wildcard and \
157
+ epi .does_contain (cpi ):
158
+ indices .append (idx )
159
+ else :
160
+ if cpi != self .cfg .classifier_wildcard and \
161
+ epi == self .cfg .classifier_wildcard :
162
+ indices .append (idx )
157
163
158
164
return indices
159
165
@@ -178,6 +184,9 @@ def is_reliable(self) -> bool:
178
184
def is_inadequate (self ) -> bool :
179
185
return self .q < self .cfg .theta_i
180
186
187
+ def is_enhanceable (self ):
188
+ return self .ee
189
+
181
190
def increase_experience (self ) -> int :
182
191
self .exp += 1
183
192
return self .exp
@@ -206,16 +215,62 @@ def specialize(self,
206
215
Requires the effect attribute to be a wildcard to specialize it.
207
216
By default false
208
217
"""
209
- for idx , item in enumerate ( situation ):
218
+ for idx in range ( len ( situation ) ):
210
219
if leave_specialized :
211
220
if self .effect [idx ] != self .cfg .classifier_wildcard :
212
221
# If we have a specialized attribute don't change it.
213
222
continue
214
223
215
224
if previous_situation [idx ] != situation [idx ]:
216
- self .effect [idx ] = situation [idx ]
225
+ if self .effect [idx ] == self .cfg .classifier_wildcard :
226
+ self .effect [idx ] = situation [idx ]
227
+ else :
228
+ if not isinstance (self .effect [idx ],
229
+ ProbabilityEnhancedAttribute ):
230
+ self .effect [idx ] = ProbabilityEnhancedAttribute (
231
+ self .effect [idx ])
232
+ self .effect [idx ].insert_symbol (situation [idx ])
233
+
217
234
self .condition [idx ] = previous_situation [idx ]
218
235
236
+ def merge_with (self , other_classifier , perception , time ):
237
+ assert self .cfg .do_pee
238
+
239
+ result = Classifier (cfg = self .cfg )
240
+
241
+ result .condition = Condition (self .condition )
242
+ result .condition .specialize_with_condition (other_classifier .condition )
243
+
244
+ # action is an int, so we can assign directly
245
+ result .action = self .action
246
+
247
+ result .effect = Effect .enhanced_effect (
248
+ self .effect , other_classifier .effect ,
249
+ self .q , other_classifier .q ,
250
+ perception )
251
+
252
+ result .mark = PMark (cfg = self .cfg )
253
+
254
+ result .r = (self .r + other_classifier .r ) / 2.0
255
+ result .q = (self .q + other_classifier .q ) / 2.0
256
+
257
+ # This 0.5 is Q_INI constant in the original C++ code
258
+ if result .q < 0.5 :
259
+ result .q = 0.5
260
+
261
+ result .num = 1
262
+ result .tga = time
263
+ result .talp = time
264
+ result .tav = 0
265
+ result .exp = 1
266
+
267
+ result .ee = False
268
+
269
+ return result
270
+
271
+ def reverse_increase_quality (self ):
272
+ self .q = (self .q - self .cfg .beta ) / (1.0 - self .cfg .beta )
273
+
219
274
def predicts_successfully (self ,
220
275
p0 : Perception ,
221
276
action : int ,
@@ -270,14 +325,18 @@ def does_anticipate_correctly(self,
270
325
False otherwise
271
326
"""
272
327
def effect_item_is_correct (effect_item , p0_item , p1_item ):
273
- if effect_item == self .cfg .classifier_wildcard :
274
- if p0_item != p1_item :
275
- return False
328
+ if not isinstance (effect_item , ProbabilityEnhancedAttribute ):
329
+ if effect_item == self .cfg .classifier_wildcard :
330
+ if p0_item != p1_item :
331
+ return False
332
+ else :
333
+ if p0_item == p1_item :
334
+ return False
335
+
336
+ if effect_item != p1_item :
337
+ return False
276
338
else :
277
- if p0_item == p1_item :
278
- return False
279
-
280
- if effect_item != p1_item :
339
+ if not effect_item .does_contain (p1_item ):
281
340
return False
282
341
283
342
# All checks passed
0 commit comments