optapy / optapy

OptaPy is an AI constraint solver for Python to optimize planning and scheduling problems.

Home Page:https://www.optapy.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

is None not working

wemiam-co opened this issue · comments

commented

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?

commented

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'

commented

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).

commented

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.