0

I'm trying to use OptaPy for inspector's schedule optimization.

I've tried to add a shadow variable, which must be updated along with another variable. Docs recommend to annotate one shadow variable with custom VariableListener and make others refer to it.

This is how I did it (part of actual code):

@planning_entity
class Task(Slot):
    inspector: Inspector
    prev_slot: Slot
    from_time: datetime

    def __init__(self, inspector: Inspector = None, from_time: datetime = None):
        self.inspector = inspector
        self.from_time = from_time
        self.prev_slot = None

    @custom_shadow_variable(Inspector,
        variable_listener_class = TaskUpdatingVariableListener,
        sources = [planning_variable_reference(variable_name = 'previous_slot')])
    def get_inspector(self):
        return self.inspector

    @custom_shadow_variable(datetime,
        variable_listener_ref = planning_variable_reference(variable_name = 'inspector'))
    def get_from_time(self):
        return self.from_time

    @planning_variable(Slot, 
        value_range_provider_refs=['day_start_range', 'task_range'], 
        graph_type=PlanningVariableGraphType.CHAINED)
    def get_previous_slot(self):
        return self.prev_slot

    def set_previous_slot(self, previous_slot: Slot):
        self.prev_slot = previous_slot

Here, TaskUpdatingVariableListener is @variable_listener, and Slot is a @problem_fact.

The problem is when I run this code, it gives me Java type cast error:

Traceback (most recent call last):
File "model_v4.py", line 324, in <module>
  class Task(Slot):
File ".../python3.9/site-packages/optapy/annotations.py", line 546, in planning_entity
  return planning_entity_wrapper(entity_class)
File ".../python3.9/site-packages/optapy/annotations.py", line 540, in planning_entity_wrapper
  out.__optapy_java_class = _generate_planning_entity_class(entity_class_argument, annotation_data)
File ".../python3.9/site-packages/optapy/optaplanner_java_interop.py", line 1030, in _generate_planning_entity_class
  optaplanner_annotations = _get_optaplanner_annotations(python_class)
File ".../python3.9/site-packages/optapy/optaplanner_java_interop.py", line 955, in _get_optaplanner_annotations
  _to_java_list(list(map(lambda annotation: getattr(getattr(python_class, method),
File ".../python3.9/site-packages/optapy/optaplanner_java_interop.py", line 936, in _to_java_list
  out.add(_to_java_map(item))
File ".../python3.9/site-packages/optapy/optaplanner_java_interop.py", line 925, in _to_java_map
  out.put(JObject(key, java.lang.Object), JObject(value, java.lang.Object))
File ".../python3.9/site-packages/jpype/_jobject.py", line 59, in __new__
  return _JObjectFactory(*args, **kwargs)
File ".../python3.9/site-packages/jpype/_jobject.py", line 111, in _JObjectFactory
  return tp._cast(v)
TypeError: Unable to cast 'dict' to java type 'java.lang.Object'

And if I remove second shadow variable (get_from_time), it compiles pretty well!

Changing variable type from datetime to anything else didn't help.

What could be the problem here?

kol
  • 126
  • 1
  • 5
  • Sound like a bug in `optapy`; my guess from the error it has to do with `planning_variable_reference(variable_name = 'inspector')` (since, IIRC, that return a dict with annotation info). I will investigate. – Christopher Chianelli Sep 01 '22 at 13:48

1 Answers1

0

This was a bug in optapy (see https://github.com/optapy/optapy/pull/99 for details), and will be fixed in the next release.

Christopher Chianelli
  • 1,163
  • 1
  • 8
  • 8