<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Nathan Brixius : INFORMS</title><link>http://blogs.msdn.com/natbr/archive/tags/INFORMS/default.aspx</link><description>Tags: INFORMS</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Solver Foundation TSP Part II: Directives, Solver Plugins, Model Libraries</title><link>http://blogs.msdn.com/natbr/archive/2009/05/07/solver-foundation-tsp-part-ii-directives-solver-plugins-model-libraries.aspx</link><pubDate>Fri, 08 May 2009 06:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9595777</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9595777.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9595777</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9595777</wfw:comment><description>Here is my as-promised "part 2" to my &lt;A href="http://blogs.msdn.com/natbr/archive/2009/04/27/solving-traveling-salesman-problems-using-solver-foundation.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/04/27/solving-traveling-salesman-problems-using-solver-foundation.aspx"&gt;traveling salesman sample&lt;/A&gt;. My goal is not to try and do any "production level" modeling, but instead "point the way" by highlighting different aspects of Solver Foundation's architecture. This time I want to talk about &lt;STRONG&gt;directives&lt;/STRONG&gt;, &lt;STRONG&gt;plug-in solvers&lt;/STRONG&gt;, and &lt;STRONG&gt;model reusability&lt;/STRONG&gt;. The Solver Foundation architecture provides the ability to plug-in other solvers to handle one or more problem types. As of version 1.1, the Gurobi solver is Solver Foundation's default MIP (mixed integer programming)&amp;nbsp;solver. &lt;A href="http://www.gurobi.com/" mce_href="http://www.gurobi.com"&gt;Gurobi&lt;/A&gt; is a high-performance solver which is capable of taking on industrial strength problems, so my piddling little TSP example is no match for it. Gurobi has a number of parameters that can be set to tune solver performance - you set them by means of Directives. First, let's modify our code to turn on logging. Change the context.Solve() call to: &lt;PRE&gt;      GurobiDirective gurobiDirective = new GurobiDirective();
      gurobiDirective.OutputFlag = true;
      Solution solution = context.Solve(gurobiDirective);
&lt;/PRE&gt;Each plug-in solver also defines its own directives - therefore the full power and flexibility of plug-in solvers are available to you as a programmer. In this case I have just flipped on the logging bit - here's what I see. &lt;PRE&gt;Optimize a model with 185 Rows, 380 Columns and 1199 NonZeroes
Presolve removed 1 rows and 185 columns
Presolve time: 0.30s
Presolved: 184 Rows, 195 Columns, 832 Nonzeros
Objective GCD is 1

Root relaxation: objective 2.783286e+03, 36 iterations, 0.02 seconds

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

     0     0  2783.2857    0   14          -  2783.2857     -      -    0s
     0     0  3006.1964    0   29          -  3006.1964     -      -    0s
     0     0  3006.1964    0   29          -  3006.1964     -      -    0s
     0     0  3006.1964    0   25          -  3006.1964     -      -    0s
     0     0  3006.1964    0   25          -  3006.1964     -      -    0s
H    0     0                       6029.0000  3006.1964  50.1%     -    0s
     0     0  3006.1964    0   25  6029.0000  3006.1964  50.1%     -    0s
H    0     2                       3805.0000  3006.1964  21.0%     -    0s
     0     2  3006.1964    0   25  3805.0000  3006.1964  21.0%     -    0s
*   75    54              29       3644.0000  3077.0000  15.6%   8.2    0s
*  129    80              27       3381.0000  3077.0000  8.99%   8.7    0s
*  158    62              30       3323.0000  3077.0000  7.40%   8.1    0s

Cutting planes:
  Learned: 3
  Gomory: 1
  MIR: 3

Explored 1231 nodes (5693 simplex iterations) in 0.69 seconds
Thread count was 2 (of 2 available processors)

Optimal solution found (tolerance 1.00e-04)
Best objective 3.3230000000e+03, best bound 3.3230000000e+03, gap 0.0000%
&lt;/PRE&gt;For large models it is sometimes useful to tweak the solver options for performance. For example, if I wanted to spend a slightly larger amount of time doing MIP heuristics, and I wanted to eliminate presolve, then I can set those options easily: &lt;PRE&gt;      gurobiDirective.Heuristics = 0.1;
      gurobiDirective.Presolve = PresolveLevel.None;
