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

Cant consistently create relation between two python planning entities #1282

Open
luxaritas opened this issue Dec 20, 2024 · 2 comments
Open
Labels
bug Something isn't working process/needs triage Requires initial assessment of validity, priority etc.

Comments

@luxaritas
Copy link

luxaritas commented Dec 20, 2024

Describe the bug
Attempting to have two planning entities refer to each other leads to a runtime error

Expected behavior
It should work just as it already does if the inverse relation is not specified (even if you still set the property at runtime)

Actual behavior

Traceback (most recent call last):
  File "DefaultSolver.java", line 196, in ai.timefold.solver.core.impl.solver.DefaultSolver.solve
java.lang.java.lang.NullPointerException: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$141.invoke(org.jpyinterpreter.user.__main__.ResourceConfiguration)" because "org.jpyinterpreter.user.__main__.ResourceConfiguration.$methodholder$get_cpu_range" is null

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "DefaultSolver.java", line 196, in ai.timefold.solver.core.impl.solver.DefaultSolver.solve
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 109, in solve
    java_solution = self._delegate.solve(java_problem)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
java.lang.java.lang.IllegalStateException: java.lang.IllegalStateException: The property ($method$get_cpu_range) getterMethod (public ai.timefold.jpyinterpreter.types.collections.PythonLikeList org.jpyinterpreter.user.__main__.ResourceConfiguration.$method$get_cpu_range()) on bean of class (class org.jpyinterpreter.user.__main__.ResourceConfiguration) throws an exception.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py", line 63, in <module>
    solver_factory.build_solver().solve(problem)
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 113, in solve
    raise RuntimeError(f'Solving failed due to an error: {e.getMessage()}.\n'
RuntimeError: Solving failed due to an error: The property ($method$get_cpu_range) getterMethod (public ai.timefold.jpyinterpreter.types.collections.PythonLikeList org.jpyinterpreter.user.__main__.ResourceConfiguration.$method$get_cpu_range()) on bean of class (class org.jpyinterpreter.user.__main__.ResourceConfiguration) throws an exception..
Java stack trace: java.lang.IllegalStateException: The property ($method$get_cpu_range) getterMethod (public ai.timefold.jpyinterpreter.types.collections.PythonLikeList org.jpyinterpreter.user.__main__.ResourceConfiguration.$method$get_cpu_range()) on bean of class (class org.jpyinterpreter.user.__main__.ResourceConfiguration) throws an exception.
        at ai.timefold.solver.core.impl.domain.common.accessor.ReflectionMethodMemberAccessor.executeGetter(ReflectionMethodMemberAccessor.java:76)
        at ai.timefold.solver.core.impl.domain.valuerange.descriptor.AbstractFromPropertyValueRangeDescriptor.readValueRangeSize(AbstractFromPropertyValueRangeDescriptor.java:146)
        at ai.timefold.solver.core.impl.domain.valuerange.descriptor.FromEntityPropertyValueRangeDescriptor.extractValueRangeSize(FromEntityPropertyValueRangeDescriptor.java:35)
        at ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor.lambda$getApproximateValueCount$15(SolutionDescriptor.java:1083)
        at ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor.visitEntitiesByEntityClass(SolutionDescriptor.java:985)
        at ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor.getApproximateValueCount(SolutionDescriptor.java:1080)
        at ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor.getProblemSizeStatistics(SolutionDescriptor.java:1143)
        at ai.timefold.solver.core.impl.solver.DefaultSolver.registerSolverSpecificMetrics(DefaultSolver.java:249)
        at ai.timefold.solver.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:228)
        at ai.timefold.solver.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:196)
Caused by: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$141.invoke(org.jpyinterpreter.user.__main__.ResourceConfiguration)" because "org.jpyinterpreter.user.__main__.ResourceConfiguration.$methodholder$get_cpu_range" is null
        at org.jpyinterpreter.user.__main__.ResourceConfiguration.$method$get_cpu_range(/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py:29)
        at ai.timefold.solver.core.impl.domain.common.accessor.ReflectionMethodMemberAccessor.executeGetter(ReflectionMethodMemberAccessor.java:73)
        ... 9 more

To Reproduce

from typing import Annotated
from dataclasses import dataclass, field
from timefold.solver.domain import (
    PlanningVariable,
    PlanningEntityCollectionProperty,
    PlanningScore, ValueRangeProvider,
    planning_entity, planning_solution
)
from timefold.solver.score import HardSoftScore, constraint_provider
from timefold.solver import SolverFactory
from timefold.solver.config import SolverConfig, ScoreDirectorFactoryConfig, TerminationConfig, Duration

