Freigeben über


Controlling Simplex and IPM termination conditions

On our MSDN message board there was a question about how to control when the SimplexSolver aborts.  You can do this by providing an abort callback to the params object sent to the solver.  For example, to terminate after 100ms:

     private static void PetrochemLinearModel() {
      SimplexSolver solver = new SimplexSolver();
      int sa, vz;
      solver.AddVariable("SA", out sa);
      solver.SetBounds(sa, 0, 9000);
      solver.AddVariable("VZ", out vz);
      solver.SetBounds(vz, 0, 6000);

      int goal;
      solver.AddRow("goal", out goal);
      solver.AddGoal(goal, 0, true);
      solver.SetCoefficient(goal, sa, 20);
      solver.SetCoefficient(goal, vz, 15);

      int demand1, demand2, demand3;
      solver.AddRow("demand1", out demand1);
      solver.SetCoefficient(demand1, sa, 0.3);
      solver.SetCoefficient(demand1, vz, 0.4);
      solver.SetLowerBound(demand1, 1126);

      solver.AddRow("demand2", out demand2);
      solver.SetCoefficient(demand2, sa, 0.4);
      solver.SetCoefficient(demand2, vz, 0.2);
      solver.SetLowerBound(demand2, 1500);

      solver.AddRow("demand3", out demand3);
      solver.SetCoefficient(demand3, sa, 0.2);
      solver.SetCoefficient(demand3, vz, 0.3);
      solver.SetLowerBound(demand3, 500);

      Stopwatch s = new Stopwatch();
      var param = new SimplexSolverParams(() => s.ElapsedMilliseconds > 100);
      s.Start();
      var solution = solver.Solve(param);
      Console.WriteLine(solution.LpResult);
      Console.WriteLine("goal = " + solution.GetValue(goal).ToDouble());
      Console.WriteLine("sa   = " + solution.GetValue(sa).ToDouble());
      Console.WriteLine("vz   = " + solution.GetValue(vz).ToDouble());
    }

If you are using the InteriorPointSolver, the callback can reference solver properties (including iteration count and duality gap) to do more sophisticated stuff.  For example:

       var param = new InteriorPointSolverParams();
      param.IterationStartedCallback = () => {
        Console.WriteLine("{0}\t{1:f6} {2:e6}", solver.IterationCount, solver.Primal, solver.Gap.ToDouble());
        return false;
      };
      var solution = solver.Solve(param);