&lt;/PRE&gt;
&lt;P&gt;There is a full reference in the Gurobi Solver Programming Primer that ships with Solver Foundation. My point is that you do not get a "least common denominator" solution - you get all the bells and whistles. &lt;/P&gt;
&lt;P&gt;Gurobi is just one example - there are a wide range of plug-ins available, covering most of the popular LP and MIP solvers - check out &lt;A href="http://www.solverfoundation.com/" mce_href="http://www.solverfoundation.com"&gt;solverfoundation.com&lt;/A&gt; for the full list. To use a plug-in solver, you need to: 1) install the solver (duh), 2) change your exe.config or web.config to point to the solver. No code changes are required. You can find additional documentation on the default MIP directives and the third-party Solver configuration in the SFS Programming Primer. &lt;/P&gt;
&lt;P&gt;Last thing - modern programming languages like C# are cool because they promote reusability and maintainability. Don't forget about that when you are writing SFS code. It's common for models in a particular vertical (say, finance or transportation) to have common "blocks" of goals or constraints that are re-used over and over again. It's pretty easy to build reusable model libraries using extension methods. For example, take the assignment constraints in my TSP example. I could factor them out: &lt;/P&gt;&lt;PRE&gt;  public static class ModelingExtensions {
    public static void AssignmentConstraintsNoDiag(this Model model, Set s, Decision assign) {
      model.AddConstraint("A1", Model.ForEach(s, i =&amp;gt; Model.Sum(Model.ForEachWhere(s, j =&amp;gt; assign[i, j], j =&amp;gt; i != j)) == 1));
      model.AddConstraint("A2", Model.ForEach(s, j =&amp;gt; Model.Sum(Model.ForEachWhere(s, i =&amp;gt; assign[i, j], i =&amp;gt; i != j)) == 1));
    }
  }
&lt;/PRE&gt;Now I can just say model.AssignmentConstraintsNoDiag(city, assign). I could add other variations inside of ModelingExtensions as well. I think this aspect of Solver Foundation has not gotten enough attention - maybe because it doesn't make for a cool demo! &lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9595777" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/natbr/archive/tags/combinatorial+optimization/default.aspx">combinatorial optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/INFORMS/default.aspx">INFORMS</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Gurobi/default.aspx">Gurobi</category></item><item><title>Solving traveling salesman problems using Solver Foundation</title><link>http://blogs.msdn.com/natbr/archive/2009/04/27/solving-traveling-salesman-problems-using-solver-foundation.aspx</link><pubDate>Mon, 27 Apr 2009 18:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9571061</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9571061.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9571061</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9571061</wfw:comment><description>&lt;P&gt;Here's an example that I walked through during yesterday's INFORMS session.&amp;nbsp; Erwin has &lt;A href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/03/tsp-in-oml-ms-solver-foundation.html" mce_href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/03/tsp-in-oml-ms-solver-foundation.html"&gt;two&lt;/A&gt; &lt;A href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/02/tsp-powerset-formulation.html" mce_href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/02/tsp-powerset-formulation.html"&gt;blog postings&lt;/A&gt; about Solver Foundation and the traveling salesman problem, but I want to throw in my two cents because I want to emphasize a couple of points:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;By combining C# and Solver Foundation Services it is possible to express complex models clearly and succinctly.&lt;/LI&gt;
&lt;LI&gt;It is very easy to build powerful, reusable model libraries using C# and Solver Foundation Services.&lt;/LI&gt;
&lt;LI&gt;Solver Foundation Services code can be used in many different application environments (ASP.Net, silverlight, DB, command line apps, WPF, …) with minimal changes.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The traveling salesman problem is a classical problem in computer science, and you should bow your head in shame if you don't know about it (and turn in your conference badge if you happen to be in Phoenix).&amp;nbsp; A salesperson needs to make a tour of a number of cities.&amp;nbsp; The restrictions are that she wants to visit each city once and only once, and she wants to minimize the distance travelled.&amp;nbsp; This is perhaps &lt;STRONG&gt;the&lt;/STRONG&gt; definitive example of an NP-hard problem.&lt;/P&gt;
&lt;P&gt;TSP can be solved using mixed integer programming - optimizing a linear goal with linear constraints, where some of the decision variables are integer.&amp;nbsp; In this first post I will show how to formulate and solve a TSP model using Solver Foundation Services.&amp;nbsp; In my second post I will show how to use the Gurobi MIP solver using SFS.&amp;nbsp;&amp;nbsp; There are many different ways to model the TSP - &lt;A href="http://archive.ite.journal.informs.org/Vol7No1/LeeRaffensperger/" mce_href="http://archive.ite.journal.informs.org/Vol7No1/LeeRaffensperger/"&gt;here&lt;/A&gt; is a nice introduction.&amp;nbsp; My goal is to provide a clear, complete example - not build a "production level" TSP model, so I am going to choose a model formulation that dates back to 1960!&amp;nbsp; First, I need to establish a couple of building blocks that will help me construct the data for the model.&amp;nbsp; We need to know the distances between each pair of cities.&amp;nbsp; Typically we are provided the coordinates of the cities and need to derive the distances.&amp;nbsp; So I will introduce a Coordinate class that contains properties for the (x, y) coordinates, and properties to convert to latitude and longitude.&amp;nbsp; Finally, a method that computes the distance between points.&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SolverFoundation.Services;
using SolverFoundation.Plugin.Gurobi;

