<?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 : linear algebra</title><link>http://blogs.msdn.com/natbr/archive/tags/linear+algebra/default.aspx</link><description>Tags: linear algebra</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><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></channel></rss>