<?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 : QAP</title><link>http://blogs.msdn.com/natbr/archive/tags/QAP/default.aspx</link><description>Tags: QAP</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><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>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>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><item><title>Quadratic assignment problems: bounds</title><link>http://blogs.msdn.com/natbr/archive/2008/07/10/quadratic-assignment-problems-bounds.aspx</link><pubDate>Thu, 10 Jul 2008 22:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8718377</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/natbr/comments/8718377.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=8718377</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=8718377</wfw:comment><description>&lt;P&gt;This is part 3 of what will be a long series about how to solve QAPs using branch-and-bound. My goal to end up with a simple branch-and-bound algorithm in C#.&amp;nbsp; In my last post I wrote down the formulation for QAP, wrote a QAP class in C#, and showed how to create subproblems for branching.&amp;nbsp; Let's focus on lower bounds for QAP.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We get a lower bound for QAP by relaxing some of the constraints of the problem, and then solving the relaxed version of the problem.&amp;nbsp; Different bounds&amp;nbsp; are obtained by relaxing the constraints in different ways.&amp;nbsp; Unfortunately in most cases the relaxations require a lot of math and are pretty darn hard to blog about.&amp;nbsp; So I will pick one of the oldest bounds for QAP, called the "Gilmore Lawler" bound, and try to sketch the motivation behind it.&amp;nbsp; I'm not going to try and prove anything about the bound - the point is that the relaxation that we end up with is fairly easy to code, which is exactly what I'm after.&amp;nbsp; If you're after a nitty-gritty derivation of the bound, there's the original paper by &lt;A class="" href="http://www.zentralblatt-math.org/zmath/search/?an=0995.90579" target=_blank mce_href="http://www.zentralblatt-math.org/zmath/search/?an=0995.90579"&gt;Lawler from 1963&lt;/A&gt;&amp;nbsp;(!), or check out &lt;A class="" href="http://books.google.com/books?id=yPXxPRtc8C0C&amp;amp;pg=PA28&amp;amp;lpg=PA28&amp;amp;dq=gilmore+lawler&amp;amp;source=web&amp;amp;ots=FMroC0m4Uu&amp;amp;sig=9n9fIvqjZ9e4IKx73sI_PHwt5Is&amp;amp;hl=en&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;resnum=6&amp;amp;ct=result#PPA28,M1" target=_blank mce_href="http://books.google.com/books?id=yPXxPRtc8C0C&amp;amp;pg=PA28&amp;amp;lpg=PA28&amp;amp;dq=gilmore+lawler&amp;amp;source=web&amp;amp;ots=FMroC0m4Uu&amp;amp;sig=9n9fIvqjZ9e4IKx73sI_PHwt5Is&amp;amp;hl=en&amp;amp;sa=X&amp;amp;oi=book_result&amp;amp;resnum=6&amp;amp;ct=result#PPA28,M1"&gt;Cela's book on QAP&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;In the case of QAP, the constraint is that "X" in our equation is a permutation matrix.&amp;nbsp; Permutation matrices are matrices where the rows and columns sum up to 1 and each entry is either a 0 or a 1.&amp;nbsp; The idea behind the bound is to not be so strict about these constraints.&amp;nbsp; Since QAP is a minimization problem, dropping constraints means that you're going to get a solution whose value is lower than it would otherwise have been:&amp;nbsp; a lower bound.&amp;nbsp;&amp;nbsp; Loosening these constraints (and here's where it gets hand-wavy) results in a linear assignment problem - the matrix for the LAP is formed from the input matrices (A, B, C).&amp;nbsp; Solving the linear assignment problem gives us GLB.&amp;nbsp; A few months back I wrote some code to solve linear assignment problems, so now let's use it to compute GLB.&amp;nbsp; The code is below.&amp;nbsp; A few notes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Just like the last post, LinearAlgebra.NewMatrix(n) creates a new matrix of size n.&amp;nbsp; In general, when I make reference to a method in LinearAlgebra, I assume you can write it yourself!&lt;/LI&gt;
&lt;LI&gt;LinearAssignment.ReducedCosts computes what is known as the "dual matrix" for the solution.&amp;nbsp; I won't get into the details - the important fact is that each element of the dual matrix U_ij is a kind of prediction of how much the objective function will increase when&amp;nbsp;i assign facility "i" to location "j".&amp;nbsp; In other words, if U_ij is really big, then assigning facility i to location j is probably a bad idea.&amp;nbsp; For this reason, the dual matrix (I'll just call it the "U matrix") is very useful in a branch-and-bound algorithm: it helps us make branching decisions.&lt;/LI&gt;&lt;/UL&gt;&lt;PRE&gt;    /// &amp;lt;SUMMARY&amp;gt;Computes the Gilmore-Lawler bound.&amp;lt;/SUMMARY&amp;gt;
    public class GilmoreLawler
    {
        /// &amp;lt;SUMMARY&amp;gt;Computes the Gilmore-Lawler bound.&amp;lt;/SUMMARY&amp;gt;
        /// &amp;lt;PARAM name="qap"&amp;gt;The QAP.&amp;lt;/PARAM&amp;gt;
        /// &amp;lt;PARAM name="p"&amp;gt;Primal solution.&amp;lt;/PARAM&amp;gt;
        /// &amp;lt;PARAM name="U"&amp;gt;Reduced costs matrix (dual solution).&amp;lt;/PARAM&amp;gt;
        /// &amp;lt;RETURNS&amp;gt;The Gilmore-Lawler bound of the QAP.&amp;lt;/RETURNS&amp;gt;
        public static double Bound(Qap qap, int[] p, double[][] U)
        {
            int n = qap.Size;

            // copy all elements of B_i into br_i except B_ii
            double[][] br = LinearAlgebra.NewMatrix(n, n - 1);
            for (int i = 0; i &amp;lt; n; i++)
            {
                for (int j = 0; j &amp;lt; i; j++)
                {
                    br[i][j] = qap.B[i][j];
                }
                for (int j = i + 1; j &amp;lt; n; j++)
                {
                    br[i][j - 1] = qap.B[i][j];
                }
                Array.Sort&lt;DOUBLE&gt;(br[i]);
                Array.Reverse(br[i]); // descending
            }

            // L_ij = A_ii B_jj + &lt;A'_I, B?_j&gt;_ + c_ij
            // (A'_i is computed inline below)
            double[][] L = LinearAlgebra.NewMatrix(n);
            double[] ar_i = new double[n - 1];
            for (int i = 0; i &amp;lt; n; i++)
            {
                for (int j = 0; j &amp;lt; i; j++)
                {
                    ar_i[j] = qap.A[i][j];
                }
                for (int j = i + 1; j &amp;lt; n; j++)
                {
                    ar_i[j - 1] = qap.A[i][j];
                }
                Array.Sort&lt;DOUBLE&gt;(ar_i); // ascending
                for (int j = 0; j &amp;lt; n; j++)
                {
                    double l_ij = qap.A[i][i] * qap.B[j][j] + qap.C[i][j];
                    for (int k = 0; k &amp;lt; n - 1; k++)
                    {
                        l_ij += ar_i[k] * br[j][k];
                    }
                    L[i][j] = l_ij;
                }
            }

            // Solve LAP(L) to get bound - U is the reduced costs matrix.
            int[] ip = new int[n];
            double[] ys = new double[n];
            double[] yt = new double[n];
            double bound = LinearAssignment.Solve(L, p, ip, ys, yt) + qap.Shift;
            LinearAssignment.ReducedCosts(L, U, ys, yt);
            return bound;
        }
    }
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8718377" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/QAP/default.aspx">QAP</category></item><item><title>Quadratic Assignment Problems: branch and bound</title><link>http://blogs.msdn.com/natbr/archive/2008/05/03/quadratic-assignment-problems-branch-and-bound.aspx</link><pubDate>Sat, 03 May 2008 21:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8455865</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/8455865.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=8455865</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=8455865</wfw:comment><description>&lt;P&gt;In my &lt;A class="" href="http://blogs.msdn.com/natbr/archive/2008/04/28/quadratic-assignment-problems-part-i.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2008/04/28/quadratic-assignment-problems-part-i.aspx"&gt;last post&lt;/A&gt; I introduced quadratic assignment problems.&amp;nbsp;&amp;nbsp;As I explained, the problem is to assign an equal number of facilities to locations, minimizing the transportation cost.&amp;nbsp; A compact way to write the problem is to store the "flows" in a matrix A, the "distances" in matrix B, and represent assignments as permutation matrices.&amp;nbsp; If you throw in a linear term C, then the problem can be written as:&lt;/P&gt;
&lt;P&gt;&lt;IMG title="min tr AXBX' + CX'" style="WIDTH: 167px; HEIGHT: 30px" height=30 alt="min tr AXBX' + CX'" src="http://blogs.msdn.com/photos/nathan_brixius/images/8455876/original.aspx" width=167 mce_src="http://blogs.msdn.com/photos/nathan_brixius/images/8455876/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;Branch-and-bound algorithms are the most common technique&amp;nbsp;for finding optimal solutions for QAP.&amp;nbsp;&amp;nbsp;The next few posts will focus on describing how branch-and-bound works and will result in a complete implementation of&amp;nbsp;a QAP solver in C#.&amp;nbsp; Branch-and-bound is a "divide and conquer" solution technique for combinatorial problems. Branch-and-bound repeatedly divides a problem into simpler subproblems of the same type, which are then solved or further subdivided. The search space of a problem is partitioned into search spaces for its subproblems. The algorithm generates a search tree with the root corresponding to the original problem to be solved.&amp;nbsp; At each node in the search tree, a relaxed version of the subproblem is solved, typically by loosening the constraints of the subproblem. The solution to the relaxation is a lower bound to the original subproblem. If a lower bound at a given node exceeds the value of a previously known solution, then continued searching on this path cannot lead to an improved solution, and there's no need to continue searching on that node's subtree (this is called "fathoming"). &lt;/P&gt;
&lt;P&gt;A little less formally, we take the search space and divide it into subregions.&amp;nbsp; Then for each piece, we solve a "relaxed" version of the problem to see if we can rule out the solution lying in that subregion.&amp;nbsp; If we can't rule it out, we divide the subregion into pieces and repeat.&amp;nbsp; The "relaxation" part is bounding, the dividing is called branching.&amp;nbsp; The effectiveness of a branch-and-bound algorithm depends on 1) the strength of the bound, 2) how fast bounds can be computed, and 3) the branching decisions.&amp;nbsp; For example, if the bound is terrible we'll never fathom subproblems and we'll end up searching the entire tree. &lt;/P&gt;
&lt;P&gt;So how do we apply branch-and-bound to QAP?&amp;nbsp; The solution to a QAP is an assignment of facilities to locations.&amp;nbsp; Therefore the subproblems are obtained by assigning some of the facilities to locations.&amp;nbsp; To branch, I can pick a facility and try assigning it to each of the available locations (or vice-versa).&amp;nbsp; As we will see, the logic for selecting which facility/location to branch on is extremely important.&lt;/P&gt;
&lt;P&gt;Let's start putting together some of the pieces of our branch-and-bound solver for QAP.&amp;nbsp; First, let's define a QAP, which as I said before consists of the flow and distance matrices A and B, and a linear term C.&lt;/P&gt;&lt;PRE&gt;    /// &lt;SUMMARY&gt;A quadratic assignment problem.&lt;/SUMMARY&gt;
    public class Qap
    {
        /// &lt;SUMMARY&gt;A (flow matrix).&lt;/SUMMARY&gt;
        public double[][] A { get; set; }
        /// &lt;SUMMARY&gt;B (distance matrix).&lt;/SUMMARY&gt;
        public double[][] B { get; set; }
        /// &lt;SUMMARY&gt;C (linear costs).&lt;/SUMMARY&gt;
        public double[][] C { get; set; }
        /// &lt;SUMMARY&gt;Constant term.&lt;/SUMMARY&gt;
        public double Shift { get; set; }

        /// &lt;SUMMARY&gt;Size of (A, B, C) matrices.&lt;/SUMMARY&gt;
        public int Size
        {
            get { return A.Length; }
        }

        /// &lt;SUMMARY&gt;Compute tr AXBX' + CX', where the permutation matrix X is determined by p.&lt;/SUMMARY&gt;
        public double Evaluate(int[] p)
        {
            double obj = this.Shift;
            for (int i = 0; i &amp;lt; A.Length; i++)
            {
                obj += this.C[i][p[i]];
                for (int j = 0; j &amp;lt; A[i].Length; j++)
                {
                    obj += this.A[i][j] * this.B[p[i]][p[j]];
                }
            }
            return obj;
        }
    }