namespace Microsoft.SolverFoundation.Samples.TravelingSalesman {
  class Program {
    // TSP coordinate.
    public class Coordinate {
      public int Name { get; set; }

      // X-coordinate (from TSPLIB)
      public double X { get; set; }

      // Y-coordinate (from TSPLIB)
      public double Y { get; set; }

      public Coordinate(int name, double x, double y) {
        Name = name;
        X = x;
        Y = y;
      }

      // Latitude in radians.
      public double Latitude {
        get { return Math.PI * (Math.Truncate(X) + 5 * (X - Math.Truncate(X)) / 3) / 180; }
      }

      // Longitude in radians.
      public double Longitude {
        get { return Math.PI * (Math.Truncate(Y) + 5 * (Y - Math.Truncate(Y)) / 3) / 180; }
      }

      // Geographic distance between two points (as an integer).
      public int Distance(Coordinate p) {
        double q1 = Math.Cos(Longitude - p.Longitude);
        double q2 = Math.Cos(Latitude - p.Latitude);
        double q3 = Math.Cos(Latitude + p.Latitude);
        // There may rounding difficulties her if the points are close together...just sayin'.
        return (int)(6378.388 * Math.Acos(0.5 * ((1 + q1) * q2 - (1 - q1) * q3)) + 1);
      }
    }

    // TSP city-city arc.
    // &lt;/SUMMARY&gt;
    public class Arc {
      public int City1 { get; set; }
      public int City2 { get; set; }
      public double Distance { get; set; }
    }

    // Burma14 from TSPLIB. Optimal tour = 3323.
    private static Coordinate[] data = new Coordinate[] {
      new Coordinate(0, 16.47, 96.10),
      new Coordinate(1, 16.47, 94.44),
      new Coordinate(2, 20.09, 92.54),
      new Coordinate(3, 22.39, 93.37),
      new Coordinate(4, 25.23, 97.24),
      new Coordinate(5, 22.00, 96.05),
      new Coordinate(6, 20.47, 97.02),
      new Coordinate(7, 17.20, 96.29),
      new Coordinate(8, 16.30, 97.38),
      new Coordinate(9, 14.05, 98.12),
      new Coordinate(10, 16.53, 97.38),
      new Coordinate(11, 21.52, 95.59),
      new Coordinate(12, 19.41, 97.13),
      new Coordinate(13, 20.09, 94.55)
    };
&lt;/PRE&gt;
&lt;P&gt;(The data for this 14-city problem comes from the &lt;A href="http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/" mce_href="http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/"&gt;TSPLIB&lt;/A&gt; library). If you've been following my blog you know that the building blocks of a Solver Foundation model are: sets, parameters, decisions, goals, and constraints. I am going to implement a simple formulation that is centered around&amp;nbsp;the following (indexed) decisions:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Assign[i,j]: this is equal to 1 if the optimal tour contains a trip (or arc) from city i to city j.&lt;/LI&gt;
&lt;LI&gt;Rank[i]: this is equal to the number of cities visited after arriving at city i.&amp;nbsp;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;We have one parameter in our model:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Distance[I,j]: the distance from city i to city j.&amp;nbsp;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;With that in mind, here's the model.&amp;nbsp; Explanation of the goals and constraints follow.&lt;/P&gt;&lt;PRE&gt;    static void Main(string[] args) {
      SolverContext context = SolverContext.GetContext();
      Model model = context.CreateModel();