@planning_entity
@dataclass
class ResourceConfiguration2:
    parent: 'ResourceConfiguration' = field(default=None)
    cpus: Annotated[int, PlanningVariable(value_range_provider_refs = ['cpu_range2'])] = 1

    def get_cpu_range(self) -> Annotated[list[int], ValueRangeProvider(id='cpu_range2')]:
        return list(range(1, 5))


@planning_entity
@dataclass
class ResourceConfiguration:
    child: ResourceConfiguration2
    cpus: Annotated[int, PlanningVariable(value_range_provider_refs = ['cpu_range'])] = 1

    def get_cpu_range(self) -> Annotated[list[int], ValueRangeProvider(id='cpu_range')]:
        return list(range(1, 5))

@planning_solution
@dataclass
class Schedule:
    resource_configurations: Annotated[list[ResourceConfiguration], PlanningEntityCollectionProperty]
    resource_configuration2s: Annotated[list[ResourceConfiguration2], PlanningEntityCollectionProperty]

    score: Annotated[HardSoftScore, PlanningScore] = field(default=None)

@constraint_provider
def constraints(factory):
    return [
        factory.for_each(ResourceConfiguration).penalize(HardSoftScore.ONE_HARD).as_constraint('static')
    ]

solver_factory = SolverFactory.create(
    SolverConfig(
        solution_class=Schedule,
        entity_class_list=[ResourceConfiguration, ResourceConfiguration2],
        score_director_factory_config=ScoreDirectorFactoryConfig(
            constraint_provider_function=constraints
        ),
        termination_config=TerminationConfig(
            spent_limit=Duration(seconds=1)
        )
    )
)

rc2 = ResourceConfiguration2(1)
rc = ResourceConfiguration(rc2, 1)
rc2.parent = rc
problem = Schedule([rc], [rc2])
solver_factory.build_solver().solve(problem)

Environment

Timefold Solver Version or Git ref:
1.17.0

Output of java -version:

openjdk version "23" 2024-09-17
OpenJDK Runtime Environment (build 23)
OpenJDK 64-Bit Server VM (build 23, mixed mode, sharing)

Output of uname -a or ver:

Linux 6.6.63-1-MANJARO #1 SMP PREEMPT_DYNAMIC Sat Nov 23 02:15:34 UTC 2024 x86_64 GNU/Linux

Additional information

While in this reduced example the error refers to get_cpu_range, in my actual project it instead complains about a lack of __eq__, which suggests this is something more general with the binding generation rather than ValueRangeProvider

@luxaritas luxaritas added bug Something isn't working process/needs triage Requires initial assessment of validity, priority etc. labels Dec 20, 2024
@luxaritas
Copy link
Author

Interestingly if you switch the order of the classes, you instead get the following error:

Traceback (most recent call last):
  File "java.lang.ClassLoader.java", line 0, in java.lang.ClassLoader.loadClass
