Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OptaPyException: A problem occurred when wrapping the python problem #176

Open
DavidGarHeredia opened this issue Jul 20, 2023 · 2 comments

Comments

@DavidGarHeredia
Copy link

Hi!

I was trying to solve a school timetabling problem using Optapy, but I got the following error:

solution = solver.solve(problem_to_solve)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/d-future/miniconda3/envs/Minerva/lib/python3.11/site-packages/optapy/optaplanner_api_wrappers.py", 
line 416, in solve
    wrapped_problem = PythonSolver.wrapProblem(object_class, problem)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
org.optaplanner.optapy.org.optaplanner.optapy.OptaPyException: org.optaplanner.optapy.OptaPyException: 
A problem occurred when wrapping the python problem
(<jpype._jproxy.proxy.OptaPlannerSchedule object at 0x7ff372e86440>). 
Maybe an annotation was passed an incorrect type (for example, @problem_fact_collection_property(str)  
on a function that return a list of int).

I have reviewed the code multiple times to find an error like the one described in the msg but I did not succeed. Could you have a quick look at the code below to see if I am missing something? From the error msg, it seems to be something trivial, but it keeps eluding me :S

Thanks in advance!

@dataclass(frozen=True)
class Slot:
    id: int
    t0: datetime
    tf: datetime
    duration: timedelta = field(init=False)

    def __post_init__(self):
        object.__setattr__(self, "duration", self.tf - self.t0)


@problem_fact
class SlotFact:
    def __init__(self, slot: Slot):
        self.slot = slot

    @planning_id
    def get_id(self) -> int:
        return self.slot.id

    @property
    def duration(self):
        return self.slot.duration


@planning_entity
class AssignmentEntity:
    def __init__(
        self,
        id: int,
        teacher: OptaTeacher,
        group: OptaGroup,
        subject: Subject,
        room: Classroom,
        slot: Optional[SlotFact] = None,
    ) -> None:
        self.id = id
        self.teacher = teacher
        self.group = group
        self.subject = subject
        self.room = room
        self.slot = slot

    @planning_id
    def get_id(self):
        return self.id

    @planning_variable(SlotFact, ["SlotRange"])
    def get_slot(self):
        return self.slot

    def set_slot(self, new_slot: SlotFact):
        self.slot = new_slot

@planning_solution
class OptaPlannerSchedule:
    def __init__(
        self, slots: list[SlotFact], assignments: list[AssignmentEntity], score=None
    ):
        self.slots = slots
        self.assignments = assignments
        self.score = score

    @problem_fact_collection_property(SlotFact)
    @value_range_provider("SlotRange")
    def get_slots(self) -> list[SlotFact]:
        return self.slots

    @planning_entity_collection_property(AssignmentEntity)
    def get_assignments(self) -> list[AssignmentEntity]:
        return self.assignments

    @planning_score(HardSoftScore)
    def get_score(self):
        return self.score

    def set_score(self, score):
        self.score = score
@mmmvvvppp
Copy link

There's a note at the bottom of section 3.3.1 that warns:

Planning entity __hash__(self) implementations must remain constant. Therefore entity __hash__(self) must not depend on any planning variables. Pay special attention when using data structures with auto-generated __hash__(self) as entities, such as Python @dataclass.

Perhaps this is an origin of your problem?

@DavidGarHeredia
Copy link
Author

Hey! Thanks for the response!

I tried defining a __hash__(self) method for the @planning_entity class, but still not working. Actually, I think the error may have a different nature as @planning_entity is defined as a class, not as @dataclass.

According to the error msg, the issue seems to happen when wrapping the @planning_solution class. However, given your warning about the usage of @dataclass, I wonder if there may be any other side effects when using these with Optapy? I will try to investigate in that direction.

In the meanwhile, if you come up with any other ideas, just let me know, please.

Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants