Skip to content
Browse files

term ordering comparer

1 parent a5bc8a7 commit 4f8875a4e272c5c488afee7def115c1480e9eb56 @cdrnet cdrnet committed May 14, 2009
View
1 src/app/MathNet.Palladium/MathNet.Palladium.csproj
@@ -52,6 +52,7 @@
<Compile Include="Arithmeric.cs" />
<Compile Include="Exponential.cs" />
<Compile Include="ExpressionBuilder.cs" />
+ <Compile Include="Ordering.cs" />
<Compile Include="Output\MathMLContentMarkupFormatter.cs" />
<Compile Include="PartialDerivative.cs" />
<Compile Include="Trigonometry.cs" />
View
140 src/app/MathNet.Palladium/Ordering.cs
@@ -0,0 +1,140 @@
+//-----------------------------------------------------------------------
+// <copyright file="Ordering.cs" company="Math.NET Project">
+// Copyright (c) 2002-2009, Christoph Rüegg.
+// All Right Reserved.
+// </copyright>
+// <author>
+// Christoph Rüegg, http://christoph.ruegg.name
+// </author>
+// <product>
+// Math.NET Palladium, part of the Math.NET Project.
+// http://mathnet.opensourcedotnet.info
+// </product>
+// <license type="opensource" name="LGPL" version="2 or later">
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2 of the License, or
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// </license>
+//-----------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace MathNet.ExpressionAlgebra
+{
+ public class Ordering : IComparer<Expression>
+ {
+ /// <summary>
+ /// Compare two terms for ordering (i.e. "2*x", not "x*2").
+ /// </summary>
+ /// <remarks>
+ /// Only the top expression node is analyzed, this method is therefore
+ /// not intended (and can't be used) for comparing two expression trees for equality.
+ /// </remarks>
+ public static int Compare(Expression x, Expression y)
+ {
+ // ordering by type
+ int comparison = Assess(x) - Assess(y);
+ if(comparison != 0)
+ {
+ return comparison;
+ }
+
+ // if same type, ordering by name (if it has a name)
+ string nameX = NameOfExpression(x);
+ string nameY = NameOfExpression(y);
+
+ return string.Compare(nameX, nameY, StringComparison.Ordinal);
+ }
+
+ /// <summary>
+ /// Returns a simple ordering priority score based on the term type.
+ /// </summary>
+ static int Assess(Expression term)
+ {
+ if(term == null)
+ {
+ throw new ArgumentNullException("term");
+ }
+
+ ConstantExpression constExpr = term as ConstantExpression;
+ if(constExpr != null)
+ {
+ if((constExpr.Type == typeof(int)) || (constExpr.Type == typeof(long)))
+ {
+ return 1;
+ }
+
+ if((constExpr.Type == typeof(double)) || (constExpr.Type == typeof(float)))
+ {
+ return 2;
+ }
+
+ return 3;
+ }
+
+ if(term is ParameterExpression)
+ {
+ return 10;
+ }
+
+ if(term is MethodCallExpression)
+ {
+ return 200;
+ }
+
+ BinaryExpression binaryExpr = term as BinaryExpression;
+ if(binaryExpr != null)
+ {
+ switch(binaryExpr.NodeType)
+ {
+ case ExpressionType.Multiply:
+ return 20;
+ case ExpressionType.Add:
+ case ExpressionType.Subtract:
+ return 21;
+ case ExpressionType.Divide:
+ return 22;
+ }
+ }
+
+ return 100;
+ }
+
+ /// <summary>
+ /// Tries to find and return the term's name, if it is named (i.e. a parameter or a method call).
+ /// </summary>
+ static string NameOfExpression(Expression term)
+ {
+ ParameterExpression paramExpr = term as ParameterExpression;
+ if(paramExpr != null)
+ {
+ return paramExpr.Name;
+ }
+
+ MethodCallExpression methodExpr = term as MethodCallExpression;
+ if(methodExpr != null)
+ {
+ return methodExpr.Method.Name;
+ }
+
+ return null;
+ }
+
+ int IComparer<Expression>.Compare(Expression x, Expression y)
+ {
+ return Compare(x, y);
+ }
+ }
+}
View
3 src/test/MathNet.Palladium.Test/MathNet.Palladium.Test.csproj
@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
+ <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AD594119-58D0-4BF2-921C-6EC1A5BD67A1}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -62,6 +62,7 @@
<Compile Include="ExpressionAlgebraSimplifyTests.cs" />
<Compile Include="LinqExpressionTests.cs" />
<Compile Include="MathMLContentMarkupFormatterTests.cs" />
+ <Compile Include="OrderingTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
View
85 src/test/MathNet.Palladium.Test/OrderingTests.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using System.Linq.Expressions;
+
+namespace MathNet.Palladium.Test
+{
+ using MathNet.ExpressionAlgebra;
+ using MathNet.Numerics;
+
+ [TestFixture]
+ public class OrderingTests
+ {
+ [Test]
+ public void TestFrameworkStringCompare()
+ {
+ Assert.AreEqual(0, String.Compare("a", "a", StringComparison.Ordinal));
+ Assert.AreEqual(-1, String.Compare("a", "b", StringComparison.Ordinal));
+ Assert.AreEqual(1, String.Compare("b", "a", StringComparison.Ordinal));
+ Assert.AreEqual(32, String.Compare("a", "A", StringComparison.Ordinal));
+ Assert.AreEqual(-32, String.Compare("A", "a", StringComparison.Ordinal));
+ }
+
+ [Test]
+ public void TestParameterOrdering()
+ {
+ ParameterExpression a = Expression.Parameter(typeof(int), "a");
+ ParameterExpression b = Expression.Parameter(typeof(int), "b");
+ ParameterExpression c = Expression.Parameter(typeof(int), "c");
+ ParameterExpression B = Expression.Parameter(typeof(int), "B");
+ ParameterExpression C = Expression.Parameter(typeof(int), "C");
+
+ Assert.IsTrue(Ordering.Compare(a, b) < 0, "a < b");
+ Assert.IsTrue(Ordering.Compare(b, a) > 0, "b > a");
+ Assert.IsTrue(Ordering.Compare(a, c) < 0, "a < c");
+ Assert.IsTrue(Ordering.Compare(a, a) == 0, "a = a");
+ Assert.IsTrue(Ordering.Compare(c, c) == 0, "c = c");
+
+ Assert.IsTrue(Ordering.Compare(B, C) < 0, "B < C");
+ Assert.IsTrue(Ordering.Compare(C, B) > 0, "C > B");
+ Assert.IsTrue(Ordering.Compare(C, C) == 0, "C = C");
+
+ Assert.IsTrue(Ordering.Compare(b, B) > 0, "b > B");
+ Assert.IsTrue(Ordering.Compare(c, C) > 0, "c > C");
+ Assert.IsTrue(Ordering.Compare(c, B) > 0, "c > B");
+ }
+
+ [Test]
+ public void TestTypeOrdering()
+ {
+ ParameterExpression x = Expression.Parameter(typeof(int), "x");
+ ConstantExpression c = Expression.Constant(2);
+ BinaryExpression sum = Expression.Add(x, c);
+ BinaryExpression product = Expression.Multiply(x, c);
+ Expression cos = Trigonometry.Cosine(x);
+ Expression sin = Trigonometry.Sine(x);
+
+ Assert.IsTrue(Ordering.Compare(c, x) < 0, "2 < x");
+ Assert.IsTrue(Ordering.Compare(x, c) > 0, "x > 2");
+
+ Assert.IsTrue(Ordering.Compare(c, sum) < 0, "2 < (2+x)");
+ Assert.IsTrue(Ordering.Compare(sum, c) > 0, "(2+x) > 2");
+
+ Assert.IsTrue(Ordering.Compare(x, sum) < 0, "x < (2+x)");
+ Assert.IsTrue(Ordering.Compare(sum, x) > 0, "(2+x) > x");
+
+ Assert.IsTrue(Ordering.Compare(x, sin) < 0, "x < sin(x)");
+ Assert.IsTrue(Ordering.Compare(sin, x) > 0, "sin(x) > x");
+
+ Assert.IsTrue(Ordering.Compare(product, sum) < 0, "2*x < (2+x)");
+ Assert.IsTrue(Ordering.Compare(sum, product) > 0, "(2+x) > 2*x");
+
+ Assert.IsTrue(Ordering.Compare(sum, sum) == 0, "(2+x) = (2+x)");
+ Assert.IsTrue(Ordering.Compare(product, product) == 0, "2*x = 2*x");
+
+ Assert.IsTrue(Ordering.Compare(product, sin) < 0, "2*x < sin(x)");
+ Assert.IsTrue(Ordering.Compare(sin, product) > 0, "sin(x) > 2*x");
+
+ Assert.IsTrue(Ordering.Compare(cos, sin) < 0, "cos(x) < sin(x)");
+ Assert.IsTrue(Ordering.Compare(sin, cos) > 0, "sin(x) > cos(x)");
+ }
+ }
+}

0 comments on commit 4f8875a

Please sign in to comment.
Something went wrong with that request. Please try again.