Changeset 2301


Ignore:
Timestamp:
Feb 9, 2010 9:14:26 PM (10 years ago)
Author:
jwatson
Message:

Performance improvements to PH obtained by processing scenario sub-problem results as they come in, instead of waiting for them after a solver barrier sync

File:
1 edited

Legend:

Unmodified
Added
Removed
  • coopr.pysp/trunk/coopr/pysp/ph.py

    r2249 r2301  
    10091009
    10101010      action_handles = []
    1011       action_handle_instance_map = {}
     1011      scenario_action_handle_map = {} # maps scenario names to action handles
     1012      action_handle_scenario_map = {} # maps action handles to scenario names
    10121013
    10131014      for scenario in self._scenario_tree._scenarios:
     
    10301031
    10311032         new_action_handle = self._solver_manager.queue(instance, opt=self._solver, tee=self._output_solver_log)
    1032          action_handle_instance_map[scenario._name] = new_action_handle
     1033         scenario_action_handle_map[scenario._name] = new_action_handle
     1034         action_handle_scenario_map[new_action_handle] = scenario._name
    10331035
    10341036         action_handles.append(new_action_handle)
    10351037
    1036       # STEP 2: barrier sync for all scenario sub-problem solves.
     1038      # STEP 2: loop for the solver results, reading them and loading
     1039      #         them into instances as they are available.
     1040
    10371041      if self._verbose is True:
    10381042         print "Waiting for scenario sub-problem solves"
    1039       self._solver_manager.wait_all(action_handles)
    1040       if self._verbose is True:     
    1041          print "Scenario sub-problem solves completed"     
    1042 
    1043       solve_end_time = time.time()
    1044       self._cumulative_solve_time += (solve_end_time - solve_start_time)
    1045 
    1046       if self._output_times is True:
    1047          print "Aggregate sub-problem solve time=%8.2f" % (solve_end_time - solve_start_time)
    1048 
    1049       # STEP 3: Load the results!
    1050       for scenario_name, action_handle in action_handle_instance_map.items():
    1051 
    1052          if self._verbose is True:         
    1053             print "Successfully processed results for scenario="+scenario_name
    1054 
    1055          instance = self._instances[scenario_name]
    1056          results = self._solver_manager.get_results(action_handle)
     1043
     1044      num_results_so_far = 0
     1045
     1046      while (num_results_so_far < len(self._scenario_tree._scenarios)):
     1047
     1048         action_handle = self._solver_manager.wait_any()
     1049         results = self._solver_manager.get_results(action_handle)         
     1050         scenario_name = action_handle_scenario_map[action_handle]
     1051         instance = self._instances[scenario_name]         
     1052
     1053         if self._verbose is True:
     1054            print "Results obtained for scenario="+scenario_name
    10571055
    10581056         if len(results.solution) == 0:
     
    10681066         end_time = time.time()
    10691067         if self._output_times is True:
    1070             print "Time loading results="+str(end_time-start_time)+" seconds"
     1068            print "Time loading results into instance="+str(end_time-start_time)+" seconds"
    10711069
    10721070         if self._verbose is True:                 
    10731071            print "Successfully loaded solution for scenario="+scenario_name
     1072
     1073         num_results_so_far = num_results_so_far + 1
     1074         
     1075      if self._verbose is True:     
     1076         print "Scenario sub-problem solves completed"     
     1077
     1078      solve_end_time = time.time()
     1079      self._cumulative_solve_time += (solve_end_time - solve_start_time)
     1080
     1081      if self._output_times is True:
     1082         print "Aggregate sub-problem solve time this iteration=%8.2f" % (solve_end_time - solve_start_time)
    10741083
    10751084      if self._verbose is True:
     
    13521361   def iteration_k_solve(self):
    13531362
    1354      if self._verbose is True:
    1355         print "------------------------------------------------"       
    1356         print "Starting PH iteration " + str(self._current_iteration) + " solves"
    1357 
    1358      # cache the objective values generated by PH for output at the end of this function.
    1359      ph_objective_values = {}
    1360 
    1361      solve_start_time = time.time()
    1362 
    1363      # STEP 0: set up all global solver options.
    1364      self._solver.mipgap = self._mipgap     
    1365 
    1366      # STEP 1: queue up the solves for all scenario sub-problems and
    1367      #         grab all of the action handles for the subsequent barrier sync.
    1368 
    1369      action_handles = []
    1370      action_handle_instance_map = {}
    1371 
    1372      for scenario in self._scenario_tree._scenarios:     
    1373 
    1374         instance = self._instances[scenario._name]
    1375 
    1376         if self._verbose is True:
    1377            print "Queuing solve for scenario=" + scenario._name
    1378 
    1379         # IMPT: You have to re-presolve, as the simple presolver collects the linear terms together. If you
    1380         # don't do this, you won't see any chance in the output files as you vary the problem parameters!
    1381         # ditto for instance fixing!
    1382         instance.presolve()
    1383 
    1384         # once past iteration 0, there is always a feasible solution from which to warm-start.
    1385         # however, you might want to disable warm-start when the solver is behaving badly (which does happen).
    1386         new_action_handle = None
    1387         if (self._disable_warmstarts is False) and (self._solver.warm_start_capable() is True):
    1388            new_action_handle = self._solver_manager.queue(instance, opt=self._solver, warmstart=True, tee=self._output_solver_log)
    1389         else:
    1390            new_action_handle = self._solver_manager.queue(instance, opt=self._solver, tee=self._output_solver_log)           
    1391 
    1392         action_handle_instance_map[scenario._name] = new_action_handle
    1393 
    1394         action_handles.append(new_action_handle)
    1395 
    1396      # STEP 2: barrier sync for all scenario sub-problem solves.
    1397      if self._verbose is True:           
    1398         print "Waiting for scenario sub-problem solves"
    1399      self._solver_manager.wait_all(action_handles)
    1400      if self._verbose is True:               
    1401         print "Scenario sub-problem solves completed"
    1402        
    1403      solve_end_time = time.time()
    1404      self._cumulative_solve_time += (solve_end_time - solve_start_time)
    1405 
    1406      if self._output_times is True:
    1407         print "Aggregate sub-problem solve time=%8.2f" % (solve_end_time - solve_start_time)
    1408 
    1409      # STEP 3: Load the results!
    1410      for scenario_name, action_handle in action_handle_instance_map.items():
    1411 
    1412         if self._verbose is True:         
    1413            print "Successfully processed results for scenario="+scenario_name
    1414 
    1415         instance = self._instances[scenario_name]
    1416         results = self._solver_manager.get_results(action_handle)
    1417 
    1418         if len(results.solution) == 0:
    1419            results.write()
    1420            raise RuntimeError, "Solve failed for scenario="+scenario_name+"; no solutions generated"
    1421 
    1422         if self._output_solver_results is True:
    1423            print "Results for scenario=", scenario_name
    1424            results.write(num=1)           
    1425 
    1426         start_time = time.time()
    1427         instance.load(results)
    1428         end_time = time.time()
    1429 
    1430         if self._output_times is True:
    1431            print "Time loading results="+str(end_time-start_time)+" seconds"       
    1432 
    1433         if self._verbose is True:                 
    1434            print "Successfully loaded solution for scenario="+scenario_name
    1435 
    1436         # we're assuming there is a single solution.
    1437         # the "value" attribute is a pre-defined feature of any solution - it is relative to whatever
    1438         # objective was selected during optimization, which of course should be the PH objective.
    1439         ph_objective_values[instance.name] = float(results.solution(0).objective['f'].value)
    1440 
    1441      if self._verbose is True:
    1442         print "Successfully completed PH iteration " + str(self._current_iteration) + " solves - solution statistics:"
    1443         print "  Scenario             PH Objective             Cost Objective"
    1444         for scenario in self._scenario_tree._scenarios:
    1445            instance = self._instances[scenario._name]
    1446            for objective_name in instance.active_components(Objective):
    1447               objective = instance.active_components(Objective)[objective_name]
    1448               print "%20s       %18.4f     %14.4f" % (scenario._name, ph_objective_values[scenario._name], 0.0)
     1363      if self._verbose is True:
     1364         print "------------------------------------------------"       
     1365         print "Starting PH iteration " + str(self._current_iteration) + " solves"
     1366
     1367      # cache the objective values generated by PH for output at the end of this function.
     1368      ph_objective_values = {}
     1369
     1370      solve_start_time = time.time()
     1371
     1372      # STEP 0: set up all global solver options.
     1373      self._solver.mipgap = self._mipgap     
     1374
     1375      # STEP 1: queue up the solves for all scenario sub-problems and
     1376      #         grab all of the action handles for the subsequent barrier sync.
     1377
     1378      action_handles = []
     1379      scenario_action_handle_map = {} # maps scenario names to action handles
     1380      action_handle_scenario_map = {} # maps action handles to scenario names
     1381
     1382      for scenario in self._scenario_tree._scenarios:     
     1383
     1384         instance = self._instances[scenario._name]
     1385
     1386         if self._verbose is True:
     1387            print "Queuing solve for scenario=" + scenario._name
     1388
     1389         # IMPT: You have to re-presolve, as the simple presolver collects the linear terms together. If you
     1390         # don't do this, you won't see any chance in the output files as you vary the problem parameters!
     1391         # ditto for instance fixing!
     1392         instance.presolve()
     1393
     1394         # once past iteration 0, there is always a feasible solution from which to warm-start.
     1395         # however, you might want to disable warm-start when the solver is behaving badly (which does happen).
     1396         new_action_handle = None
     1397         if (self._disable_warmstarts is False) and (self._solver.warm_start_capable() is True):
     1398            new_action_handle = self._solver_manager.queue(instance, opt=self._solver, warmstart=True, tee=self._output_solver_log)
     1399         else:
     1400            new_action_handle = self._solver_manager.queue(instance, opt=self._solver, tee=self._output_solver_log)           
     1401
     1402         scenario_action_handle_map[scenario._name] = new_action_handle
     1403         action_handle_scenario_map[new_action_handle] = scenario._name         
     1404
     1405         action_handles.append(new_action_handle)
     1406
     1407      # STEP 2: loop for the solver results, reading them and loading
     1408      #         them into instances as they are available.
     1409      if self._verbose is True:
     1410         print "Waiting for scenario sub-problem solves"
     1411
     1412      num_results_so_far = 0
     1413
     1414      while (num_results_so_far < len(self._scenario_tree._scenarios)):
     1415
     1416         action_handle = self._solver_manager.wait_any()
     1417         results = self._solver_manager.get_results(action_handle)         
     1418         scenario_name = action_handle_scenario_map[action_handle]
     1419         instance = self._instances[scenario_name]         
     1420
     1421         if self._verbose is True:
     1422            print "Results obtained for scenario="+scenario_name
     1423
     1424         if len(results.solution) == 0:
     1425            results.write(num=1)
     1426            raise RuntimeError, "Solve failed for scenario="+scenario_name+"; no solutions generated"
     1427
     1428         if self._output_solver_results is True:
     1429            print "Results for scenario=",scenario_name
     1430            results.write(num=1)
     1431
     1432         start_time = time.time()
     1433         instance.load(results)
     1434         end_time = time.time()
     1435         if self._output_times is True:
     1436            print "Time loading results into instance="+str(end_time-start_time)+" seconds"
     1437
     1438         if self._verbose is True:                 
     1439            print "Successfully loaded solution for scenario="+scenario_name
     1440
     1441         # we're assuming there is a single solution.
     1442         # the "value" attribute is a pre-defined feature of any solution - it is relative to whatever
     1443         # objective was selected during optimization, which of course should be the PH objective.
     1444         ph_objective_values[instance.name] = float(results.solution(0).objective['f'].value)
     1445
     1446         num_results_so_far = num_results_so_far + 1
     1447         
     1448      if self._verbose is True:     
     1449         print "Scenario sub-problem solves completed"     
     1450
     1451      solve_end_time = time.time()
     1452      self._cumulative_solve_time += (solve_end_time - solve_start_time)
     1453
     1454      if self._output_times is True:
     1455         print "Aggregate sub-problem solve time this iteration=%8.2f" % (solve_end_time - solve_start_time)
     1456
     1457      if self._verbose is True:
     1458         print "Successfully completed PH iteration " + str(self._current_iteration) + " solves - solution statistics:"
     1459         print "  Scenario             PH Objective             Cost Objective"
     1460         for scenario in self._scenario_tree._scenarios:
     1461            instance = self._instances[scenario._name]
     1462            for objective_name in instance.active_components(Objective):
     1463               objective = instance.active_components(Objective)[objective_name]
     1464               print "%20s       %18.4f     %14.4f" % (scenario._name, ph_objective_values[scenario._name], 0.0)
    14491465
    14501466   def solve(self):
Note: See TracChangeset for help on using the changeset viewer.