      // ------------
      // Parameters
      Set city = new Set(Domain.IntegerNonnegative, "city");
      Parameter dist = new Parameter(Domain.Real, "dist", city, city);
      var arcs = from p1 in data
                 from p2 in data
                 select new Arc { City1 = p1.Name, City2 = p2.Name, Distance = p1.Distance(p2) };
      dist.SetBinding(arcs, "Distance", "City1", "City2");
      model.AddParameters(dist);

      // ------------
      // Decisions
      Decision assign = new Decision(Domain.IntegerRange(0, 1), "assign", city, city);
      Decision rank = new Decision(Domain.RealNonnegative, "rank", city);
      model.AddDecisions(assign, rank);

      // ------------
      // Goal: minimize the length of the tour.
      Goal goal = model.AddGoal("TourLength", GoalKind.Minimize,
        Model.Sum(Model.ForEach(city, i =&amp;gt; Model.ForEachWhere(city, j =&amp;gt; dist[i, j] * assign[i, j], j =&amp;gt; i != j))));

      // ------------
      // Enter and leave each city only once.
      int N = data.Length;
      model.AddConstraint("assign 1",
        Model.ForEach(city, i =&amp;gt; Model.Sum(Model.ForEachWhere(city, j =&amp;gt; assign[i, j],
          j =&amp;gt; i != j)) == 1));
      model.AddConstraint("assign 2",
        Model.ForEach(city, j =&amp;gt; Model.Sum(Model.ForEachWhere(city, i =&amp;gt; assign[i, j], i =&amp;gt; i != j)) == 1));
      model.AssignmentNoDiag(city, assign);

      // Forbid subtours (Miller, Tucker, Zemlin - 1960...)
      model.AddConstraint("no subtours",
        Model.ForEach(city,
          i =&amp;gt; Model.ForEachWhere(city,
            j =&amp;gt; rank[i] + 1 &amp;lt;= rank[j] + N * (1 - assign[i, j]),
            j =&amp;gt; Model.And(i != j, i &amp;gt;= 1, j &amp;gt;= 1)
          )
        )
      );

      Solution solution = context.Solve();

      // Retrieve solution information.
      Console.WriteLine("Cost = {0}", goal.ToDouble());
      Console.WriteLine("Tour:");
      var tour = from p in assign.GetValues() where (double)p[0] &amp;gt; 0.9 select p[2];
      foreach (var i in tour.ToArray()) {
        Console.Write(i + " -&amp;gt; ");
      }
      Console.WriteLine();
    }
  }
