is None not working
wemiam-co opened this issue · comments
Hi,
I'm facing a problem with the use of "is None"
I'm using forEachIncludingNullVars()
I have None values that i would like to penalize, but they dont seem to be detected.
When i try to reward the not None values it works.
Is it a bug or i'm missing something ?
Same when i try to avoir null pointer exceptions.
When i code, before making operations on some variables i set X is not None and Y is not None and ( X.a !=Y.a ). This avoids null pointer exceptions.
But with optapy, i still get null pointer exceptions.
Am I doing something wrong ?
Thanks :)
Can you please paste some code (that include your planning entities, problem facts, planning solution and constraints) that can be run to replicate the NullPointerException?
Hi Christopher,
Here are the classes and more details about the error:
class Resp:
id: int
name: str
date_dispo: datetime.date
creneau_dispo: str
last_rdv: datetime.date
collab: str
param_strat: str
def init(self, id, name_resp, date_dispo, creneau_dispo, last_rdv,collab,param_strat):
self.id = id
self.name_resp = name_resp
self.date_dispo=date_dispo
self.creneau_dispo=creneau_dispo
self.last_rdv=last_rdv
self.collab=collab
self.param_strat=param_strat
@planning_id
def get_id(self):
return self.id
def __str__(self):
return f"id={self.id}, name_resp={self.name_resp}, date_dispo={self.date_dispo}, creneau_dispo={self.creneau_dispo}, last_rdv={self.last_rdv}, collab={self.collab}, param_strat={self.param_strat}\n"
def __repr__(self):
return self.__str__()
@planning_entity
class Talent:
id: int
name: str
dateslot: Dateslot
resp: Resp
talent_creneau: Talent_creneau
def init(self, id, name, dateslot=None, resp=None, talent_creneau=None):
self.id = id
self.name = name
self.dateslot = dateslot
self.resp = resp
self.talent_creneau=talent_creneau
@planning_id
def get_id(self):
return self.id
@planning_variable(Dateslot, ["dateslotRange"],nullable = False)
def get_dateslot(self):
return self.dateslot
def set_dateslot(self, new_dateslot):
self.dateslot = new_dateslot
@planning_variable(Resp, ["respRange"],nullable = True)
def get_resp(self):
return self.resp
def set_resp(self, new_resp):
self.resp = new_resp
contraint where the problem is located:
def pen_resp_notnone(constraint_factory: ConstraintFactory):
return constraint_factory.forEachIncludingNullVars(Talent)
.flatten_last(lambda talent: talent)
.filter(lambda talent:talent.resp is None )
.penalize("pen_resp_notnone" ,HardMediumSoftScore.ONE_MEDIUM)
Error :
java.lang.RuntimeException: java.lang.RuntimeException: org.optaplanner.jpyinterpreter.types.errors.AttributeError: object 'Talent(6, None, None, 32f2bd91-5482-46e4-a32e-7965a74191b5,None)
' does not have attribute 'resp'
And when i write this, i don't get any penality, like if it didn't detect any thing :
def pen_resp_notnone(constraint_factory: ConstraintFactory):
return constraint_factory.forEachIncludingNullVars(Talent)
.filter(lambda talent:talent.resp is None )
.penalize("pen_resp_notnone" ,HardMediumSoftScore.ONE_MEDIUM)
Thanks for the reproducer. A tip on formatting code on GitHub: use
```language
code
```
when creating code blocks, which will cause the code to be properly formatted and indented. For instance,
```python
def my_fun():
print('hello world')
```
would appear as
def my_fun():
print('hello world')
The flatten_last 'trick' is interesting, since that code should error before the filter (since Talent
is not iterable). Nonetheless, it is a bug, and can be observed without the flatten_last
by using print
(or in general, an operation that is not is
).
Thanks, i'm not familiar with github. If i understand correctly your answer, there is a bug in optapy? Or it's in my code ?
If it's in optapy, do you have any idea when the fix will be released?
Have a nice day!
Both (flatten_last
should not be used to flatten something that not an iterable (user + optapy), and Java null is not being converted to Python None (optapy)). I can't give a firm time line for the fix, but I'll investigate it when I have time.
Fixed by #152