&lt;/PRE&gt;
&lt;P&gt;To make the code shorter I am using C# 3.0 &lt;A class="" href="http://weblogs.asp.net/scottgu/archive/2007/03/08/new-c-orcas-language-features-automatic-properties-object-initializers-and-collection-initializers.aspx" target=_blank mce_href="http://weblogs.asp.net/scottgu/archive/2007/03/08/new-c-orcas-language-features-automatic-properties-object-initializers-and-collection-initializers.aspx"&gt;automatic properties&lt;/A&gt;. In addition to the matrices I have also added a constant term "Shift", whose purpose will become clear in a moment.&amp;nbsp; I've also provided a method called Evaluate() that computes the objective given a permutation.&amp;nbsp; Let's think about how branching works.&amp;nbsp; If we go back to the mathematical formulation of QAP at the start of this post, assigning a facility to a location means setting X_ij = 1.&amp;nbsp; If we plug X_ij into the formula above we see that we end up with a QAP of size n - 1 with:&lt;/P&gt;
&lt;P&gt;A′ = A(ii)&lt;BR&gt;B′ = B(jj)&lt;BR&gt;C′ = C(ij) + 2 a_i b_j ,&lt;BR&gt;Shift' = A[i][i] B[j][j] + C[i][j] + Shift&lt;/P&gt;
&lt;P&gt;Where&amp;nbsp; A(ij) denotes matrix A with row i and column j removed, a_i are the elements in row i of A, excluding A[i][i], and let b_j are the elements in column j of B, excluding b[j][j]. Here's the code:&lt;/P&gt;&lt;PRE&gt;private static Qap Reduce(Qap qap, int i, int j)
{
    Qap r = new Qap();

    r.A = Reduce(qap.A, i, i);
    r.B = Reduce(qap.B, j, j);
    r.C = Reduce(qap.C, i, j);

    // Tack on: 2 a'_i b'_j (where a'_i is row i of A, with element i removed)
    for (int ii = 0; ii &amp;lt; r.Size; ii++)
    {
        for (int jj = 0; jj &amp;lt; r.Size; jj++)
        {
            r.C[ii][jj] += 2 * qap.A[i][ii &amp;lt; i ? ii : ii + 1] * qap.B[jj &amp;lt; j ? jj : jj + 1][j];
        }
    }

    r.Shift = qap.Shift + qap.A[i][i] * qap.B[j][j] + qap.C[i][j];

    return r;
}