&lt;/PRE&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;In my humble opinion, the "Parameter data =" line is an awesome example of the power of LINQ data binding in Solver Foundation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We generate the 2D matrix of distances using a single LINQ expression.  It would be incredibly easy to change the code to retrieve the coordinate data from a database (perhaps using a LINQ expression once again), a file, or even a user application.&lt;/PRE&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&amp;nbsp;&lt;/PRE&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;The goal is straightforward: minimize the distance traveled.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a product of the selected arcs and the distance matrix.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;We have two types of constraints:&lt;/PRE&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;SPAN style="FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;Assignment constraints: these ensure that we enter and leave each city only once.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;SPAN style="FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;Subtour constraints: these ensure that we do not have any subtours.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a four city problem {A, B, C, D}, for example, we cannot have two cycles (A, B), (C, D).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We need to have one tour that contains all the cities.&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;The assignment constraints are easy using the ForEach and ForEachWhere operations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I use ForEachWhere because I want to disallow arcs that enter and leave the same city - that doesn't make sense.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The subtour constraint is a little more complicated.   It relates the "assign" and "rank" decisions.  The key fact is that if there is an arc from city i to city j, rank[i] + 1 == j.  Of course, if the (i, j) arc is not part of the optimal tour then all bets are off.   Last note: notice that I can mix parameters, decisions, and C# variables in my expressions. &lt;/PRE&gt;&lt;PRE style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt; &lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;Once we solve the model we want to print out the cost, and the optimal tour.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Getting the cost is very easy using goal.ToDouble().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We can get the tour using either Assign or Rank.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I have chosen to use Assign because it gives me another opportunity to use LINQ.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you call GetValues() on a decision, you get arrays that contain the value along with the indexes for each decision.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, the last entry in the array is the one we are interested in.  There are other ways to conveniently query decsision results, I'll save that for another time.&lt;/P&gt;&lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;The next post will show how we can use Solver Foundation's plug-in model to tune the behavior of the Gurobi MIP solver.&lt;/P&gt; &lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9571061" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/natbr/archive/tags/combinatorial+optimization/default.aspx">combinatorial optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.msdn.com/natbr/archive/tags/INFORMS/default.aspx">INFORMS</category></item><item><title>Modeling a production planning problem using Solver Foundation</title><link>http://blogs.msdn.com/natbr/archive/2009/04/24/modeling-a-production-planning-problem-using-solver-foundation.aspx</link><pubDate>Fri, 24 Apr 2009 23:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9567262</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9567262.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9567262</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9567262</wfw:comment><description>&lt;P&gt;In this post I am going to present two complete C# programs for modeling and solving a simple production problem using Solver Foundation. In this example we have two refineries (located in Saudi Arabia and Venzuela) that produce three products: gasoline, jet fuel, and lubricant. The goal is to minimize production costs, which depend on location. There is demand for each product which must be met. Finally, each production site has a limited production capacity. &lt;/P&gt;
&lt;P&gt;The code for the simple case&amp;nbsp;is below.&amp;nbsp;&amp;nbsp;Creating&amp;nbsp;a model amounts to adding the goals, decisions, and constraints using the appropriate Add method.&amp;nbsp; The signature for each is similar: the first argument is the name and the second argument is a term.&amp;nbsp; Terms are created by combining decisions or parameters using the usual operators, or by using static methods on the Model class (as we will see in our second example).&amp;nbsp; Finally, notice the call to SolverContext.Solve().&amp;nbsp; I have supplied a Directive that specifies that the Simplex solver should be used.&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Microsoft.SolverFoundation.Services;

namespace Microsoft.SolverFoundation.Samples.Petrochem {
  class Program {
    static void Main(string[] args) {
      PetrochemSimple();
    }

