Uploaded image for project: 'OptaPlanner'
  1. OptaPlanner
  2. PLANNER-2738

Wrong FlightAssignment comparator corrupts the CollectionInverseVariableListener

    XMLWordPrintable

Details

    • 2022 Week 23-25 (from Jun 6)
    • 3
    • NEW
    • NEW

    Description

      https://github.com/kiegroup/optaplanner-quickstarts/issues/339

      The Employee has the following shadow variable:

          @InverseRelationShadowVariable(sourceVariableName = "employee")
          private SortedSet<FlightAssignment> flightAssignmentSet;
      

      Each time an employee is assigned, the flight assignment is added to the shadow variable set. The variable listener legitimately assumes that after Chad Q. Green is assigned to AB007@2018-01-01-0, his flightAssignmentSet does not yet contain AB007@2018-01-01-0 (before the listener adds it).

      Now, flightAssignmentSet is actually a TreeSet, which requires the comparator to be consistent with equals. But the comparator used to compare flight assignments only takes into account the flight departure time, arrival time and the flight assignment index within the flight (a flight typically has multiple assignments - several pilots and several attendants). So, different flight assignments can be compared as equal if their flight has the same departure and arrival time, even if it's a completely different flight (between different airports).

      From the TreeSet point of view, if the comparator says c1.compareTo(c2) == 0, then c1 and c2 are equal. Therefore, the following exception happens on certain data sets:

      java.lang.IllegalStateException: The entity (AB007@2018-01-01-0) has a variable (employee) with value (Chad Q. Green) which has a sourceVariableName variable (flightAssignmentSet) with a value ([AB001@2018-01-01-0, AB005@2018-01-01-0, AB008@2018-01-01-0, AB009@2018-01-01-0]) which already contained the entity (AB007@2018-01-01-0).
      Verify the consistency of your input problem for that bi-directional relationship.
      	at org.optaplanner.core.impl.domain.variable.inverserelation.CollectionInverseVariableListener.insert(CollectionInverseVariableListener.java:88)
      

      The flightAssignmentSet clearly doesn't contain AB007@2018-01-01-0 but since it has the same departure and arrival as AB009@2018-01-01-0 they are considered equal by the TreeSet.

      The following is the same exception message with modified Flight toString() that includes departure time.

      java.lang.IllegalStateException: The entity (AB007@2018-01-01T07:22-0) has a variable (employee) with value (Chad Q. Green) which has a sourceVariableName variable (flightAssignmentSet) with a value ([AB001@2018-01-01T05:12-0, AB005@2018-01-01T06:03-0, AB008@2018-01-01T06:58-0, AB009@2018-01-01T07:22-0]) which already contained the entity (AB007@2018-01-01T07:22-0).
      

      Attachments

        Issue Links

          Activity

            People

              lpetrovi@redhat.com Lukáš Petrovický (Inactive)
              jlocker Jiří Locker
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: