<?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 : combinatorial optimization</title><link>http://blogs.msdn.com/natbr/archive/tags/combinatorial+optimization/default.aspx</link><description>Tags: combinatorial optimization</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Solver Foundation on Hanselminutes</title><link>http://blogs.msdn.com/natbr/archive/2009/12/09/solver-foundation-on-hanselminutes.aspx</link><pubDate>Wed, 09 Dec 2009 15:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9934634</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9934634.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9934634</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9934634</wfw:comment><description>&lt;P&gt;The latest edition of &lt;A href="http://www.hanselman.com/blog/" mce_href="http://www.hanselman.com/blog/"&gt;Scott Hanselman&lt;/A&gt;'s &lt;A href="http://www.hanselminutes.com/default.aspx?showID=209" mce_href="http://www.hanselminutes.com/default.aspx?showID=209"&gt;Hanselminutes&lt;/A&gt; podcast features yours truly.&amp;nbsp; We talked about Solver Foundation, numerical optimization, and good old-fashioned code optimization.&amp;nbsp; Scott's a great guy and doing the podcast was a lot of fun.&lt;/P&gt;
&lt;P&gt;Those of you new to Solver Foundation (or this blog) may be curious about what you can actually do with Solver Foundation. Here is the &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799" mce_href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799"&gt;download location&lt;/A&gt; for the free&amp;nbsp;Express version of Solver Foundation.&amp;nbsp; I hope that by listening to the podcast you already know the basics, so here are a few code-oriented posts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Here is a short description of “&lt;A href="http://blogs.msdn.com/natbr/archive/2009/10/08/announcing-solver-foundation-2-0.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/10/08/announcing-solver-foundation-2-0.aspx"&gt;what’s new&lt;/A&gt;” in our 2.0 release.&lt;/LI&gt;
&lt;LI&gt;Here is a &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;C# sample&lt;/A&gt; that solves traveling salesman problems.&lt;/LI&gt;
&lt;LI&gt;Here is a &lt;A href="http://blogs.msdn.com/natbr/archive/2009/05/05/creating-parameterized-solver-foundation-models-using-linq-to-sql.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/05/05/creating-parameterized-solver-foundation-models-using-linq-to-sql.aspx"&gt;LINQ to SQL&lt;/A&gt; sample using Solver Foundation.&lt;/LI&gt;
&lt;LI&gt;Here is an&lt;A href="http://blogs.msdn.com/lengningliu/archive/2009/09/04/optimization-domain-specific-language-in-f-with-units-of-measure.aspx" mce_href="http://blogs.msdn.com/lengningliu/archive/2009/09/04/optimization-domain-specific-language-in-f-with-units-of-measure.aspx"&gt; F# sample&lt;/A&gt;.&amp;nbsp; The F# integration features a domain specific language for creating optimization problems.&amp;nbsp; It also supports “units of measure”, meaning you can associate real-life units such as miles, gallons, dollars, or touchdowns to parameters and decisions.&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://yetanothermathprogrammingconsultant.blogspot.com/" mce_href="http://yetanothermathprogrammingconsultant.blogspot.com/"&gt;Erwin&lt;/A&gt; did a really nice post on doing &lt;A href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/07/ms-solver-foundation-excel-interface.html" mce_href="http://yetanothermathprogrammingconsultant.blogspot.com/2009/07/ms-solver-foundation-excel-interface.html"&gt;portfolio management&lt;/A&gt; using Solver Foundation and Excel.&amp;nbsp; I like the visuals.&amp;nbsp; In fact Erwin's site has a number of great samples and documents.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;And I'd be remiss if I didn't mention that Solver Foundation ships with TONS of samples that span languages, scenarios, and solvers.&lt;/P&gt;
&lt;P&gt;The last part of our conversation was about writing high-performance code.&amp;nbsp;I'll share some thoughts about that later this week.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9934634" 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/Software+Development/default.aspx">Software Development</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/project+scheduling/default.aspx">project scheduling</category><category domain="http://blogs.msdn.com/natbr/archive/tags/operations+research/default.aspx">operations research</category><category domain="http://blogs.msdn.com/natbr/archive/tags/interior+point+methods/default.aspx">interior point methods</category><category domain="http://blogs.msdn.com/natbr/archive/tags/self+promotion/default.aspx">self promotion</category></item><item><title>Int'l Symposium on Mathematical Programming, Day 2</title><link>http://blogs.msdn.com/natbr/archive/2009/08/27/int-l-symposium-on-mathematical-programming-day-2.aspx</link><pubDate>Fri, 28 Aug 2009 06:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9887863</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9887863.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9887863</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9887863</wfw:comment><description>&lt;P&gt;Here are my notes from the second day of &lt;A href="http://ismp2009.eecs.northwestern.edu/" mce_href="http://ismp2009.eecs.northwestern.edu/"&gt;ISMP&lt;/A&gt;.&amp;nbsp; (&lt;A href="http://blogs.msdn.com/natbr/archive/2009/08/26/int-l-symposium-on-mathematical-programming-day-1.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/08/26/int-l-symposium-on-mathematical-programming-day-1.aspx"&gt;Here are my day 1 notes.&lt;/A&gt;)&amp;nbsp; I spent the whole day going to IPM talks:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;A href="http://www.sztaki.hu/~meszaros/" mce_href="http://www.sztaki.hu/~meszaros/"&gt;Meszaros&lt;/A&gt;&lt;/STRONG&gt;: Unfortunately I missed the plenary talk by Friedrich Eisenbrand due to microbrews.&amp;nbsp; I attended an IPM session after that - first up was Csaba Meszaros - interesting to hear from him because BPMPD has been such an impressive code for so many years.&amp;nbsp; His talk was about recent improvements in &lt;A href="http://www.sztaki.hu/~meszaros/bpmpd/" mce_href="http://www.sztaki.hu/~meszaros/bpmpd/"&gt;BPMPD&lt;/A&gt;.&amp;nbsp; BPMPD has been in continuous development for 15 years or so.&amp;nbsp; His recent work appears to focus on a) QCQP b) exploiting "hypersparsity".&amp;nbsp; He is using a primal-dual log barrier method&amp;nbsp; - not a primal-dual HSD method as we at &lt;A href="http://www.solverfoundation.com/" mce_href="http://www.solverfoundation.com"&gt;Solver Foundation&lt;/A&gt; have chosen for our SOCP solver.&amp;nbsp; So his handling of starting points and infeasibility detection is different.&amp;nbsp; He went into the tradeoffs between using augmented and normal systems for the search direction, which affect both performance and numerical stability.&amp;nbsp; He has implemented both and has logic on top to determine which to use.&amp;nbsp; He also talked about QCQP presolve, which often whittles down the size of "real" models substantially.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;An interesting bit of trivia:&amp;nbsp;he showed a table that compared lines of code in various modules, "then and now":&lt;PRE&gt; 	2009	1981
Ordering	5700	155
Cholesky	2825	100
Backsolve	820	45
&lt;/PRE&gt;&lt;BR&gt;I think the difference is indicative of both Csaba's commitment to improving BPMPD as well as the number of practical issues you need to think about when building an industrial grade solver.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;STRONG&gt;Bliek (IBM):&lt;/STRONG&gt; Next up - IPM session chair Christian Bliek from &lt;A href="http://www.ibm.com/" mce_href="http://www.ibm.com"&gt;IBM&lt;/A&gt;.&amp;nbsp; His talk was about barrier improvements in &lt;A href="http://www.ilog.com/products/cplex/" mce_href="http://www.ilog.com/products/cplex/"&gt;CPLEX&lt;/A&gt;.&amp;nbsp; For the single threaded case, CPLEX 12 is about 5% faster than 11 [note that these numbers are totally unofficial and any errors are my own].&amp;nbsp; With 4 threads it is about 20% better.&amp;nbsp; There was no magic bullet here, more tuning at the solver and algebra layer.&amp;nbsp; With a sophisticated solver such as CPLEX the improvements come through hard work, no tricks.&amp;nbsp; There was also some data on simplex vs. barrier.&amp;nbsp; For their complete set of their benchmark LPs, for problems that take 100 seconds or more barrier (without crossover) beats dual simplex on average.&amp;nbsp; If you allow crossover, then performance vs dual simplex is about even for small problems (~1s solution time) and after that crossover really takes over.&amp;nbsp; For problems that take 1000s and up, the geometric mean for the performance ratio against dual is 0.55.&amp;nbsp; So almost twice as fast.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;For QP, barrier is way better than their active set approach.&amp;nbsp; Of course this does not take into account scenarios where warmstart could be used, where simplex rocks.&amp;nbsp; More on that later.&amp;nbsp; They also have&amp;nbsp;a "concurrent" setting, meaning to race the simplex &amp;amp; IPM solvers.&amp;nbsp; This setting gives the best results.&amp;nbsp; Solver Foundation Services has also supported this type of "transparent parallelism" since version 1.0. The last bit of the talk was about some experiments using PARDISO instead of the solver's own algebra stack.&amp;nbsp; Their conclusion was that using a "black box" linear algebra module shows potential.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;STRONG&gt;Warmstart:&lt;/STRONG&gt; The last talk in the session was by Anthony Vannelli, who&amp;nbsp;talked about IPM warmstart.&amp;nbsp; He takes a very pragmatic approach and layed out a very sensible procedure for attacking the difficult problem of using the solution of an IPM problem to seed the solution of a related problem.&amp;nbsp; The net was that using a relatively simple warmstart procedure they were able to get (roughly) a factor of 3 speedup for their test set.&amp;nbsp; There were also some other IPM warmstart researchers in attendance - in particular &lt;A href="http://www.bilkent.edu.tr/~yildirim/" mce_href="http://www.bilkent.edu.tr/~yildirim/"&gt;Alper Yilidrim&lt;/A&gt; and &lt;A href="http://www.pages.drexel.edu/~hvb22/" mce_href="http://www.pages.drexel.edu/~hvb22/"&gt;Hande Benson&lt;/A&gt;. Alper had a great survey talk of existing IPM warmstart methods, and Hande is one of the top researchers in the area.&amp;nbsp; I am sure there have been interesting discussions this week!&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;STRONG&gt;&lt;A href="http://www.mosek.com/fileadmin/homepages/e.d.andersen/" mce_href="http://www.mosek.com/fileadmin/homepages/e.d.andersen/"&gt;Erling Andersen&lt;/A&gt; (&lt;A href="http://www.mosek.com/" mce_href="http://www.mosek.com"&gt;Mosek&lt;/A&gt;):&lt;/STRONG&gt; The afternoon IPM session had talks by Erling Andersen from Mosek, Jacek Gondzio, and myself.&amp;nbsp; Erling talked about SOCP improvements in MOSEK 6 (which will be out later this year).&amp;nbsp; He's had SOCP support forever, but for version 6 he has refactored and reworked much of the implementation.&amp;nbsp; He has run into problems getting high accuracy solutions (I feel his pain), and he has had some problems with infeasible or nearly infeasible problems.&amp;nbsp; He had some interesting thoughts on infeasibility criteria, rooted in his experience with real problems.&amp;nbsp; He's going to get about a 15% speedup, which is quite impressive since he is already starting with a very fast solver.&amp;nbsp; Erling has built a great set of solvers and I wish him well with Mosek 6. 
&lt;P&gt;&lt;STRONG&gt;&lt;A href="http://www.maths.ed.ac.uk/~gondzio/" mce_href="http://www.maths.ed.ac.uk/~gondzio/"&gt;Jacek Gondzio&lt;/A&gt;&lt;/STRONG&gt; talked about the use of indirect methods (such as preconditioned conjugate gradient) in IPM.&amp;nbsp; This hasn't worked out well in the past because such methods are not able to solve the systems to the accuracy required by IPM search directions.&amp;nbsp; And the problem is still not solved, but for his new approach he did show some impressive results for dense problems.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;The title of &lt;STRONG&gt;my talk&lt;/STRONG&gt; was Interior Point Methods in Solver Foundation.&amp;nbsp; I gave an overview of where IPM sits in the Solver Foundation stack, discussed our user and solver models.&amp;nbsp; (And why different user and solver models are necessary - the "user model" serves Solver Foundation Services as well as programmers, whereas the solver model is structured so as to attain the most numerically stable, high performance solver possible.&amp;nbsp; Separation of concerns!)&amp;nbsp; Then I gave a high-level overview of our solution approach, and talked about a couple of implementation issues including handling of free variables, equality constraints, etc.&amp;nbsp; Lastly I talked about some numerical stability issues. I got nice feedback from people afterwards and there was a lot of curiosity about who is using our stuff and what is next.&amp;nbsp; &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9887863" width="1" height="1"&gt;</description><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/OML/default.aspx">OML</category><category domain="http://blogs.msdn.com/natbr/archive/tags/operations+research/default.aspx">operations research</category><category domain="http://blogs.msdn.com/natbr/archive/tags/ISMP/default.aspx">ISMP</category><category domain="http://blogs.msdn.com/natbr/archive/tags/interior+point+methods/default.aspx">interior point methods</category></item><item><title>Int'l Symposium on Mathematical Programming, Day 1</title><link>http://blogs.msdn.com/natbr/archive/2009/08/26/int-l-symposium-on-mathematical-programming-day-1.aspx</link><pubDate>Wed, 26 Aug 2009 16:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9885312</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9885312.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9885312</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9885312</wfw:comment><description>&lt;P&gt;I am attending the &lt;A href="http://ismp2009.eecs.northwestern.edu/program.htm" target=_blank mce_href="http://ismp2009.eecs.northwestern.edu/program.htm"&gt;ISMP math programming conference&lt;/A&gt; in Chicago, representing the &lt;A href="http://www.solverfoundation.com/" target=_blank mce_href="http://www.solverfoundation.com"&gt;Solver Foundation&lt;/A&gt; team. Here are some of my impressions of Day 1 at ISMP:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Plenary [Steven Boyd]: &lt;/STRONG&gt;The plenary speaker was &lt;A href="http://www.stanford.edu/~boyd/" target=_blank mce_href="http://www.stanford.edu/~boyd/"&gt;Steve Boyd&lt;/A&gt; who talked about real-time embedded convex optimization.&amp;nbsp; He considered cases where problems need to be solved in milliseconds or less: control, signal processing, resource allocation, and even finance (think flash trading).&amp;nbsp;&amp;nbsp; The approach is basically to extend "disciplined convex programming".&amp;nbsp; DCP is a modeling system where problems are convex "by construction" because they combine operators with well-known properties; the system is then able to rewrite the problem in the standard form required by a convex programming solver (such as an IPM QP/SOCP solver). The new step is that the system can now generate highly optimized C code for a custom solver for the particular problem family described by the model.&amp;nbsp; (The algorithm itself is standard IPM.)&amp;nbsp; You can do all sorts of optimizations in this case: the problem structure is known so the symbolic ordering can be done in advance, you can ensure better memory locality, etc.&amp;nbsp; He gave many example where small QP instances were solved in tensof microseconds.&amp;nbsp; Fun stuff. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Morning Sessions:&lt;/STRONG&gt; I attended a morning session concerning approaches for nonconvex optimization problems. Jon Lee talked about solving a particular class of parametric nonlinear problems, &lt;A href="http://www.biz.uiowa.edu/faculty/anstreicher/" target=_blank mce_href="http://www.biz.uiowa.edu/faculty/anstreicher/"&gt;Kurt Anstreicher&lt;/A&gt; talked about *nonconvex* QP and associated bounds.&amp;nbsp; I then went to a straight-up theory session talking about convergence rates &amp;amp; asymptotic costs for IPM - there were a couple of new results and an interesting "corrector-predictor" (instead of the other way around) approach that attains better asymptotic convergence.&amp;nbsp; There is an embarrassment of riches at ISMP: I missed by John Hooker about integrating MIP, constraint &amp;amp; global optimization, a great MIP session including Bob Bixby from &lt;A href="http://blogs.msdn.com/controlpanel/blogs/www.gurobi.com" target=_blank mce_href="http://blogs.msdn.com/controlpanel/blogs/www.gurobi.com"&gt;Gurobi&lt;/A&gt;, and all sorts of other stuff.&amp;nbsp; There are a staggering number of good talks to attend.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Afternoon Sessions [Modeling / Stochastic]:&lt;/STRONG&gt; I went to a modeling languages track in the afternoon.&amp;nbsp; The first speaker was from &lt;A href="http://www.lindo.com/" target=_blank mce_href="http://www.lindo.com/"&gt;LINDO Systems&lt;/A&gt;&amp;nbsp;who talked about their new &lt;A href="http://www.lindo.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=2&amp;amp;Itemid=10" target=_blank mce_href="http://www.lindo.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=2&amp;amp;Itemid=10"&gt;LINGO&lt;/A&gt; offering.&amp;nbsp; The primary new feature is to support stochastic modeling. There were some screenshots from &lt;A href="http://www.lindo.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=3&amp;amp;Itemid=11" mce_href="http://www.lindo.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=3&amp;amp;Itemid=11"&gt;What's Best&lt;/A&gt;, their spreadsheet solver. They had a few nice samples as well.&lt;/P&gt;
&lt;P&gt;Gautam Mitra from &lt;A href="http://www.optirisk-systems.com/" mce_href="http://www.optirisk-systems.com/"&gt;OptiRisk&lt;/A&gt; was up next - he talked about SAMPL, stochastic extensions for AMPL.&amp;nbsp; They have extended SAMPL to support:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Chance constraints&lt;/LI&gt;
&lt;LI&gt;Integrated chance constraints&lt;/LI&gt;
&lt;LI&gt;Robust optimization&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Chance constraints are interesting - they occur in a range of financial problems including VaR and CVaR calculation.&amp;nbsp; Gautam riffed on the difference between stochastic and robust optimization by invoking Rumsfeld:&amp;nbsp; there are known knowns [deterministic optimization], known unknowns [stochastic],&amp;nbsp; and unknown unknowns [robust optimization].&amp;nbsp; In robust optimization you may have problem coefficients that are in some range with an unknown distribution and you want the constraints to hold in all (or most) possible circumstances.&amp;nbsp; Robust optimization also has SOCP reformulations, and I am a big believer because I think RO can be cleanly expressed in modeling languages.&amp;nbsp; The last talk in the session was about &lt;A href="http://control.ee.ethz.ch/~joloef/yalmip.php" target=_blank mce_href="http://control.ee.ethz.ch/~joloef/yalmip.php"&gt;YALMIP&lt;/A&gt; support for robust optimization - YALMIP has had widespread adoption by control theory specialists and has had a long history of improvements.&amp;nbsp; This talk was very code-oriented&amp;nbsp;and fun to watch.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;A few overall impressions: I think it is fair to say that SOCP is entering the mainstream with LP/QP/MIP - it came up a lot today.&amp;nbsp; On the modeling side, it was interesting to see that stochastic was featured in all three talks in the session I attended.&amp;nbsp; A larger trend is that MINLP (mixed integer nonlinear programming) is hot.&amp;nbsp; There are tons of tracks on it, and it is [unsurprisingly] being taken on by both the MIP and NLP communities.&amp;nbsp; The problem description is very general so of course there are applications, but the dust has not settled on the solver side.&amp;nbsp; &lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9885312" width="1" height="1"&gt;</description><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/operations+research/default.aspx">operations research</category><category domain="http://blogs.msdn.com/natbr/archive/tags/ISMP/default.aspx">ISMP</category></item><item><title>Quadratic Assignment Problems: solution enumeration</title><link>http://blogs.msdn.com/natbr/archive/2009/07/27/quadratic-assignment-problems-solution-enumeration.aspx</link><pubDate>Mon, 27 Jul 2009 19:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9850185</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9850185.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9850185</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9850185</wfw:comment><description>&lt;P&gt;In the last few posts we have given code for computing the &lt;A href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx"&gt;Gilmore Lawler bound&lt;/A&gt; for quadratic assignment problems, and &lt;A href="http://blogs.msdn.com/natbr/archive/2009/07/19/quadratic-assignment-problems-strong-and-weak-branching.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/07/19/quadratic-assignment-problems-strong-and-weak-branching.aspx"&gt;described two different branching techniques&lt;/A&gt;.&amp;nbsp;&amp;nbsp; In this post we show how to enumerate solutions of a small QAP.&amp;nbsp; The possible solutions to a QAP range over permutations over unassigned facilities and locations.&amp;nbsp;&amp;nbsp; If lower bounds do not increase after repeated branching, we may eventually assign nearly all the facilities to locations.&amp;nbsp; If there are only 2 or 3 remaining, we may as well just enumerate all the possible solutions and pick the best.&amp;nbsp;&amp;nbsp; In practice, we hope that we will rarely have to do this, otherwise the branch-and-bound tree will be too large to process efficiently.&amp;nbsp; Here is a procedure that enumerates over all solutions of a size 3 QAP.&amp;nbsp; Iterating over permutations is a standard textbook problem, so maybe you can write cleaner code than I did here!&lt;BR&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; Assume that all facilities have been assigned to locations, &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; except three. EnumerateSolutions enumerates all six remaining assignments &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; returns the best.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; EnumerateSolutions(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Qap&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; q, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[] pBest) {&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; objBest;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; nPerm = perm3.GetLength(0);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; n = perm3.GetLength(1);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[] obj = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[nPerm];&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[] r = node.p.UnusedIndices().ToArray();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[] c = node.pInv.UnusedIndices().ToArray();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[] p = (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[])node.p.Clone();&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Debug&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.Assert(r.Length == n, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;"Only call me for size "&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; + n + &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;" QAPs."&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;);&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;// Try all the possible permutations.&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; i = 0; i &amp;lt; nPerm; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; j = 0; j &amp;lt; n; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p[r[j]] = c[perm3[i, j]]; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj[i] = q.Evaluate(p);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;// Get the best permutation and objective.&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; best = obj.ArgMin(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;out&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; objBest);&lt;BR&gt;&amp;nbsp; p.CopyTo(pBest, 0);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; j = 0; j &amp;lt; n; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pBest[r[j]] = perm3[best, j];&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; objBest;&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;If you combine the code from the following posts you will see that we almost have a working B&amp;amp;B solver:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-iii.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-iii.aspx"&gt;Linear assignment problem solver&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2008/05/03/quadratic-assignment-problems-branch-and-bound.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2008/05/03/quadratic-assignment-problems-branch-and-bound.aspx"&gt;QAP object&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx"&gt;QAP Gilmore-Lawler bound&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx"&gt;Branch-and-bound skeleton&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/24/simple-matrix-vector-permutation-utilities.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/24/simple-matrix-vector-permutation-utilities.aspx"&gt;Vector and matrix utilities&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/07/12/quadratic-assignment-problems-branching.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/07/12/quadratic-assignment-problems-branching.aspx"&gt;Branching&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/07/19/quadratic-assignment-problems-strong-and-weak-branching.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/07/19/quadratic-assignment-problems-strong-and-weak-branching.aspx"&gt;Strong and weak branching&lt;/A&gt;.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;In my next post I will fill in a couple of the gaps, and then I will re-post all of the code.&amp;nbsp; Then we'll think about what we can actually do with a QAP solver!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9850185" 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/QAP/default.aspx">QAP</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/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/operations+research/default.aspx">operations research</category></item><item><title>Quadratic Assignment Problems: strong and weak branching</title><link>http://blogs.msdn.com/natbr/archive/2009/07/19/quadratic-assignment-problems-strong-and-weak-branching.aspx</link><pubDate>Mon, 20 Jul 2009 05:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9840714</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9840714.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9840714</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9840714</wfw:comment><description>&lt;P&gt;Let's pick up where we left off &lt;A href="http://blogs.msdn.com/natbr/archive/2009/07/12/quadratic-assignment-problems-branching.aspx" target=_blank mce_href="http://blogs.msdn.com/natbr/archive/2009/07/12/quadratic-assignment-problems-branching.aspx"&gt;last time&lt;/A&gt; and write a score-based Branch delegate.&amp;nbsp; It will be used as the basis for&amp;nbsp;both of our "real"&amp;nbsp;branching functions.&amp;nbsp; &lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; BranchCore(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; bound, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] S) {&lt;BR&gt;&amp;nbsp; RowColumnSums(S, node.Size);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; rowVal, colVal;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; rowBest = _rowSum.ArgMax(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;out&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; rowVal);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; colBest = _colSum.ArgMax(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;out&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; colVal);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (rowVal &amp;gt; colVal) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;, rowBest);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;else&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;, colBest);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; RowColumnSums(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] U, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; size) {&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (_rowSum == &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;null&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rowSum = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[_qap.Size];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _colSum = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[_qap.Size];&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; _rowSum.ConstantFill(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.MinValue);&lt;BR&gt;&amp;nbsp; _colSum.ConstantFill(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.MinValue);&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; i = 0; i &amp;lt; size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; j = 0; j &amp;lt; size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rowSum[i] += U[i][j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _colSum[j] += U[i][j];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;If we can create a reasonable score matrix and pass it into BranchCore, then we've got something.&amp;nbsp; Two common techniques for QAP are:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Weak branching.&lt;/STRONG&gt;&amp;nbsp; Let S_ij be the reduced cost U_ij that we got from computing the lower bound.&amp;nbsp; (U_ij is a lower bound on the amount that the bound on the subproblem will increase.&amp;nbsp; So large U_ij means the subproblem will be a lot easier.)&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Strong branching.&amp;nbsp; &lt;/STRONG&gt;Let S_ij be the bound for subproblem ij.&amp;nbsp; The bigger the bound, the easier the subproblem.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Weak branching is trivial to implement for the &lt;A href="http://www.seas.upenn.edu/qaplib/codes.html" target=_blank mce_href="http://www.seas.upenn.edu/qaplib/codes.html"&gt;Gilmore-Lawler&lt;/A&gt; (or&amp;nbsp;GLB) bound.&amp;nbsp; &lt;A href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx" target=_blank mce_href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx"&gt;As I mentioned a long time ago&lt;/A&gt;, the reduced cost matrix essentially comes for free.&lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; WeakBranch(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; bound, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] U) {&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; BranchCore(node, bound, U);&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;For strong branching we need to compute bounds for each subproblem.&amp;nbsp; We overwrite the U matrix and pass it into BranchCore.&amp;nbsp; Since the U matrix is used to fathom subproblems later on in the code, we subtract the parent bound from the bound of each subproblem.&lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; StrongBranch(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; bound, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] U) {&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Qap&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; r = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;new&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Qap&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;(node.Size - 1);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] Ur = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;MatrixUtilities&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.NewMatrix(node.Size - 1, node.Size - 1);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; i = 0; i &amp;lt; node.Size; i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;for&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; (&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; j = 0; j &amp;lt; node.Size; j++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Qap&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.Reduce(node.Qap, r, i, j);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; U[i][j] = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;GLB&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;.Bound(r, Ur) - bound;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; BranchCore(node, bound, U);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;Strong branching in general produces better guesses that weak branching.&amp;nbsp; However, it comes at a computational cost.&amp;nbsp; Therefore I want to introduce one last complication…er…feature.&amp;nbsp; Since strong branching is smarter but more costly, we should only use it where it is most needed.&amp;nbsp; I want to have a set of rules that governs when to use strong or weak branching.&amp;nbsp; Branching decisions are most important at the top of the tree, or on nodes where the bound sucks.&amp;nbsp; We can measure the suckiness of the bound for a node by computing the relative gap:&amp;nbsp; the ratio of the gap between the bound and the incumbent solution, and the corresponding gap at the root.&amp;nbsp;&amp;nbsp; So our branching rule data structure will have Depth and Gap properties, as well as properties that store the Branch delegate information.&lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;A description of a branching rule: when and how.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;class&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingRule&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; {&lt;BR&gt;&lt;FONT color=#808080&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;The ID for this rule.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Index { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;FONT color=#808080&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;Maximum depth for which the rule applies.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Depth { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;FONT color=#808080&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;Maximum relative gap for&amp;nbsp;which the rule applies.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Gap { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;FONT color=#808080&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;Strong or Weak.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchType&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Type { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;FONT color=#808080&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;StrongBranch() or WeakBranch().&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;internal&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Branch&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Rule { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; BranchingRule(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; index, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; gap, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; depth, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchType&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; type) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Index = index;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Depth = depth;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Gap = gap;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type = type;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;override&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;string&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; ToString() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;"Depth = "&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; + Depth + &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;", Gap = "&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; + Gap + &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;&lt;FONT color=#a31515 size=2 face=Consolas&gt;", Type = "&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; + Type.ToString();&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;We will have an array of BranchingRule called _branchingRule.&amp;nbsp; Given a node, we will select the first rule in the array whose depth is larger than the node depth, and whose gap is larger than the node gap.&lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;private&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Branch&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; SelectBranchingRule(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node) {&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; gap = _results.RelativeGap(node.LowerBound);&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingRule&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; criterion = _branchingRules.First(entry =&amp;gt; (node.Level &amp;lt;= entry.Depth) &amp;amp;&amp;amp; (gap &amp;gt;= entry.Gap));&lt;BR&gt;&amp;nbsp; node.RuleIndex = criterion.Index;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; criterion.Rule;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;I am cheating here because I have not defined the local variable _results.&amp;nbsp; We'll get to that in a few posts.&amp;nbsp; For now, just assume that RelativeGap is defined as I described above: (Objective - bound) / (Objective - RootBound).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;At long last, that covers branching.&amp;nbsp; There are many variations, but they are essentially variations of strong or weak branching.&amp;nbsp; At this point we only have two more main topics to cover: what to do when you get to the bottom of the tree, and how do you capture and update results.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9840714" 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/QAP/default.aspx">QAP</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/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/operations+research/default.aspx">operations research</category></item><item><title>Quadratic assignment problems: branching</title><link>http://blogs.msdn.com/natbr/archive/2009/07/12/quadratic-assignment-problems-branching.aspx</link><pubDate>Mon, 13 Jul 2009 02:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9830717</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9830717.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9830717</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9830717</wfw:comment><description>&lt;P&gt;(This is part of a long-running series on quadratic assignment problems in C#.&amp;nbsp; &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx"&gt;Click here to&amp;nbsp;catch up.&lt;/A&gt;)&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx" target=_blank mce_href="http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx"&gt;Branching&lt;/A&gt; means to divide the search space represented by a node into subnodes.&amp;nbsp; QAP is about making assignments of facilities to locations, so two possible approaches come to mind:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Branch into two subproblems: one where an assignment i -&amp;gt; j is allowed, and another where it is disallowed.&lt;/LI&gt;
&lt;LI&gt;Pick a facility and try assigning it to all possible locations, creating N subproblems.&amp;nbsp; (Or pick a location and assign all facilities to it…)&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The second approach, called &lt;STRONG&gt;polytomic branching&lt;/STRONG&gt;, turns out to be more effective.&amp;nbsp; The problem with the first ("single assignment branching") is that the subproblems aren't that much easier than the parent problem.&amp;nbsp; You'll have to branch a whole bunch of times before you are able to determine anything.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We still need to decide whether to fix a facility ("row branching") or a location ("column branching").&amp;nbsp; And after that we need to figure out which particular facility or location is best.&amp;nbsp; At this point you may be wondering, "does it even matter?"&amp;nbsp; The answer is that, yes, branching decisions are earth shatteringly important.&amp;nbsp; Where's what I mean: if you make bad branching choices it could take a thousand times longer to solve the problem, or more!&amp;nbsp; This is part of the reason why QAP (and branch-and-bound) are so interesting.&amp;nbsp; Bad branching decisions lead to subproblems that are just about as hard as the original problem.&amp;nbsp; &lt;A href="http://www.youtube.com/watch?v=LD8HDta7Z_4" target=_blank mce_href="http://www.youtube.com/watch?v=LD8HDta7Z_4"&gt;It's kind of like this.&lt;/A&gt;&amp;nbsp; Here is a data structure that represents the results of a polytomic branching decision.&lt;/P&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;A branching decision, the result of applying a branching rule.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;internal&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;class&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; {&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;If true, enumerate over all unassigned rows.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&amp;nbsp; public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; IsRowBranch { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;The row or column index.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&amp;nbsp; public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; Index { &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;get&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;set&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;; }&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;Create a new instance.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;nbsp; ///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; BranchingDecision(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; isRowBranch, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; index) {&lt;BR&gt;&amp;nbsp;&amp;nbsp; IsRowBranch = isRowBranch;&lt;BR&gt;&amp;nbsp;&amp;nbsp; Index = index;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P style="MARGIN: 0in; FONT-FAMILY: Calibri; FONT-SIZE: 11pt"&gt;Ultimately we want to write methods that produce BranchingDecisions.&amp;nbsp; The following delegate represents such a method (we will write two methods in the next blog post):&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;summary&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;Makes a branching decision.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;///&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt;&lt;FONT color=#008000 size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&lt;FONT color=#808080 size=2 face=Consolas&gt;&amp;lt;/summary&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;internal&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;delegate&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchingDecision&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;Branch&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;(&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;&lt;FONT color=#2b91af size=2 face=Consolas&gt;BranchAndBoundNode&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; node, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt; bound, &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;&lt;FONT color=#0000ff size=2 face=Consolas&gt;double&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2 face=Consolas&gt;&lt;FONT size=2 face=Consolas&gt;[][] U);&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;If you accept the claim that branching choices make a big difference, then it is&amp;nbsp;clear that we want to&amp;nbsp;branch&amp;nbsp;so we get the&amp;nbsp;easiest subproblems possible.&amp;nbsp; That is, nodes that will be processed by the branch-and-bound algorithm as quickly as possible.&amp;nbsp; We don't know how to measure that directly (why?), so we have to guess.&amp;nbsp; A general framework for polytomic branching is to compute a score for each of the N^2 subproblems, and store it in a matrix.&amp;nbsp; S_ij is the score for the subproblem created by fixing facility i to location j.&amp;nbsp; Then compute the row and column sums of S, and branch on the row or the column with maximum sum.&amp;nbsp; Making a branching choice reduces to computing scores on subproblems.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The next step will be to write methods that compute scores and return BranchingDecisions.&amp;nbsp; We'll look at two common ways to do that next time.&amp;nbsp; We're about two or three posts away from having a pretty decent branch-and-bound solver for QAP.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9830717" 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/QAP/default.aspx">QAP</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/optimization/default.aspx">optimization</category></item><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>Solver Foundation 1.2 released!</title><link>http://blogs.msdn.com/natbr/archive/2009/04/18/solver-foundation-1-2-released.aspx</link><pubDate>Sun, 19 Apr 2009 06:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9555406</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9555406.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9555406</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9555406</wfw:comment><description>&lt;P&gt;I am pleased to announce that Solver Foundation v1.2 is live on &lt;A href="http://solverfoundation.com/" mce_href="http://solverfoundation.com"&gt;solverfoundation.com&lt;/A&gt;! Our goal in 1.2 was to make a few key improvements to address feedback that we have received from partners and customers. If you have feedback, questions, suggestions…please post it here, or on our &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Thread/List.aspx" mce_href="http://code.msdn.microsoft.com/solverfoundation/Thread/List.aspx"&gt;MSDN forum&lt;/A&gt;. Positive or negative - that's okay. I am particularly interested in hearing how you use Solver Foundation in your application - or what features you would like to see. &lt;/P&gt;
&lt;P&gt;Back to 1.2:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The popular &lt;A href="http://www.dashoptimization.com/home/products/xpress_msf.html" mce_href="http://www.dashoptimization.com/home/products/xpress_msf.html"&gt;FICO Xpress&lt;/A&gt; is now a "certified partner". That means if you are an Xpress user, you can use Solver Foundation's plug-in model to write .Net applications without a hitch. &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://www.amsterdamoptimization.com/solverfoundation.html" mce_href="http://www.amsterdamoptimization.com/solverfoundation.html"&gt;Amsterdam Optimization&lt;/A&gt; is a certified modeling consultant for Solver Foundation. I've linked to&lt;A href="http://yetanothermathprogrammingconsultant.blogspot.com/" mce_href="http://yetanothermathprogrammingconsultant.blogspot.com/"&gt; Erwin's blog&lt;/A&gt; before - he's a member of this group. We are happy to be partnering with them. &lt;/LI&gt;
&lt;LI&gt;MIP start functionality has been added. This allows you to give a starting solution to a MIP model using SetInitialValue on Decision. &lt;/LI&gt;
&lt;LI&gt;Bug fixes - in particular we've taken care of a few QP issues. &lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9555406" width="1" height="1"&gt;</description><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/OML/default.aspx">OML</category></item><item><title>Resource constrained scheduling; OML tutorials</title><link>http://blogs.msdn.com/natbr/archive/2009/03/31/resource-constrained-scheduling-oml-tutorials.aspx</link><pubDate>Wed, 01 Apr 2009 05:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9524968</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9524968.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9524968</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9524968</wfw:comment><description>&lt;P&gt;Two weeks back I posted &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx"&gt;two&lt;/A&gt; &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/06/project-scheduling-and-solver-foundation-links-and-constraints.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/06/project-scheduling-and-solver-foundation-links-and-constraints.aspx"&gt;articles&lt;/A&gt; showing how easy it is to model critical path scheduling using &lt;A href="http://www.solverfoundation.com/" mce_href="http://www.solverfoundation.com"&gt;Microsoft Solver Foundation&lt;/A&gt;.&amp;nbsp; I received a few emails asking about various extensions; I will be covering those in upcoming posts.&amp;nbsp; Julian just wrote &lt;A href="http://brightsparc.wordpress.com/2009/03/31/scheduling-algorithm-in-gams-ampl-mfs-and-lp_solve/" mce_href="http://brightsparc.wordpress.com/2009/03/31/scheduling-algorithm-in-gams-ampl-mfs-and-lp_solve/"&gt;a great blog post&lt;/A&gt; that covers the most commonly requested extension - resource constrained scheduling.&amp;nbsp; If you are getting started with Solver Foundation and want to see an interesting, instructive example, I encourage you to check out his post.&amp;nbsp; Two things that I really like about his OML:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;He separates the data from the model description using Parameters.&lt;/LI&gt;
&lt;LI&gt;He relies on the Foreach construct to define his constraints.&amp;nbsp; It results in a very clean model definition.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Julian mentions it in his post, but I also want to call out another great resource for learning OML.&amp;nbsp; Erwin Kalvalagen has written an &lt;A href="http://www.amsterdamoptimization.com/models/msf/oml.pdf" mce_href="http://www.amsterdamoptimization.com/models/msf/oml.pdf"&gt;OML tutorial&lt;/A&gt; which includes several interesting examples.&amp;nbsp; It's a great complement to the &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799" mce_href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799"&gt;Excel Programming Primer&lt;/A&gt; that is part of the Solver Foundation documentation.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9524968" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</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/OML/default.aspx">OML</category><category domain="http://blogs.msdn.com/natbr/archive/tags/project+scheduling/default.aspx">project scheduling</category></item><item><title>Simple matrix, vector, permutation utilities</title><link>http://blogs.msdn.com/natbr/archive/2009/03/24/simple-matrix-vector-permutation-utilities.aspx</link><pubDate>Wed, 25 Mar 2009 07:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9506333</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9506333.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9506333</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9506333</wfw:comment><description>&lt;P&gt;I am going to be rolling out the rest of my branch-and-bound algorithm in the next few posts.&amp;nbsp; To make that easier, in this post I introduce some common matrix, vector, and permutation methods.&amp;nbsp; It turns out that for technical computing applications, C#'s &lt;STRONG&gt;extension&lt;/STRONG&gt; methods (introduced in 3.0) are awesome.&amp;nbsp; With vectors it's great because you retain the control of having direct array access, but you get the nice object-oriented notation.&lt;/P&gt;
&lt;P&gt;I've left out comments and error-checking, and it's not super-optimized,&amp;nbsp;but you get the idea.&amp;nbsp; None of these methods end up being the bottleneck.&amp;nbsp; Most of the methods are obvious, but I do want to comment on the permutation methods.&amp;nbsp; The goal of QAP is to find an optimal assignment of facilities to locations, represented as a permutation.&amp;nbsp; In the course of our branch-and-bound algorithm, we'll be making partial assignments - that is, only some of the entries in the permutation will be filled in.&amp;nbsp; By convention, p[i] == -1 will mean that facility i is unassigned.&amp;nbsp; An index where p[i] &amp;lt; 0 is called "unused".&amp;nbsp; When we branch, we'll want to pick an unused facility (or location), and try assigning all unused locations (or facilities) to it.&amp;nbsp;&amp;nbsp; The use of C#'s &lt;STRONG&gt;iterator&lt;/STRONG&gt; and &lt;STRONG&gt;yield&lt;/STRONG&gt; concepts really help here.&lt;/P&gt;
&lt;P&gt;That said, here's the code.&lt;/P&gt;&lt;PRE&gt;  public static class MatrixUtilities {
    #region Vector
    public static void ConstantFill&lt;T&gt;(this T[] data, T val) {
      for (int i = 0; i &amp;lt; data.Length; i++) {
        data[i] = val;
      }
    }

    public static int ArgMin(this double[] data, out double best) {
      if (data.Length == 0) {
        best = Double.MinValue;
        return -1;
      }
      int iBest = 0;
      best = data[0];
      for (int i = 1; i &amp;lt; data.Length; i++) {
        if (best &amp;gt; data[i]) {
          best = data[i];
          iBest = i;
        }
      }
      return iBest;
    }

    public static int ArgMax(this double[] data, out double best) {
      if (data.Length == 0) {
        best = Double.MinValue;
        return -1;
      }
      int iBest = 0;
      best = data[0];
      for (int i = 1; i &amp;lt; data.Length; i++) {
        if (best &amp;lt; data[i]) {
          best = data[i];
          iBest = i;
        }
      }
      return iBest;
    }
    #endregion

    #region Permutation
    public static void Swap(this int[] p, int i, int j) {
      int temp = p[i];
      p[i] = p[j];
      p[j] = temp;
    }

    public static int FindUnused(this int[] data, int index) {
      foreach (int unused in data.UnusedIndices()) {
        if (index-- &amp;lt;= 0) {
          return unused;
        }
      }
      return -1;
    }

    public static IEnumerable&lt;INT&gt; UnusedIndices(this int[] data) {
      for (int i = 0; i &amp;lt; data.Length; i++) {
        if (data[i] &amp;lt; 0) {
          yield return i;
        }
      }
    }

    public static string PermutationToString(this int[] p, bool oneBased) {
      StringBuilder build = new StringBuilder(p.Length * 4);
      int width = ((int)Math.Log10(p.Length)) + 2;
      build.Append("[");
      for (int i = 0; i &amp;lt; p.Length; i++) {
        int index = oneBased ? p[i] + 1 : p[i];
        build.Append(index.ToString().PadLeft(width));
      }
      build.Append("]");
      return build.ToString();
    }
    #endregion

    #region Matrix

    public static string MatrixToString(this double[][] A) {
      if (A != null) {
        StringBuilder build = new StringBuilder(A.Length * A.Length * 3);
        for (int i = 0; i &amp;lt; A.Length; i++) {
          if (A[i] != null) {
            for (int j = 0; j &amp;lt; A[i].Length; j++) {
              build.AppendFormat("{0,4}", A[i][j]);
              build.Append(" ");
            }
            build.AppendLine();
          }
        }
        return build.ToString();
      }
      return null;
    }

    public static double[][] NewMatrix(int m, int n) {
      double[][] M = new double[m][];
      for (int i = 0; i &amp;lt; M.Length; i++) {
        M[i] = new double[n];
      }
      return M;
    }

    public static double[][] NewMatrix(int n) {
      return NewMatrix(n, n);
    }
    #endregion
  }
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9506333" 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/QAP/default.aspx">QAP</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/linear+algebra/default.aspx">linear algebra</category></item><item><title>Branch-and-bound algorithms for QAP</title><link>http://blogs.msdn.com/natbr/archive/2009/03/23/branch-and-bound-algorithms-for-qap.aspx</link><pubDate>Mon, 23 Mar 2009 23:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9502479</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9502479.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9502479</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9502479</wfw:comment><description>&lt;P&gt;This is part 4 in a series of posts laying out a simple branch-and-bound solver for QAP in C#.&amp;nbsp;&lt;A href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx" target=_blank mce_href="http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx"&gt;Last time&lt;/A&gt; (several months ago!)&amp;nbsp;I provided a simple bounding procedure for QAP.&amp;nbsp; I want to take a step back and give the high-level algorithm, then in subsequent posts I will fill in the implementation.&lt;/P&gt;
&lt;P&gt;Branch-and-bound algorithms are a general framework for solving combinatorial optimization problems.&amp;nbsp; The idea is to repeatedly subdivide the search space into smaller subproblems of the same time.&amp;nbsp; For each subproblem we compute bounds, which may allow us to determine that the subproblem cannot lead to an improved solution to the original problem.&lt;/P&gt;&lt;PRE&gt;  /// &lt;SUMMARY&gt;Solves QAP using branch-and-bound.
  /// &lt;/SUMMARY&gt;
  public class BranchAndBound {

    private readonly Qap _qap;
    private BranchAndBoundResults _results;

    /// &lt;SUMMARY&gt;Create a new instance.
    /// &lt;/SUMMARY&gt;
    public BranchAndBound(Qap qap) {
      _qap = qap;
    }

    /// &lt;SUMMARY&gt;Solve a QAP to optimality.
    /// &lt;/SUMMARY&gt;
    public void Solve() {

      _results = new BranchAndBoundResults();
      Stack&lt;BRANCHANDBOUNDNODE&gt; stack = new Stack&lt;BRANCHANDBOUNDNODE&gt;();
      stack.Push(new BranchAndBoundNode(_qap));

      while (stack.Count &amp;gt; 0) {
        BranchAndBoundNode node = stack.Pop();

        if (node.LowerBound &amp;lt;= _results.Objective) {
          if (node_is_easy_to_solve) {
            EnumerateSolutions(node, _results);
          }
          else {
            node.LowerBound = GLB.Bound(node.Qap, U);

            if (node.LowerBound &amp;lt;= _results.Objective) {
              foreach (BranchAndBoundNode subNode in Branch(node, U).OrderBy(n =&amp;gt; n.LowerBound)) {
                stack.Push(subNode);
              }
            }
          }
        }
      }
    }
  }

  /// &lt;SUMMARY&gt;A subproblem in a branch-and-bound algorithm.
  /// &lt;/SUMMARY&gt;
  public class BranchAndBoundNode {
    private readonly Qap _qap;
    /// &lt;SUMMARY&gt;The size of the subproblem.
    /// &lt;/SUMMARY&gt;
    public int Size {
      get { return _qap.Size; }
    }

    /// &lt;SUMMARY&gt;The lower bound of the subproblem.
    /// &lt;/SUMMARY&gt;
    public double LowerBound { get; set; }

    /// &lt;SUMMARY&gt;The QAP subproblem.
    /// &lt;/SUMMARY&gt;
    public Qap Qap {
      get { return _qap; }
    }
  }

  /// &lt;SUMMARY&gt;Branch-and-bound solution information.
  /// &lt;/SUMMARY&gt;
  public class BranchAndBoundResults {
    public int[] p { get; set; }
    public double Objective { get; set; }
  }
&lt;/PRE&gt;
&lt;P&gt;Let's work through the pseudocode.&amp;nbsp; Our stack will contain the current set of subproblems that need to be solved.&amp;nbsp; We initialize the stack with our QAP instance, wrapping&amp;nbsp;it inside a BranchAndBoundNode data&amp;nbsp; structure.&amp;nbsp; We'll develop this data structure as we go, but from the code we can already see&amp;nbsp;two uses: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It stores the subproblem (a QAP),&lt;/LI&gt;
&lt;LI&gt;It stores the lower bound computed by the code from my last post.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The other thing we do is allocate a data structure which stores the results: the best assignment found so far, and the best objective value.&amp;nbsp; In the main loop of Solve() we repeatedly pop nodes from the stack.&amp;nbsp; We first compare the node's lower bound to the best objective (also called the &lt;STRONG&gt;incumbent&lt;/STRONG&gt;).&amp;nbsp; If the lower bound exceeds the incumbent value, there is no way this subproblem can lead to a better result, so we need not process it.&amp;nbsp; The incumbent value may have changed since the subproblem was created.&amp;nbsp; Then we check to see if the subproblem is "easy" - if so, we can simply &lt;STRONG&gt;enumerate&lt;/STRONG&gt; over all possible solutions for the subproblem and update the results if needed.&amp;nbsp; Otherwise, we use our GLB code to compute a bound.&amp;nbsp; Again, we check the lower bound to see if we can eliminate (or &lt;STRONG&gt;fathom&lt;/STRONG&gt;) the subproblem.&amp;nbsp; If not, we need to subdivide the node into subproblems, and push them onto the stack.&lt;/P&gt;
&lt;P&gt;The top-level algorithm itself is not all that complicated!&amp;nbsp; It's also quite general.&amp;nbsp; We have already described how to compute bounds, so all we need to do is specify:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;How to enumerate solutions for small problems.&lt;/LI&gt;
&lt;LI&gt;How to branch - i.e. how to subdivide BranchAndBoundNodes.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The motivation and code for enumerating and branching will be the subject of the next two posts.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9502479" 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/QAP/default.aspx">QAP</category><category domain="http://blogs.msdn.com/natbr/archive/tags/combinatorial+optimization/default.aspx">combinatorial optimization</category></item><item><title>Microsoft Solver Foundation version 1.1 released</title><link>http://blogs.msdn.com/natbr/archive/2009/02/18/microsoft-solver-foundation-version-1-1-released.aspx</link><pubDate>Wed, 18 Feb 2009 18:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9431576</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9431576.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9431576</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9431576</wfw:comment><description>&lt;P&gt;&lt;A href="http://www.solverfoundation.com/" target=_blank mce_href="http://www.solverfoundation.com"&gt;Microsoft Solver Foundation&lt;/A&gt; version 1.1 has been released and the Express version can be downloaded for free &lt;A href="http://code.msdn.microsoft.com/solverfoundation/" target=_blank mce_href="http://code.msdn.microsoft.com/solverfoundation/"&gt;here&lt;/A&gt;.&amp;nbsp; 1.1 is a big deal because of the introduction of our solver plug-in model.&amp;nbsp; This allows new or existing 3rd party solvers to interface with Solver Foundation Services (SFS) directly - meaning that existing OML models, C#, or other .Net application code will work without changes.&amp;nbsp; As improvements in solver technology emerge, your application code will benefit without a single line of code being changed.&amp;nbsp; We did not just throw the plug-in model over the wall - we have partnered with some of the top names in the field to provide certified plug-ins.&amp;nbsp; The Gurobi MIP solver is included in this release as the default MIP solver (recent, independent benchmarks for Gurobi are available &lt;A href="http://plato.asu.edu/ftp/milpc.html" target=_blank mce_href="http://plato.asu.edu/ftp/milpc.html"&gt;here&lt;/A&gt;).&amp;nbsp; We also provide a Mosek partner wrapper.&amp;nbsp; In addition, we provide reference plug-ins (with source code) for CPLEX, Mosek, Xpress-MP, and lp_solve.&amp;nbsp; If you have one of these solvers, it's very easy to drop in the plug-in and get the benefits of Solver Foundation Services: declarative modeling, transparent parallelism, a fully-featured .Net API.&lt;/P&gt;
&lt;P&gt;We have also made a number of other improvements.&amp;nbsp; Solver Foundation now supports SOS2 (special ordered sets) -&amp;nbsp; an ordered set of non-negative decisions where at most two consecutive values are nonzero.&amp;nbsp; There is a complete description of the syntax with examples in the Excel Programming Primer document (Appendix 4).&amp;nbsp; We're shipping a number of new examples, including more data binding and ASP.Net samples.&amp;nbsp; Finally, we've improved the performance across the board.&amp;nbsp; In particular, I am proud to say that the performance of our interior-point solvers has improved by 20%, with bigger gains for some problems.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Give it a try and let me know what you think.&amp;nbsp; &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Thread/List.aspx" target=_blank mce_href="http://code.msdn.microsoft.com/solverfoundation/Thread/List.aspx"&gt;Post on the Solver Foundation&amp;nbsp;forum&lt;/A&gt; with questions or comments, we want to hear from you.&amp;nbsp; 2009 will be a big year for Solver Foundation and it's great to kick it off with this release.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9431576" width="1" height="1"&gt;</description><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></item><item><title>Solver Foundation used to schedule Microsoft Tech Days '09</title><link>http://blogs.msdn.com/natbr/archive/2009/01/21/solver-foundation-used-to-schedule-microsoft-tech-days-09.aspx</link><pubDate>Thu, 22 Jan 2009 06:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9362470</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9362470.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9362470</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9362470</wfw:comment><description>&lt;P&gt;Pascal Belaud of Microsoft France recently used Microsoft Solver Foundation to schedule the big&amp;nbsp;&lt;A href="http://www.microsoft.com/france/mstechdays/" mce_href="http://www.microsoft.com/france/mstechdays/"&gt;Microsoft Tech Days '09&lt;/A&gt; conference in sunny Paris, France.&amp;nbsp;The conference has over 16,000 attendees, with hundreds of presentations involving hundreds of speakers and rooms - quite a challenge, but Pascal (with Solver Foundation's help)&amp;nbsp;was up to the task!&amp;nbsp;&amp;nbsp;Solver Foundation&amp;nbsp;was also featured in the keynote.&amp;nbsp; It's quite an application and we were pleased to have the opportunity to work with Pascal.&amp;nbsp; Read more about it (in French - but don't be scared, click the link) &lt;A href="http://blogs.technet.com/mstechdays/archive/2009/01/18/l-agenda-des-microsoft-techdays-2009-a-t-enti-rement-con-u-l-aide-de-microsoft-solver-foundation.aspx" mce_href="http://blogs.technet.com/mstechdays/archive/2009/01/18/l-agenda-des-microsoft-techdays-2009-a-t-enti-rement-con-u-l-aide-de-microsoft-solver-foundation.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;In other recent news, we now have an official web presence, check out &lt;A href="http://www.solverfoundation.com/" mce_href="http://www.solverfoundation.com/"&gt;solverfoundation.com&lt;/A&gt; for an overview of what were about and where to get it.&amp;nbsp; Version 1.1 will be on its way soon with many enhancements.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9362470" width="1" height="1"&gt;</description><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/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category></item><item><title>Announcing Microsoft Solver Foundation</title><link>http://blogs.msdn.com/natbr/archive/2008/11/14/announcing-microsoft-solver-foundation.aspx</link><pubDate>Fri, 14 Nov 2008 21:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9075468</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9075468.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9075468</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9075468</wfw:comment><description>&lt;P&gt;I'm pleased to announce the availability of the first version of &lt;STRONG&gt;Microsoft Solver Foundation&lt;/STRONG&gt;!&amp;nbsp; Simply put, Solver Foundation is a set of modeling tools and solvers to help you make smart decisions when confronted with complex requirements and priorities.&amp;nbsp; A huge range of business and research problems can be modeled using Solver Foundation, including supply chain optimization, job scheduling, transportation network flows, risk analysis of investment portfolios, etc. &lt;/P&gt;
&lt;P&gt;Solver Foundation consists of three types of services:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Programming and Modeling Services&lt;/STRONG&gt; which allow .Net and Excel developers to easily integrate Solver Foundation into their applications.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Solver Foundation Services&lt;/STRONG&gt; for model interchange, feasibility analysis, and declarative parallel solving.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Solver Runtime and Extensibility Services&lt;/STRONG&gt; for plugging in third-party solvers.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Solver Foundation is 100% pure managed code and comes with a number of solvers right out of the box:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Revised, Simplex Linear and Mixed Integer Programming (Primal and Dual Simplex) &lt;/LI&gt;
&lt;LI&gt;Interior Point Method Linear and Quadratic Programming &lt;/LI&gt;
&lt;LI&gt;Constraint Programming with Exhaustive Tree Search, Local Search, and Metaheuristic Techniques &lt;/LI&gt;
&lt;LI&gt;Compact, Quasi-Newton (L-BFGS), Unconstrained Nonlinear Programming &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;For more information, check out &lt;A href="http://code.msdn.microsoft.com/solverfoundation"&gt;http://code.msdn.microsoft.com/solverfoundation&lt;/A&gt;.&amp;nbsp; Click on the Downloads tab to get the Express Edition for free.&amp;nbsp; Solver Foundation includes a bunch of samples for Excel, C#, F# to help you get started.&lt;/P&gt;
&lt;P&gt;I'm a new member of the team and I am excited to be a part of the Solver Foundation effort.&amp;nbsp; Before I started at Microsoft I worked on optimization software (interior point methods and combinatorial optimization in particular), so this is a huge passion of mine.&amp;nbsp;&amp;nbsp; In the upcoming months, I'll be blogging in detail about many aspects of Solver Foundation.&amp;nbsp; &lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9075468" 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/QAP/default.aspx">QAP</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></item></channel></rss>