private static double[][] Reduce(double[][] M, int i, int j)
{
    double[][] R = LinearAlgebra.NewMatrix(M.Length - 1);
    for (int ii = 0; ii &amp;lt; R.Length; ii++)
    {
        for (int jj = 0; jj &amp;lt; R[ii].Length; jj++)
        {
            R[ii][jj] = M[ii &amp;lt; i ? ii : ii + 1][jj &amp;lt; j ? jj : jj + 1];
        }
    }
    return R;
}
&lt;/PRE&gt;
&lt;P&gt;LinearAlgebra.NewMatrix() is a helper function that initializes the matrix. So now we have a data structure for QAP, and we now how to obtain subproblems.&amp;nbsp; Next time we'll look at how to compute lower bounds.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8455865" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/QAP/default.aspx">QAP</category></item><item><title>Quadratic Assignment Problems, Part I</title><link>http://blogs.msdn.com/natbr/archive/2008/04/28/quadratic-assignment-problems-part-i.aspx</link><pubDate>Tue, 29 Apr 2008 05:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8436452</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/natbr/comments/8436452.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=8436452</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=8436452</wfw:comment><description>&lt;P&gt;In a previous series I talked a bit about linear assignment problems (LAPs) and provided code for a simple LAP solver.&amp;nbsp; Now I want to spend a few posts on LAP's big brother, the Quadratic Assignment Problem.&amp;nbsp; In an LAP we are trying to assign objects in one set to an equal number of objects in another set, where we are given the cost of assigning any pair of objects.&amp;nbsp; In QAP we still have two sets of objects - and I will stick with the original formulation of the problem (from the 50's) and call the first step of objects "facilities" and the second set "locations".&amp;nbsp; Imagine that we are going to build a bunch of computer labs in different rooms of a building, for example.&amp;nbsp; Suppose that each lab has a different purpose, and the rooms are wired up and we're trying to figure out where to put each lab.&amp;nbsp; The quadratic assignment problem is the problem of finding an assignment &lt;BR&gt;of an equal number of facilities to locations that minimizes the transportation cost between facilities.&amp;nbsp; In my example, the transportation cost is a product of how far the rooms are from each other and how often&amp;nbsp;one travels&amp;nbsp;from one lab to the other.&lt;/P&gt;
&lt;P&gt;QAPs are interesting problems in part because they are so difficult to solve.&amp;nbsp; Finding the optimal assignment is an NP-hard problem.&amp;nbsp; In upcoming posts I will write down the problem more formally, and explore some heuristics for QAP, as well as some tools for finding exact solutions for QAP.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8436452" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/QAP/default.aspx">QAP</category></item><item><title>Linear assignment problems, part III</title><link>http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-iii.aspx</link><pubDate>Thu, 09 Aug 2007 20:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4312460</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/natbr/comments/4312460.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=4312460</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=4312460</wfw:comment><description>&lt;P&gt;Here's the code. See the &lt;A class="" title=disclaimer href="http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-ii.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-ii.aspx"&gt;previous posting&lt;/A&gt; for background.&lt;/P&gt;&lt;PRE&gt;using System;

namespace NathanBrixius.AssignmentLib
{
    /// &amp;lt;summary&amp;gt;Linear assignment problem solver.&amp;lt;summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;
    /// This code is a port of Fortran code by R.E. Burkard and U. Derigs. 
    /// Assignment and matching problems: Solution methods with fortran programs, 
    /// volume 184 of Lecture Notes in Economics and Mathematical Systems. 
    /// Springer, Berlin, 1980.  The original code is available on the QAPLIB site.
    /// &amp;lt;/remarks&amp;gt;
    public class LinearAssignment
    {
        public static void Main(params string[] args)
        {
            double[][] L = new double[5][];
            for (int i = 0; i &amp;lt; L.Length; i++)
            {
                L[i] = new double[5];
                for (int j = 0; j &amp;lt; L[i].Length; j++)
                {
                    L[i][j] = i + j;
                }
            }
            int[] p = new int[L.Length];
            int[] ip = new int[L.Length];
            double[] ys = new double[L.Length];
            double[] yt = new double[L.Length];
            Solve(L, p, ip, ys, yt);
        }

        /// &amp;lt;summary&amp;gt;Evaluate a permutation against the given LAP.&amp;lt;summary&amp;gt;
        /// &amp;lt;param name="L"&amp;gt;LAP cost matrix.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="p"&amp;gt;Permutation.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;The cost of the permutation.&amp;lt;/returns&amp;gt;
        public static double Evaluate(double[][] L, int[] p)
        {
            double cost = 0.0;
            for (int i = 0; i &amp;lt; p.Length; i++)
            {
                cost += L[i][p[i]];
            }
            return cost;
        }

        /// &amp;lt;summary&amp;gt;Calculate the reduced costs matrix for the given LAP and solution.&amp;lt;summary&amp;gt;
        /// &amp;lt;param name="L"&amp;gt;LAP cost matrix.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="U"&amp;gt;Reduced cost matrix (filled in by the method)&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="ys"&amp;gt;Dual variables.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="yt"&amp;gt;Dual variables.&amp;lt;/param&amp;gt;
        public static void ReducedCosts(
            double[][] L,
            double[][] U,
            double[] ys,
            double[] yt)
        {
            for (int i = 0; i &amp;lt; L.Length; i++)
            {
                for (int j = 0; j &amp;lt; L[i].Length; j++)
                {
                    U[i][j] = L[i][j] - (yt[j] + ys[i]);

                }
            }
        }

        /// &amp;lt;summary&amp;gt;Solve the specified linear assignment problem.&amp;lt;summary&amp;gt;
        /// &amp;lt;param name="L"&amp;gt;LAP cost matrix.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="p"&amp;gt;The solution permutation.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="ip"&amp;gt;The inverse of the solution permutation.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="ys"&amp;gt;Dual variables.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="yt"&amp;gt;Dual variables.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        public static double Solve(
            double[][] L,
            int[] p,
            int[] ip,
            double[] ys,
            double[] yt
            )
        {
            if (L.Length == 0)
            {
                return 0.0;
            }
            return SolveCore(L, ip, p, ys, yt, 1.0e-7);
        }

        /// &amp;lt;summary&amp;gt;Linear sum assignment problem with double precision costs.&amp;lt;summary&amp;gt;
        /// &amp;lt;param name="L"&amp;gt;Cost matrix.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="ip"&amp;gt;Inverse of optimal assignment.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="p"&amp;gt;Optimal assignment.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="ys"&amp;gt;Optimal dual (row) variables.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="yt"&amp;gt;Optimal dual (column) variables.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="tolerance"&amp;gt;Machine accuracy.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;The optimal cost.&amp;lt;/returns&amp;gt;
        private static double SolveCore(
            double[][] L,
            int[] ip,
            int[] p,
            double[] ys,
            double[] yt,
            double tolerance
            )
        {
            const int BadIndex = -1;
            int[] vor = new int[L.Length];
            bool[] label = new bool[L.Length];
            double[] dMinus = new double[L.Length];
            double[] dPlus = new double[L.Length];

            // Start: Construction of an initial (partial) assignment.
            // (partial --&amp;gt; p[i]/ip[j] may be BadIndex for some i,j)
            double maxValue = 1.0e15;
            for (int i = 0; i &amp;lt; p.Length; i++)
            {
                ip[i] = BadIndex;
                p[i] = BadIndex;
                vor[i] = BadIndex;
                ys[i] = 0;
                yt[i] = 0;
            }

            double ui = 0.0;
            int jOpt = -1; // optimal j index
            for (int i = 0; i &amp;lt; L.Length; i++)
            {
                for (int j = 0; j &amp;lt; L[i].Length; j++)
                {
                    if ((j == 0) || (L[i][j] - ui &amp;lt; tolerance))
                    {
                        ui = L[i][j];
                        jOpt = j;
                    }
                }

                // guarantee: jOpt &amp;gt;= 0
                ys[i] = ui;
                if (ip[jOpt] == BadIndex)
                {
                    ip[jOpt] = i;
                    p[i] = jOpt;
                }
            }

            for (int j = 0; j &amp;lt; ip.Length; j++)
            {
                if (ip[j] == BadIndex)
                {
                    yt[j] = maxValue;
                }
            }

            for (int i = 0; i &amp;lt; ys.Length; i++)
            {
                ui = ys[i];
                for (int j = 0; j &amp;lt; yt.Length; j++)
                {
                    double vj = yt[j];
                    if (vj &amp;gt; tolerance)
                    {
                        double cc = L[i][j] - ui;
                        if (cc + tolerance &amp;lt; vj)
                        {
                            yt[j] = cc;
                            vor[j] = i;
                        }
                    }
                }
            }

            for (int j = 0; j &amp;lt; vor.Length; j++)
            {
                int i = vor[j];
                if ((i != BadIndex) &amp;amp;&amp;amp; (p[i] == BadIndex))
                {
                    p[i] = j;
                    ip[j] = i;
                }
            }

            for (int i = 0; i &amp;lt; p.Length; i++)
            {
                if (p[i] == BadIndex)
                {
                    ui = ys[i];
                    for (int j = 0; j &amp;lt; ip.Length; j++)
                    {
                        if (ip[j] == BadIndex)
                        {
                            double lij = L[i][j];
                            if ((lij - ui - yt[j] + tolerance) &amp;lt;= 0)
                            {
                                p[i] = j;
                                ip[j] = i;
                            }
                        }
                    }
                }
            }

            // Construction of the optimal assignment
            double d = 0.0;
            int w = BadIndex;
            int index = BadIndex;
            for (int u = 0; u &amp;lt; p.Length; u++)
            {
                if (p[u] == BadIndex)
                {
                    // Shortest path computation
                    for (int i = 0; i &amp;lt; vor.Length; i++)
                    {
                        vor[i] = u;
                        label[i] = false;
                        dPlus[i] = maxValue;
                        dMinus[i] = L[u][i] - ys[u] - yt[i];
                    }
                    dPlus[u] = 0;

                    bool done = false;
                    while (!done)
                    {
                        d = maxValue;
                        for (int i = 0; i &amp;lt; dMinus.Length; i++)
                        {
                            if (!label[i] &amp;amp;&amp;amp; (dMinus[i] + tolerance &amp;lt; d))
                            {
                                d = dMinus[i];
                                index = i;
                            }
                        }

                        // note: index &amp;gt;= 0
                        if (ip[index] != BadIndex)
                        {
                            label[index] = true;
                            w = ip[index];
                            dPlus[w] = d;
                            for (int i = 0; i &amp;lt; label.Length; i++)
                            {
                                if (!label[i])
                                {
                                    double vgl = d + L[w][i] - ys[w] - yt[i];
                                    if (dMinus[i] &amp;gt; vgl + tolerance)
                                    {
                                        dMinus[i] = vgl;
                                        vor[i] = w;
                                    }
                                }
                            }
                        }
                        else
                        {
                            done = true;
                        }
                    }

                    // Augmentation
                    done = false;
                    while (!done)
                    {
                        w = vor[index];
                        ip[index] = w;
                        int tempIndex = p[w];
                        p[w] = index;
                        if (w == u)
                        {
                            done = true;
                        }
                        else
                        {
                            index = tempIndex;
                        }
                    }

                    // Transformation
                    for (int i = 0; i &amp;lt; dPlus.Length; i++)
                    {
                        if (dPlus[i] != maxValue)
                        {
                            ys[i] += d - dPlus[i];
                        }

                        if (dMinus[i] + tolerance &amp;lt; d)
                        {
                            yt[i] += dMinus[i] - d;
                        }
                    }
                }
            }

            // Computation of the optimal value
            return Evaluate(L, p);
        }
    }
}
&lt;/PRE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4312460" 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>Linear assignment problems, part II</title><link>http://blogs.msdn.com/natbr/archive/2007/08/09/linear-assignment-problems-part-ii.aspx</link><pubDate>Thu, 09 Aug 2007 20:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4312406</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/natbr/comments/4312406.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=4312406</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=4312406</wfw:comment><description>&lt;P&gt;In a &lt;A class="" title="Part 1" href="http://blogs.msdn.com/natbr/archive/2007/07/02/linear-assignment-problems-part-i.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2007/07/02/linear-assignment-problems-part-i.aspx"&gt;previous post&lt;/A&gt; I talked a bit about the linear assignment problem:&amp;nbsp; finding the minimum cost matching in a bipartite graph.&amp;nbsp; In my next post I will give a simple self-contained C# program for solving LAP based on some Fortran code from my colleague &lt;A class="" title=Burkard href="http://www.opt.math.tu-graz.ac.at/burkard/" target=_blank mce_href="http://www.opt.math.tu-graz.ac.at/burkard/"&gt;Rainer Burkard&lt;/A&gt;.&amp;nbsp; First a few notes and disclaimers!&lt;/P&gt;
&lt;P&gt;The input to the code is a matrix which represents the adjacency matrix of the graph.&amp;nbsp; In my application (solving quadratic assignment problems) I am concerned with input matrices that are relatively small and dense.&amp;nbsp;&amp;nbsp; The code is a port of Fortran code by Burkard and Ulrich Derigs:&amp;nbsp; &lt;A class="" title="Paper reference" href="http://www.opt.math.tu-graz.ac.at/burkard/art_proc.htm" target=_blank mce_href="http://www.opt.math.tu-graz.ac.at/burkard/art_proc.htm"&gt;Assignment and matching problems: Solution methods with Fortran programs&lt;/A&gt;,&amp;nbsp;volume 184 of Lecture Notes in Economics and Mathematical Systems.&amp;nbsp; Springer, Berlin, 1980.&amp;nbsp; The original code is available on the &lt;A class="" title=QAPLIB href="http://www.seas.upenn.edu/qaplib/codes.html" target=_blank mce_href="http://www.seas.upenn.edu/qaplib/codes.html"&gt;QAPLIB site&lt;/A&gt;.&amp;nbsp; Rainer has given me permission to post this code, although if you look at the terms on the original you will see that it is freely distributable.&amp;nbsp; This code is offered under the same conditions and I make no claims about its correctness, value, etc.&amp;nbsp; But it works okay for me.&lt;/P&gt;
&lt;P&gt;My port is relatively "conservative" in that I have tried to retain the original structure and flow as much as possible because I don't want to introduce any bugs.&amp;nbsp; I want to keep the implementation clean, so like many numerical optimization codes there isn't much input validation.&amp;nbsp; I have chosen to use arrays rather than trying to encapsulate the input and output into matrix and vector classes.&amp;nbsp; I kept it simple so you can adapt it to your needs.&lt;/P&gt;
&lt;P&gt;Lastly, I wanted to mention that this is not the most efficient LAP solver available.&amp;nbsp; At the time I wrote my thesis the fastest code over the domain I was working on was the code of Jonker and Volgenant, which is available on &lt;A class="" title="JV code" href="http://www.magiclogic.com/assignment.html" target=_blank mce_href="http://www.magiclogic.com/assignment.html"&gt;this site&lt;/A&gt;.&amp;nbsp; I notice that the code is used by others as well, see &lt;A class="" href="http://mit.edu/harold/www/code.html" target=_blank mce_href="http://mit.edu/harold/www/code.html"&gt;here&lt;/A&gt; and &lt;A class="" href="http://adsabs.harvard.edu/abs/1997SPIE.3068..228M" target=_blank mce_href="http://adsabs.harvard.edu/abs/1997SPIE.3068..228M"&gt;here&lt;/A&gt;.&amp;nbsp; This code is really quite slick and I had a great experience working with it all those years ago.&amp;nbsp; It's not hard to port it over to C#, so go for it!&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4312406" 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>Linear assignment problems, part I</title><link>http://blogs.msdn.com/natbr/archive/2007/07/02/linear-assignment-problems-part-i.aspx</link><pubDate>Mon, 02 Jul 2007 23:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3663736</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/natbr/comments/3663736.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=3663736</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=3663736</wfw:comment><description>&lt;P&gt;I'm going to devote a few posts to my thesis topic, the &lt;A class="" title=QAP href="http://en.wikipedia.org/wiki/Quadratic_assignment_problem" target=_blank mce_href="http://en.wikipedia.org/wiki/Quadratic_assignment_problem"&gt;quadratic assignment problem&lt;/A&gt;.&amp;nbsp; Quadratic assignment problems are a type of matching problem that are NP hard and have some interesting applications.&amp;nbsp; I'll start out by describing linear assignment problems, which are simpler but still fun.&lt;/P&gt;
&lt;P&gt;As the name suggests, in a linear assignment problem objects in one set are to be assigned to an equal number of objects in a second set. The cost of assigning objects in the first set to objects in the second set are given, and the objective is to find the assignment that minimizes the total assignment cost.&amp;nbsp; For example, the problem may be to assign workers to jobs so as to minimize the total amount of working time.&amp;nbsp; A more formal description of the problem can be found on &lt;A class="" title=LAP href="http://www.assignmentproblem.com/linearAP.htm" target=_blank mce_href="http://www.assignmentproblem.com/linearAP.htm"&gt;this page&lt;/A&gt; (and I recommend the book, BTW).&lt;/P&gt;
&lt;P&gt;LAP can also be posed as the problem of finding the minimum cost matching on a bipartite graph.&amp;nbsp; For this reason, in algorithms texts this problem is also sometimes referred to as “minimum cost weighted bipartite matching”.&amp;nbsp; LAPs are linear programs and so they can be solved in polynomial time.&amp;nbsp; As the &lt;A class="" title="Wikipedia LAP" href="http://en.wikipedia.org/wiki/Assignment_problem" target=_blank mce_href="http://en.wikipedia.org/wiki/Assignment_problem"&gt;wikipedia article&lt;/A&gt; on the problem states,&amp;nbsp;there are algorithms that take advantage of the special structure of LAP to solve them more efficiently than general purpose LP solvers.&lt;/P&gt;
&lt;P&gt;Next time I'll go through one possible solution approach for LAP.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3663736" width="1" height="1"&gt;</description><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></channel></rss>