    private static void PetrochemSimple() {
      SolverContext context = SolverContext.GetContext();
      context.ClearModel();
      Model model = context.CreateModel();

      Decision sa = new Decision(Domain.RealRange(0, 9000), "SA");
      Decision vz = new Decision(Domain.RealRange(0, 6000), "VZ");
      model.AddDecisions(sa, vz);

      model.AddGoal("goal", GoalKind.Minimize, 20 * sa + 15 * vz);

      model.AddConstraint("demand1", 0.3 * sa + 0.4 * vz &amp;gt;= 1900);
      model.AddConstraint("demand2", 0.4 * sa + 0.2 * vz &amp;gt;= 1500);
      model.AddConstraint("demand3", 0.2 * sa + 0.3 * vz &amp;gt;= 500);

      Solution solution = context.Solve(new SimplexDirective());
      Report report = solution.GetReport();
      Console.WriteLine(report);
    }
  }
&lt;/PRE&gt;
&lt;P&gt;Now let's reimplement the same example using data binding. Data binding is a powerful mechanism for creating large, maintainable models. Notice that in my first example, the numeric data such as the yields, the demands, and capacities were expressed directly in the terms. The first step in using Solver Foundation data binding is to lift these values into Parameters. It is often useful to create indexed parameters using Sets. In this example, there are two clearly defined Sets: the set of countries, and the set of products. In my example below I create a DataSet which contains the data for each of my parameters. (The GetData() method is just an example, it's not pretty but it is needed to complete the example.) Then I create a series of indexed parameters. For each of them I call the SetBinding method to associate the data with the parameter. In addition to the data, SetBinding also requires the caller to indicate which property specifies the values for the parameter. If the parameter is indexed, I also need to specify the parameters of the index properties. Since I am working with DataTables, these are simply column names. Notice that I could swap in any other data source that is enumerable - in particular LINQ works really well with Solver Foundation parameters. &lt;/P&gt;
&lt;P&gt;After the parameters are created, I define the decisions, goals, and constraints. Notice that there is only one decision - it is indexed. The Model.Sum and Model.Foreach operations allow me to define a series of constraints over one or more indexed sets in one single statement. This means that if I were to add more countries or products, my model definition would not change at all. &lt;/P&gt;&lt;PRE&gt;    private static void PetrochemDataBinding() {
      SolverContext context = SolverContext.GetContext();
      context.ClearModel(); 
      Model model = context.CreateModel();

      // Retrieve the problem data.
      DataSet data = GetData();

      Set products = new Set(Domain.Any, "products");
      Set countries = new Set(Domain.Any, "countries");
      
      Parameter demand = new Parameter(Domain.Real, "demand", products);
      demand.SetBinding(data.Tables["Demand"].AsEnumerable(), "Demand", "Product");

      Parameter yield = new Parameter(Domain.Real, "yield", products, countries);
      yield.SetBinding(data.Tables["Yield"].AsEnumerable(), "Yield", "Product", "Country");

      Parameter limit = new Parameter(Domain.Real, "limit", countries);
      limit.SetBinding(data.Tables["Limit"].AsEnumerable(), "Limit", "Country");

      Parameter cost = new Parameter(Domain.Real, "cost", countries);
      cost.SetBinding(data.Tables["Cost"].AsEnumerable(), "Cost", "Country");

      model.AddParameters(demand, yield, limit, cost);

      Decision produce = new Decision(Domain.RealNonnegative, "produce", countries);
      model.AddDecision(produce);

      model.AddGoal("goal", GoalKind.Minimize, Model.Sum(Model.ForEach(countries, c =&amp;gt; cost[c] * produce[c])));

      model.AddConstraint("Demand", 
        Model.ForEach(products, p =&amp;gt; Model.Sum(Model.ForEach(countries, c =&amp;gt; yield[p, c] * produce[c])) &amp;gt;= demand[p])
        );

      model.AddConstraint("Production limit",
        Model.ForEach(countries, c =&amp;gt; produce[c] &amp;lt;= limit[c])
        );

      Solution solution = context.Solve(new SimplexDirective());
      Report report = solution.GetReport();
      Console.WriteLine(report);
    }

    private static DataSet GetData() {
      string[] products = new string[] { "Gas", "Jet Fuel", "Lubricant" };
      string[] countries = new string[] { "SA", "VZ" };

      double[][] yield = new double[][] {
        new double[] { 0.3, 0.4 }, 
        new double[] { 0.4, 0.2 }, 
        new double[] { 0.2, 0.3 } 
      };
      double[] demand = new double[] { 1900, 1500, 500 };
      double[] limit = new double[] { 9000, 6000 };
      double[] cost = new double[] { 20, 15 };

      DataSet dataSet = new DataSet();
      #region Fill DataSet
      DataTable table = new DataTable("Yield");
      dataSet.Tables.Add(table);
      table.Columns.Add("Product", typeof(string));
      table.Columns.Add("Country", typeof(string));
      table.Columns.Add("Yield", typeof(double));

      for (int p = 0; p &amp;lt; products.Length; p++) {
        for (int c = 0; c &amp;lt; countries.Length; c++) {
          DataRow row = table.NewRow();
          row[0] = products[p];
          row[1] = countries[c];
          row[2] = yield[p][c];
          table.Rows.Add(row);
        }
      }

      table = new DataTable("Demand");
      dataSet.Tables.Add(table);
      table.Columns.Add("Product", typeof(string));
      table.Columns.Add("Demand", typeof(double));
      for (int p = 0; p &amp;lt; products.Length; p++) {
        DataRow row = table.NewRow();
        row[0] = products[p];
        row[1] = demand[p];
        table.Rows.Add(row);
      }

      table = new DataTable("Limit");
      dataSet.Tables.Add(table);
      table.Columns.Add("Country", typeof(string));
      table.Columns.Add("Limit", typeof(double));
      for (int c = 0; c &amp;lt; countries.Length; c++) {
        DataRow row = table.NewRow();
        row[0] = countries[c];
        row[1] = limit[c];
        table.Rows.Add(row);
      }

      table = new DataTable("Cost");
      dataSet.Tables.Add(table);
      table.Columns.Add("Country", typeof(string));
      table.Columns.Add("Cost", typeof(double));
      for (int c = 0; c &amp;lt; countries.Length; c++) {
        DataRow row = table.NewRow();
        row[0] = countries[c];
        row[1] = cost[c];
        table.Rows.Add(row);
      }
      #endregion

      return dataSet;
    }
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9567262" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/INFORMS/default.aspx">INFORMS</category></item><item><title>Solver Foundation at INFORMS Practice Conference</title><link>http://blogs.msdn.com/natbr/archive/2009/04/22/solver-foundation-at-informs-practice-conference.aspx</link><pubDate>Thu, 23 Apr 2009 00:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9563281</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9563281.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9563281</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9563281</wfw:comment><description>&lt;P&gt;A few of us on the Solver Foundation team will be presenting at the&lt;A href="http://meetings.informs.org/Practice09/" mce_href="http://meetings.informs.org/Practice09/"&gt; INFORMS Practice Conference&lt;/A&gt; in Phoenix, Arizona.&amp;nbsp; I'm looking forward to it!&amp;nbsp; We have both a workshop and a session - I will also be participating in Gurobi's session to show off its integration with Solver Foundation.&amp;nbsp; Here are the details - looking forward to seeing you there.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://meetings.informs.org/Practice09/technology.html" mce_href="http://meetings.informs.org/Practice09/technology.html"&gt;Technology Workshop&lt;/A&gt;&lt;BR&gt;Sunday, April 26, 9AM - 12PM&lt;BR&gt;Microsoft Solver Foundation is a pure, managed code runtime for mathematical programming, modeling, and optimization. Microsoft Solver Foundation provides solvers and services to a broad community of users: from Excel users and analysts to programmers working on business critical scheduling, configuration, risk management and planning solutions. It provides services for model validation, parallel solving and workload scheduling, model interchange, and declarative data binding via LINQ and other NETFx technologies. As an open framework designed for third party extensibility, it exposes facilities for users to plug-in their own solvers while still leveraging all of the modeling services and capabilities of Microsoft Solver Foundation. &lt;/P&gt;
&lt;P&gt;&lt;A href="http://meetings.informs.org/Practice09/software_tutorials.html" mce_href="http://meetings.informs.org/Practice09/software_tutorials.html"&gt;Software Tutorials&lt;BR&gt;&lt;/A&gt;Monday, April 27, 9:10AM - 10:00AM&lt;BR&gt;Solver Foundation is a framework and managed code runtime for mathematical programming, modeling and optimization. This tutorial will focus on the technical overview of Solver Foundation, and how Third-party solver vendors, modelers and solution specialists can leverage Solver Foundation from all CLS-compliant languages and Microsoft Office.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9563281" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/OML/default.aspx">OML</category><category domain="http://blogs.msdn.com/natbr/archive/tags/INFORMS/default.aspx">INFORMS</category></item></channel></rss>