Accessing Assignment in SearchMonitor AtSolution() method

890 views
Skip to first unread message

Alastair Andrew

unread,
Sep 11, 2013, 7:05:36 PM9/11/13
to or-tools...@googlegroups.com
Hi,

I was wondering if anyone could give me any advice regarding the best approach for accessing the Assignment from a RoutingModel search via a custom SearchMonitor? I know Renault De Landtsheer has covered a couple of similar questions (in threads here and here) but the answers are more about accessing the objective value or stopping the search at a specific point. 

I'm trying to write a GUI for my VRP solver that allows me to update the visualisation to reflect the current best solution found during the local search phase. 

The basic outline of my Java SearchMonitor is:

static class GUIMonitor extends SearchMonitor {
   private RoutingModel model;

   public GUIMonitor(RoutingModel m){
      super(m.solver());
      model = m;
   }

   public boolean atSolution(){
      System.out.println("Found solution"); 
      return true; 
   } 
}

If I register this with the RoutingModel then my output appears at (approximately) the same time as -routing_trace log statements. From the RoutingModel I've stored in the model variable I can access the other decision variables / slack vars etc. How do I get hold of the Assignment object at the point when atSolution is called? In all the examples I've seen it is returned by the solve call, is there another way to access the current variable assignments at any point during the search?

Thanks,
Alastair

Navjot Kukreja

unread,
Nov 26, 2013, 8:55:57 AM11/26/13
to or-tools...@googlegroups.com
Hi Alastair
Did you figure this out eventually? I want to do the same and I have looked hard but the best answer I have found is thatI would have to add all the variables and the objective var to the assignment (which I make from solver.makeAssignment() I guess ). The objective var is automatically constructed by the Routing Model which would be a combination of travel costs and disjunction penalties. I see no way to access this var. Also, for the zillion other vars in the model that would need to be added to the assignment, could I get an array of all vars in the model maybe?

Thanks 
Navjot

Alastair Andrew

unread,
Nov 26, 2013, 9:59:08 AM11/26/13
to or-tools...@googlegroups.com
Hi Navjot,

No, I haven't discovered the "proper" way to do it. I was hoping Laurent or one of the or-tools authors might shed some light. The answer might be to use the SolutionPool callback's registerNewSolution method. I haven't tried it yet (and I'm not even sure if it works with the Routing Library), so I can't guarantee anything.

A

Nikola

unread,
Nov 27, 2013, 5:57:12 AM11/27/13
to or-tools...@googlegroups.com
I have only done the part accessing the objective value and stopping the search, but I believe you should be able to access the solution itself using a SolutionCollector (e.g. BestValueSolutionCollector) and its solution() method. No need to implement SearchMonitor, SolutionCollectors are already implemented doing what you want.

Nikola

Navjot Kukreja

unread,
Nov 28, 2013, 5:28:46 AM11/28/13
to or-tools...@googlegroups.com
Nikola
I tried using a AllSolutionCollector to access the solution inside the AtSolution method of a SearchMonitor. No variable values are being returned and the objective is returned as zero every time. Reading the other threads on this topic I am led to believe that for this to work, I need to add the model variables and the objective variable to the assignment returned by the SolutionCollector. Is that correct? If not, could you write a couple of lines of code to show me how to use a SolutionCollector to get intermediate solution assignments (before the end of search)?
Thanks
Navjot

Nikola

unread,
Dec 2, 2013, 8:55:02 AM12/2/13
to or-tools...@googlegroups.com
Ok, here is some code in Python that tracks the best solution found and terminates the search if there hasn't been an improvement during the last 2 seconds:

  # set up your model in advance, then:

  routing.CloseModel()

  bestCollector=solver.BestValueSolutionCollector(False)
  bestCollector.AddObjective(routing.CostVar())
  routing.AddSearchMonitor(bestCollector)

  bestSolution = dict(score=sys.maxint, clock=0, startTime=time.time())
  def enough():
      if bestCollector.SolutionCount() > 0 and bestCollector.ObjectiveValue(0) < bestSolution.score:
        bestSolution['score'] = bestCollector.ObjectiveValue(0)
        bestSolution['clock'] = bestCollector.WallTime(0)
        print bestSolution.solution(0) # that's the solution

      #stop search?
      return bestSolution['score'] < sys.maxint and \ 
              time.time()-bestSolution['startTime'] > \
              bestSolution['clock']*0.001+2)

  routing.AddSearchMonitor(solver.CustomLimit(enough))
  plan = routing.Solve() #run the solver

Hope this helps,
Nikola

Navjot Kukreja

unread,
Dec 3, 2013, 12:14:45 AM12/3/13
to or-tools...@googlegroups.com
Nikola
Thanks a million for this. Clears up a lot of things for me, and I hope a few others too. 
Appreciate it.
-Navjot

Ido Hadanny

unread,
Jul 14, 2019, 4:26:29 PM7/14/19
to or-tools-discuss
old thread, but if you get a weird SWIG function failure, it's because `bestSolution.score` should be `bestSolution['score']`
Reply all
Reply to author
Forward
0 new messages