java.lang.java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: org.jpyinterpreter.user.__main__.ResourceConfiguration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "PythonClassTranslator.java", line 156, in ai.timefold.jpyinterpreter.PythonClassTranslator.translatePythonClass
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py", line 46, in <module>
    solver_factory = SolverFactory.create(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver_factory.py", line 51, in create
    solver_config = solver_config._to_java_solver_config()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/config/_config.py", line 211, in _to_java_solver_config
    _process_compilation_queue()
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_timefold_java_interop.py", line 365, in _process_compilation_queue
    compile_class(python_class)
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_timefold_java_interop.py", line 346, in compile_class
    out = translate_python_class_to_java_class(python_class).getJavaClass()
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/_jpyinterpreter/translator.py", line 758, in translate_python_class_to_java_class
    out = PythonClassTranslator.translatePythonClass(python_compiled_class, prepared_class_info)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
java.lang.java.lang.NoClassDefFoundError: java.lang.NoClassDefFoundError: org/jpyinterpreter/user/__main__/ResourceConfiguration

I'll also note this appears to be something more generally with reverse references (or declaration ordering more generally). Eg, this works:

from typing import Annotated
from dataclasses import dataclass, field
from timefold.solver.domain import (
    PlanningVariable, InverseRelationShadowVariable,
    PlanningEntityCollectionProperty,
    PlanningScore, ValueRangeProvider,
    planning_entity, planning_solution
)
from timefold.solver.score import HardSoftDecimalScore, constraint_provider
from timefold.solver import SolverFactory
from timefold.solver.config import SolverConfig, ScoreDirectorFactoryConfig, TerminationConfig, Duration

@planning_entity
@dataclass
class Task:
    '''
    An individual unit of work that needs to be performed and its resource requirements
    '''
    
    shard: Annotated['ComputeShard', PlanningVariable] = field(default=None)

@planning_entity
@dataclass
class ResourceConfiguration:
    '''
    An amount of available resources to a task, as configured in a ComputeShard
    '''

    cpus: Annotated[int, PlanningVariable(value_range_provider_refs = ['cpu_range'])] = 1

    def get_cpu_range(self) -> Annotated[list[int], ValueRangeProvider(id='cpu_range')]:
        return list(range(1, 5))

@planning_entity
@dataclass
class ComputeShard:
    resources: 'ResourceConfiguration'
    tasks: Annotated[list['Task'], InverseRelationShadowVariable(source_variable_name='shard')] = field(default_factory=list)

@planning_solution
@dataclass
class Schedule:
    tasks: Annotated[list[Task], PlanningEntityCollectionProperty, ValueRangeProvider]
    compute_shards: Annotated[list[ComputeShard], PlanningEntityCollectionProperty, ValueRangeProvider]
    resource_configurations: Annotated[list[ResourceConfiguration], PlanningEntityCollectionProperty]

    score: Annotated[HardSoftDecimalScore, PlanningScore] = field(default=None)

@constraint_provider
def constraints(factory):
    return [
        factory.for_each(Task).penalize(HardSoftDecimalScore.ONE_HARD).as_constraint('static')
    ]

solver_factory = SolverFactory.create(
    SolverConfig(
        solution_class=Schedule,
        entity_class_list=[Task, ResourceConfiguration, ComputeShard],
        score_director_factory_config=ScoreDirectorFactoryConfig(
            constraint_provider_function=constraints
        ),
        termination_config=TerminationConfig(
            spent_limit=Duration(seconds=1)
        )
    )
)
solver = solver_factory.build_solver()

resource_configurations = [ResourceConfiguration()]
compute_shards = [ComputeShard(resource_configurations[0])]
tasks = [Task(), Task()]

problem = Schedule(
    tasks,
    compute_shards,
    resource_configurations
)
solver.solve(problem)

But this, where ComputeShard is moved before Task, fails:

from typing import Annotated
from dataclasses import dataclass, field
from timefold.solver.domain import (
    PlanningVariable, InverseRelationShadowVariable,
    PlanningEntityCollectionProperty,
    PlanningScore, ValueRangeProvider,
    planning_entity, planning_solution
)
from timefold.solver.score import HardSoftDecimalScore, constraint_provider
from timefold.solver import SolverFactory
from timefold.solver.config import SolverConfig, ScoreDirectorFactoryConfig, TerminationConfig, Duration

@planning_entity
@dataclass
class ComputeShard:
    resources: 'ResourceConfiguration'
    tasks: Annotated[list['Task'], InverseRelationShadowVariable(source_variable_name='shard')] = field(default_factory=list)

@planning_entity
@dataclass
class Task:
    '''
    An individual unit of work that needs to be performed and its resource requirements
    '''
    
    shard: Annotated['ComputeShard', PlanningVariable] = field(default=None)

@planning_entity
@dataclass
class ResourceConfiguration:
    '''
    An amount of available resources to a task, as configured in a ComputeShard
    '''

    cpus: Annotated[int, PlanningVariable(value_range_provider_refs = ['cpu_range'])] = 1

    def get_cpu_range(self) -> Annotated[list[int], ValueRangeProvider(id='cpu_range')]:
        return list(range(1, 5))

@planning_solution
@dataclass
class Schedule:
    tasks: Annotated[list[Task], PlanningEntityCollectionProperty, ValueRangeProvider]
    compute_shards: Annotated[list[ComputeShard], PlanningEntityCollectionProperty, ValueRangeProvider]
    resource_configurations: Annotated[list[ResourceConfiguration], PlanningEntityCollectionProperty]

    score: Annotated[HardSoftDecimalScore, PlanningScore] = field(default=None)

@constraint_provider
def constraints(factory):
    return [
        factory.for_each(Task).penalize(HardSoftDecimalScore.ONE_HARD).as_constraint('static')
    ]

solver_factory = SolverFactory.create(
    SolverConfig(
        solution_class=Schedule,
        entity_class_list=[Task, ResourceConfiguration, ComputeShard],
        score_director_factory_config=ScoreDirectorFactoryConfig(
            constraint_provider_function=constraints
        ),
        termination_config=TerminationConfig(
            spent_limit=Duration(seconds=1)
        )
    )
)
solver = solver_factory.build_solver()

resource_configurations = [ResourceConfiguration()]
compute_shards = [ComputeShard(resource_configurations[0])]
tasks = [Task(), Task()]

problem = Schedule(
    tasks,
    compute_shards,
    resource_configurations
)
solver.solve(problem)
Traceback (most recent call last):
  File "DefaultSolver.java", line 197, in ai.timefold.solver.core.impl.solver.DefaultSolver.solve
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 109, in solve
    java_solution = self._delegate.solve(java_problem)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
java.lang.java.lang.NullPointerException: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$146.invoke(org.jpyinterpreter.user.__main__.Task, ai.timefold.jpyinterpreter.PythonLikeObject)" because "org.jpyinterpreter.user.__main__.Task.$methodholder$__eq__" is null

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py", line 78, in <module>
    solver.solve(problem)
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 113, in solve
    raise RuntimeError(f'Solving failed due to an error: {e.getMessage()}.\n'
RuntimeError: Solving failed due to an error: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$146.invoke(org.jpyinterpreter.user.__main__.Task, ai.timefold.jpyinterpreter.PythonLikeObject)" because "org.jpyinterpreter.user.__main__.Task.$methodholder$__eq__" is null.
Java stack trace: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$146.invoke(org.jpyinterpreter.user.__main__.Task, ai.timefold.jpyinterpreter.PythonLikeObject)" because "org.jpyinterpreter.user.__main__.Task.$methodholder$__eq__" is null
        at org.jpyinterpreter.user.__main__.Task.$method$__eq__(/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py:2)
        at org.jpyinterpreter.user.__main__.Task.equals(/home/jonathan/Development/eterna/OpenKnotScorePipeline/repro.py)
        at java.base/java.util.ArrayList.remove(Unknown Source)
        at ai.timefold.jpyinterpreter.types.collections.PythonLikeList.remove(PythonLikeList.java:483)
        at ai.timefold.solver.core.impl.domain.variable.inverserelation.CollectionInverseVariableListener.retract(CollectionInverseVariableListener.java:98)
        at ai.timefold.solver.core.impl.domain.variable.inverserelation.CollectionInverseVariableListener.beforeVariableChanged(CollectionInverseVariableListener.java:36)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:15)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:6)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.AbstractNotifiable.triggerBefore(AbstractNotifiable.java:70)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerNotifiable.notifyBefore(VariableListenerNotifiable.java:26)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:211)
        at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:403)
        at ai.timefold.solver.core.impl.move.director.VariableChangeAction.undo(VariableChangeAction.java:12)
        at ai.timefold.solver.core.impl.move.director.VariableChangeRecordingScoreDirector.undoChanges(VariableChangeRecordingScoreDirector.java:64)
        at ai.timefold.solver.core.impl.move.director.EphemeralMoveDirector.close(EphemeralMoveDirector.java:47)
        at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:278)
        at ai.timefold.solver.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.doMove(ConstructionHeuristicDecider.java:158)
        at ai.timefold.solver.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.decideNextStep(ConstructionHeuristicDecider.java:113)
        at ai.timefold.solver.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:63)
        at ai.timefold.solver.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:83)
        at ai.timefold.solver.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:197)

