<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>BlackBox : Math DSL beginning</title>
    <link>http://www.warneronstine.com/blog/articles/2007/11/23/math-dsl-beginning</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Where technology and art disappear</description>
    <item>
      <title>Math DSL beginning</title>
      <description>&lt;p&gt;I decided to start working on this taking one of the examples I worked out for the book for math Sets (partially incomplete due to Groovy&amp;#8217;s inability to directly override &lt;code&gt;lessThan&lt;/code&gt;, &lt;code&gt;lessThanEquals&lt;/code&gt;, &lt;code&gt;greaterThan&lt;/code&gt;, &lt;code&gt;greaterThanEquals&lt;/code&gt;) and to put into code some of the techniques I was learning in my Linear Algebra class. &lt;/p&gt;

&lt;p&gt;So far I&amp;#8217;ve implemented the following into my matrix math DSL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Matrix/Row equality - allows you to test if two matrices or rows are equal (i.e. - contain the same ordered set of numbers)&lt;/li&gt;
&lt;li&gt;Matrix addition/subtraction - You can add two matrices together if they are the same dimensions (2x2, 2x3, whatever, as long as the match in row and columns)&lt;/li&gt;
&lt;li&gt;Matrix/Row scalar multiplication - You can multiply a scalar value against a row or matrix&lt;/li&gt;
&lt;li&gt;Matrix multiplication - You can multiply two matrices together if the first matrix A&amp;#8217;s (say 2x3) columns match B&amp;#8217;s  rows of the matrix you are multiplying against (say 3x2) which will produce a 2x2 matrix. If you did BxA then you would end up with a new matrix of 3x3&lt;/li&gt;
&lt;li&gt;Matrix powers - If the matrix is square (say 3x3) you can multiply it by itself to get the power of the matrix&lt;/li&gt;
&lt;li&gt;Left-shift operation - be able to dynamically create a Row or Matrix by adding new elements to the end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I still have a lot of work which is laid out on my Trac site for &lt;a href="http://warneronstine.com/groovymath/roadmap"&gt;GroovyMath&lt;/a&gt; which leads me to my next conundrum. &lt;/p&gt;

&lt;p&gt;When dealing with matrices you need to do a lot of Reduced Echelon Form (REF) or Row Reduced Echelon Form (RREF) this consists of taking one of two Elementary Row Operations (EROs) and applying it to a row to get a matrix in the form of a diagonal (all 1s down the upper-left to lower-right diagonal with 0s everywhere else) or getting it into an upper-diagonal form (0s below the diagonal and integers everywhere else). The two EROs that you can consist of a) row interchange, where you can exchange one row with another; and b) row addition, where you can add one row to another multiplying that row by a scalar. What I would like to be able to do is something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def A = new Matrix(//rows go in here)
A.r1 + A.r2*2 //which will add 2 times the second row and add it to the first and replace it
A.r1 % A.r2 //which will exchange rows 1 and 2 with each other
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another thought I had was to do this in some kind of &amp;#8220;rowOperations&amp;#8221; closure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def A = new Matrix(//rows go in here)
A.rowOperations {
    r1 + r2*2
    r1 % r2
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which definitely reads better than the first (and of course that&amp;#8217;s all part of a DSL how well does it translate the native tongue into code). But the issue that I have with either of these approaches (maybe, still ironing out the second in my head) is that the properties r1 and r2 don&amp;#8217;t exist. These property accessors will need to be intercepted. Ok, not a big deal. But if I choose to implement this in MatrixRow (i.e. - actually return the row itself) it doesn&amp;#8217;t allow me to modify the originating matrix (A in this case) only change the row. For the addition problem I think I can get around it as it is executing in a closure, but the row interchange is an issue. The individual rows don&amp;#8217;t know they&amp;#8217;re a part of a matrix and I&amp;#8217;m not sure that knowing it allows them to do anything.&lt;/p&gt;

&lt;p&gt;Anyways, just wrestling with this concept right now as it is key to moving on to the more advanced functionality in my matrix math. Any suggestions are more than welcome. One new feature that I really like will be overriding the &lt;code&gt;or&lt;/code&gt; operator to provide Augmented Matrices (another key part). Normally you define an augmented matrix in one of three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A|0&lt;/code&gt; - add a column of all zeros&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|b&lt;/code&gt; - add a vector as the augmented matrix&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A|I&lt;/code&gt; - add an Identity matrix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two are used to solve the set of linear equations and a bunch of other things. The second is used to find the inverse of the matrix as you transform through EROs the matrix &lt;code&gt;A&lt;/code&gt; so that it equals &lt;code&gt;I&lt;/code&gt; (the identity matrix) and then the side that &amp;#8220;I&amp;#8221; was on now equals the inverse of &lt;code&gt;A&lt;/code&gt;. I would say stop me if I&amp;#8217;m boring you but it&amp;#8217;s probably too late for that. I just wanted to point out how cool it was I can override the &lt;code&gt;or&lt;/code&gt; operator to do something completely different that makes perfect sense in my given domain.&lt;/p&gt;</description>
      <pubDate>Fri, 23 Nov 2007 18:11:12 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:a393a739-cbd5-423b-8877-07cd92ff46fc</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2007/11/23/math-dsl-beginning</link>
      <category>programming</category>
      <category>linear_algebra</category>
      <category>math</category>
      <category>matrix</category>
      <category>groovy</category>
      <category>dsl</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/305</trackback:ping>
    </item>
    <item>
      <title>"Math DSL beginning" by Yann Richet</title>
      <description>&lt;p&gt;Hi,&lt;/p&gt;

&lt;p&gt;I've started to work on similar issues (math dsl) a few weeks ago. You can get my work named groovylab on the front page of groovy project.&lt;/p&gt;

&lt;p&gt;It also includes a simple plotter and is based on a pure java API to perform math calculations (to reduce performance issues).&lt;/p&gt;

&lt;p&gt;Here is a little preview of what is already possible with groovylab:&lt;/p&gt;

&lt;p&gt;Following access (i.e. set/get) are possible:
        x = M[1][2]
        x = M[-1][2]        // where -1 stands for last row index
        x = M[1][-2]        // where -2 stands for last column index
        x = M[-1][2]        // where -1 stands for last row index
        x = M[-1][-2]       // where -1 stands for last row index, -2 stands for last column index
        X = M[1..4][2..3]
        X = M[4..1][2..3]   // thus reverting rows order
        X = M[1..-1][-2..3]
        X = diagonal(Matrix)            // get diagonal of Matrix, alias to diag(Matrix)
        X = diagonal(Matrix, int order)     // get order diagonal of Matrix, alias to diag(Matrix, int)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    M[1][2] = x         // set x value at first row, second column
    M[-1][2] = x        // set x value at last row, second column
    M[1..2][2..5] = [[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4]]
    M[2..1][2..5] = [[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4]]   // thus reverting rows order

Following operators are available:
    Matrix + Matrix
    Matrix + Number
    Matrix - Matrix
    Matrix - Number
    Matrix * Matrix
    Matrix * Number
    Matrix / Matrix
    Matrix / Number
    Matrix ** int"

Following static operations are available:
    sum(Matrix)
    prod(Matrix)
    cumsum(Matrix)
    cumprod(Matrix)
    inverse(Matrix)
    solve(Matrix A, Matrix b)   //returns X Matrix verifying A*X = b. if 
    rank(Matrix)
    trace(Matrix)
    det(Matrix)
    cond(Matrix)
    norm1(Matrix)
    norm2(Matrix)
    normF(Matrix)
    normInf(Matrix)

Following static Linear Algebra (from JAMA) are available:
    Cholesky decomposition:
        Cholesky_L(Matrix)
        Cholesky_SPD(Matrix)
    QR decomposition:
        QR_Q(Matrix)
        QR_H(Matrix)
        QR_R(Matrix)
    LU decomposition:
        LU_L(Matrix)
        LU_U(Matrix)
        LU_P(Matrix)
    Singular values decomposition:
        Singular_S(Matrix)
        Singular_U(Matrix)
        Singular_V(Matrix)
        Singular_values(Matrix)
    Eigenvalues decomposition:
        Eigen_D(Matrix)
        Eigen_V(Matrix)

Following static constructors are available:
    matrix(double[][])
    matrix(double[])    // one row Matrix constructor
    matrix(ArrayList)   // compatible with ArrayList of Numbers or ArrayList of ArrayList of Numbers

    identity(int n)         // identity Matrix of size n*n alias to id(int n)
    diagonal(int, double)   // diagonal Matrix of constant values, alias to diag(int, double)
    diagonal(double[])      // diagonal Matrix with given diagonal values, alias to diag(double[])
    one(int, int)           // constant Matrix of given size, filled with 1.0 values 
    fill(int, int, double)  // constant Matrix of given size, filled with given values 
    increment(int, int, double begin, double pitch) // Matrix of given size with row incrementing values from given beginning value wsith given pitch increment
    increment(int, int, double[] begin, double[] pitch) // Matrix of given size with row incrementing values from given beginning values wsith given pitchs increment

Following statistic sample constructors are available (random generator from RngPack):
    random(int, int)                                // independant random values (between 0.0 and 1.0) Matrix of given size, alias to rand(int, int)
    random(int, int, double min, double max)        // independant random values (between min and max) Matrix of given size, alias to rand(int, int, double min, double max)
    randomUniform(int m, int n, double min, double max)  
    randomDirac(int m, int n, double[] values, double[] prob)  
    randomNormal(int m, int n, double mu, double sigma)  
    randomChi2(int m, int n, int d)  
    randomLogNormal(int m, int n, double mu, double sigma)  
    randomExponential(int m, int n, double lambda)  
    randomTriangular(int m, int n, double min, double max)  
    randomTriangular(int m, int n, double min, double med, double max)  
    randomBeta(int m, int n, double a, double b)  
    randomCauchy(int m, int n, double mu, double sigma)  
    randomWeibull(int m, int n, double lambda, double c)  

Following static sort/find methods are available:
    sort(Matrix)
    sort(Matrix, int columnIndex)
    min(Matrix)
    max(Matrix)

Following static transformation methods are available:
    transpose(Matrix)   // alias to t(Matrix)
    resize(Matrix, int, int)
    rowsMatrix &amp;gt;&amp;gt; Matrix    // appends rowsMatrix to Matrix at last position (i.e. add last row)
    columnsMatrix &amp;gt;&amp;gt;&amp;gt; Matrix    // appends columnsMatrix to Matrix at last position (i.e. add last column)
    Matrix &amp;lt;&amp;lt; rowsMatrix    // appends rowsMatrix to Matrix at first position (i.e. add first row)

Following static statistic sample methods are available:
    mean(Matrix)
    variance(Matrix)
    covariance(Matrix,Matrix)
    correlation(Matrix,Matrix)
&lt;/code&gt;&lt;/pre&gt;</description>
      <pubDate>Sat, 24 Nov 2007 13:55:24 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:5c217444-0189-46c5-9592-2913ec5c8b18</guid>
      <link>http://www.warneronstine.com/blog/articles/2007/11/23/math-dsl-beginning#comment-44</link>
    </item>
  </channel>
</rss>
