title: Difficulty satisfying hard and medium constraints simultaneously with Optaplanner
body: <p>I've implemented a sensor scheduling problem using OptaPlanner 6.2 that has 1 hard constraint, 1 medium constraint, and 1 soft constraint.  The trouble I'm having is that either I can satisfy some of the hard constraints after 30 seconds of or so, and then the solver makes very little progress satisfying them constraints with additional minutes of termination.  I don't think the problem is over constrained; I also don't know how to help the local search process significantly increase the score.</p>
  
  <p>My problem is a scheduling one, where I precalculate all possible times (intervals) that a sensor can observe objects prior to solving.   I've modeled the problem as follows:</p>
  
  <ol>
  <li><p>Hard constraint - no intervals can overlap</p>
  
  <pre><code> when
     $s1: A( interval!=null,$id: id, $doy : interval.doy, $interval: interval, $sensor: interval.getSensor())
    exists A( id &gt; $id, interval!=null, $interval2: interval, $interval2.getSensor() == $sensor, $interval2.getDoy() == $doy, $interval.getStartSlot() &lt;= $interval2.getEndSlot(), $interval.getEndSlot() &gt;= $interval2.getStartSlot() )
   then
     scoreHolder.addHardConstraintMatch(kcontext,-10000);
  </code></pre></li>
  <li><p>Medium constraint - every assignment should have an Interval</p>
  
  <pre><code>when
    A(interval==null)
  then
    scoreHolder.addMediumConstraintMatch(kcontext,-100);
  </code></pre></li>
  <li><p>Soft constraint - maximize a property/value in the Interval class</p>
  
  <pre><code>when
    $s1: A( interval!=null)
  then
    scoreHolder.addSoftConstraintMatch(kcontext,-1 * $s1.getInterval().getSomeProperty())
  </code></pre></li>
  </ol>
  
  <p>A:  entity planning class; each instance is an assignment for a particular object (i.e has an member objectid that corresponds with one in the Interval class)</p>
  
  <p>Interval:  planning variable class, all possible intervals (start time, stop time) for the sensor and objects</p>
  
  <p>In A, I restrict access to B instances (intervals) to just those for the object associated with that assignment.   For my test case, there are 40000 or so Intervals, but only dozens for each object.  There are about 1100 instances of A (so dozens of possible Intervals for each one).</p>
  
  <pre><code>@PlanningVariable(valueRangeProviderRefs = {"intervalRange"},strengthComparatorClass = IntervalStrengthComparator.class, nullable=true)
  public Interval getInterval() {
      return interval;
  }
  
  @ValueRangeProvider(id = "intervalRange")
  public List&lt;Interval&gt; getPossibleIntervalList() {
      return task.getAvailableIntervals();
  }
  </code></pre>
  
  <p>In my solution class:
      //have tried commenting this out since the overall interval list does not apply to all A
      @ValueRangeProvider (id="intervalRangeAll")
      public List  getIntervalList() {
          return intervals;
      }</p>
  
  <pre><code>@PlanningEntityCollectionProperty
  public List&lt;A&gt; getAList() {
      return AList;
  }
  </code></pre>
  
  <p>I've reviewed the documentation and tried a lot of things.  My problem is somewhat of a cross between the nurserostering and course scheduling examples, which I have looked at.  I am using the FIRST_FIT_DECREASING construction heuristic.</p>
  
  <p>What I have tried:</p>
  
  <ol>
  <li>Turning on and off nullable in the planning variable annotation for A.getInterval()</li>
  <li>Late acceptance, Tabu, both.</li>
  <li>Benchmarking. I wasn't seeing any problems and average </li>
  <li>Adding an IntervalChangeFactory as a moveListFactory.   Restricting the custom ChangeMove to whether the interval can be accepted or not (i.e. enforcing or not the hard constraint in the IntervalChangeMove.isDoable).</li>
  </ol>
  
  <p>Here is an example one, where most of the hard constraints are not satisfied, but the medium ones are:</p>
  
  <pre><code>[main] INFO org.optaplanner.core.impl.solver.DefaultSolver - Solving  started: time spent (202), best score (0hard/-112500medium/0soft), environment  mode (REPRODUCIBLE), random (WELL44497B with seed 987654321).
  [main] INFO org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase - Construction Heuristic phase (0) ended: step total (1125), time spent (2296), best score (-9100000hard/0medium/-72608soft).
  [main] INFO org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase - Local Search phase (1) ended: step total (92507), time spent (30000), best score (-8850000hard/0medium/-74721soft).
  [main] INFO org.optaplanner.core.impl.solver.DefaultSolver - Solving ended: time spent (30000), best score (-8850000hard/0medium/-74721soft), average calculate count per second (5643), environment mode (REPRODUCIBLE).
  </code></pre>
  
  <p>So I don't understand is why the hard constraints can't be deal with by the search process.  Any my calculate count per second has dropped to below 10000 due to all the tinkering I've done.</p>