@luxaritas luxaritas changed the title Cant create 1:1 relation between two python planning entities Cant consistently create relation between two python planning entities Dec 20, 2024
@luxaritas
Copy link
Author

Also seeing similar behavior when attempting to annotate the parameters of a VariableListener in my actual project. I don't have a minimal repro for that right now, but will include the error in case it's useful:

Traceback (most recent call last):
  File "DefaultSolver.java", line 197, in ai.timefold.solver.core.impl.solver.DefaultSolver.solve
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 109, in solve
    java_solution = self._delegate.solve(java_problem)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
java.lang.java.lang.NullPointerException: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$152.invoke(org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener, ai.timefold.jpyinterpreter.PythonLikeObject, org.jpyinterpreter.user.openknotscore.plan.domain.Task)" because "org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$methodholder$before_variable_changed" is null

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/solver.py", line 179, in <module>
    plan = solve(
           ^^^^^^
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/solver.py", line 176, in solve
    return solver.solve(problem)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/_solver.py", line 113, in solve
    raise RuntimeError(f'Solving failed due to an error: {e.getMessage()}.\n'
RuntimeError: Solving failed due to an error: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$152.invoke(org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener, ai.timefold.jpyinterpreter.PythonLikeObject, org.jpyinterpreter.user.openknotscore.plan.domain.Task)" because "org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$methodholder$before_variable_changed" is null.
Java stack trace: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$152.invoke(org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener, ai.timefold.jpyinterpreter.PythonLikeObject, org.jpyinterpreter.user.openknotscore.plan.domain.Task)" because "org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$methodholder$before_variable_changed" is null
        at org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$method$before_variable_changed(/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/domain.py:96)
        at org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$method$before_variable_changed(/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/domain.py)
        at org.jpyinterpreter.synthetic.org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.before_variable_changed$$Dispatcher.$call(Unknown Source)
        at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.beforeVariableChanged.invoke(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py:105)
        at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.$method$beforeVariableChanged(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py:103)
        at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.beforeVariableChanged(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:15)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:6)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.AbstractNotifiable.triggerBefore(AbstractNotifiable.java:70)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerNotifiable.notifyBefore(VariableListenerNotifiable.java:26)
        at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:211)
        at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:403)
        at ai.timefold.solver.core.impl.move.director.VariableChangeRecordingScoreDirector.beforeVariableChanged(VariableChangeRecordingScoreDirector.java:76)
        at ai.timefold.solver.core.impl.move.director.VariableChangeRecordingScoreDirector.changeVariableFacade(VariableChangeRecordingScoreDirector.java:177)
        at ai.timefold.solver.core.impl.heuristic.selector.move.generic.ChangeMove.doMoveOnGenuineVariables(ChangeMove.java:54)
        at ai.timefold.solver.core.impl.heuristic.move.AbstractMove.doMoveOnly(AbstractMove.java:26)
        at ai.timefold.solver.core.impl.heuristic.move.LegacyMoveAdapter.execute(LegacyMoveAdapter.java:54)
        at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:265)
        at ai.timefold.solver.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.doMove(ConstructionHeuristicDecider.java:158)
        at ai.timefold.solver.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.decideNextStep(ConstructionHeuristicDecider.java:113)
        at ai.timefold.solver.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:63)
        at ai.timefold.solver.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:83)
        at ai.timefold.solver.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:197)
        Suppressed: java.lang.NullPointerException: Cannot invoke "org.jpyinterpreter.synthetic.signature.InterfaceSignature$$152.invoke(org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener, ai.timefold.jpyinterpreter.PythonLikeObject, org.jpyinterpreter.user.openknotscore.plan.domain.Task)" because "org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$methodholder$before_variable_changed" is null
                at org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$method$before_variable_changed(/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/domain.py:96)
                at org.jpyinterpreter.user.openknotscore.plan.domain.TaskAssignmentListener.$method$before_variable_changed(/home/jonathan/Development/eterna/OpenKnotScorePipeline/openknotscore/plan/domain.py)
                at org.jpyinterpreter.synthetic.org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.before_variable_changed$$Dispatcher.$call(Unknown Source)
                at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.beforeVariableChanged.invoke(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py:105)
                at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.$method$beforeVariableChanged(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py:103)
                at org.jpyinterpreter.user.timefold.solver.domain._variable_listener.VariableListener.beforeVariableChanged(/home/jonathan/Development/eterna/OpenKnotScorePipeline/.venv/lib/python3.12/site-packages/timefold/solver/domain/_variable_listener.py)
                at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:15)
                at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerBefore(VariableChangedNotification.java:6)
                at ai.timefold.solver.core.impl.domain.variable.listener.support.AbstractNotifiable.triggerBefore(AbstractNotifiable.java:70)
                at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerNotifiable.notifyBefore(VariableListenerNotifiable.java:26)
                at ai.timefold.solver.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:211)
                at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:403)
                at ai.timefold.solver.core.impl.move.director.VariableChangeAction.undo(VariableChangeAction.java:12)
                at ai.timefold.solver.core.impl.move.director.VariableChangeRecordingScoreDirector.undoChanges(VariableChangeRecordingScoreDirector.java:64)
                at ai.timefold.solver.core.impl.move.director.EphemeralMoveDirector.close(EphemeralMoveDirector.java:47)
                at ai.timefold.solver.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:264)
                ... 5 more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working process/needs triage Requires initial assessment of validity, priority etc.
Projects
None yet
Development

No branches or pull requests

1 participant