Skip to content

Commit

Permalink
#364 - Add more simplification rules (#407)
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Apr 1, 2021
1 parent 04d7051 commit cf823f0
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 15 deletions.
2 changes: 1 addition & 1 deletion xFunc.Maths/Analyzers/Analyzer{TResult,TContext}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace xFunc.Maths.Analyzers
/// <typeparam name="TContext">The type of additional parameter for analyzer.</typeparam>
/// <seealso cref="IAnalyzer{TResult,TContext}" />
[ExcludeFromCodeCoverage]
public class Analyzer<TResult, TContext> : IAnalyzer<TResult, TContext>
public abstract class Analyzer<TResult, TContext> : IAnalyzer<TResult, TContext>
{
/// <inheritdoc />
/// <exception cref="NotSupportedException">Always.</exception>
Expand Down
23 changes: 9 additions & 14 deletions xFunc.Maths/Analyzers/Simplifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,23 +242,22 @@ public override IExpression Analyze(Add exp)
(Sub(var left, Number right), Number number)
=> Analyze(new Add(new Number(number.Value - right.Value), left)),

// TODO: nested complex 'x'

// ax + x
// xa + x
// x + bx
// x + xb
(Mul(Number a, Variable x1), Variable x2) when x1.Equals(x2)
(Mul(Number a, var x1), var x2) when x1.Equals(x2)
=> Analyze(new Mul(new Number(a.Value + 1), x1)),

// ax + bx
// ax + xb
// xa + bx
// xa + xb
(Mul(Number a, Variable x1), Mul(Number b, Variable x2)) when x1.Equals(x2)
(Mul(Number a, var x1), Mul(Number b, var x2)) when x1.Equals(x2)
=> Analyze(new Mul(new Number(a.Value + b.Value), x1)),

var (left, right) when IsChanged(exp, left, right) => new Add(left, right),
var (left, right) when IsChanged(exp, left, right)
=> new Add(left, right),

_ => exp,
};
Expand Down Expand Up @@ -535,20 +534,18 @@ public override IExpression Analyze(Mul exp)
(Div(var left, Number right), Number number)
=> Analyze(new Mul(new Number(number.Value / right.Value), left)),

// TODO: nested complex 'x'

// ax * x
// xa * x
// x * bx
// x * xb
(Mul(Number a, Variable x1), Variable x2) when x1.Equals(x2)
(Mul(Number a, var x1), var x2) when x1.Equals(x2)
=> Analyze(new Mul(a, new Pow(x1, Number.Two))),

// ax + bx
// ax + xb
// xa + bx
// xa + xb
(Mul(Number a, Variable x1), Mul(Number b, Variable x2)) when x1.Equals(x2)
(Mul(Number a, var x1), Mul(Number b, var x2)) when x1.Equals(x2)
=> Analyze(new Mul(new Number(a.Value * b.Value), new Pow(x1, Number.Two))),

// x * (1 / x)
Expand Down Expand Up @@ -766,23 +763,21 @@ public override IExpression Analyze(Sub exp)
(Number number, Sub(var left, Number right))
=> Analyze(new Sub(new Number(number.Value + right.Value), left)),

// TODO: nested complex 'x'

// x - bx
// x - xb
(Variable x1, Mul(Number b, Variable x2)) when x1.Equals(x2)
(var x1, Mul(Number b, var x2)) when x1.Equals(x2)
=> Analyze(new Mul(new Number(1 - b.Value), x1)),

// ax - x
// xa - x
(Mul(Number a, Variable x1), Variable x2) when x1.Equals(x2)
(Mul(Number a, var x1), var x2) when x1.Equals(x2)
=> Analyze(new Mul(new Number(a.Value - 1), x1)),

// ax - bx
// ax - xb
// xa - bx
// xa - xb
(Mul(Number a, Variable x1), Mul(Number b, Variable x2)) when x1.Equals(x2)
(Mul(Number a, var x1), Mul(Number b, var x2)) when x1.Equals(x2)
=> Analyze(new Mul(new Number(a.Value - b.Value), x1)),

var (left, right) when IsChanged(exp, left, right)
Expand Down
26 changes: 26 additions & 0 deletions xFunc.Tests/Analyzers/SimplifierTests/AddSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ public void AddSaveVars2()
SimplifyTest(exp, expected);
}

[Fact(DisplayName = "2 * (x + y) + (x + y)")]
public void AddComplexX()
{
var exp = new Add(
new Mul(Number.Two, new Add(Variable.X, new Variable("Y"))),
new Add(Variable.X, new Variable("Y")));
var expected = new Mul(new Number(3), new Add(Variable.X, new Variable("Y")));

SimplifyTest(exp, expected);
}

[Fact(DisplayName = "x + 2x")]
public void AddSaveVars3()
{
Expand Down Expand Up @@ -231,6 +242,21 @@ public void AddSaveVars5()
SimplifyTest(exp, expected);
}

[Fact(DisplayName = "2 * (x + y) + 3 * (x + y)")]
public void AddComplexX2()
{
var exp = new Add(
new Mul(Number.Two, new Add(Variable.X, new Variable("y"))),
new Mul(new Number(3), new Add(Variable.X, new Variable("y")))
);
var expected = new Mul(
new Number(5),
new Add(Variable.X, new Variable("y"))
);

SimplifyTest(exp, expected);
}

[Fact(DisplayName = "-x + x")]
public void AddSaveVars6()
{
Expand Down
30 changes: 30 additions & 0 deletions xFunc.Tests/Analyzers/SimplifierTests/MulSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,21 @@ public void MulSameVar2()
SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2 * (x + y) * (x + y)")]
public void MulComplexX()
{
var mul = new Mul(
new Mul(Number.Two, new Add(Variable.X, new Variable("y"))),
new Add(Variable.X, new Variable("y"))
);
var expected = new Mul(
Number.Two,
new Pow(new Add(Variable.X, new Variable("y")), Number.Two)
);

SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2x * 3x")]
public void MulSameVar3()
{
Expand All @@ -232,6 +247,21 @@ public void MulSameVar3()
SimplifyTest(mul, expected);
}

[Fact(DisplayName = "2 * (x + y) * 3 * (x + y)")]
public void MulComplexX2()
{
var mul = new Mul(
new Mul(Number.Two, new Add(Variable.X, new Variable("y"))),
new Mul(new Number(3), new Add(Variable.X, new Variable("y")))
);
var expected = new Mul(
new Number(6),
new Pow(new Add(Variable.X, new Variable("y")), Number.Two)
);

SimplifyTest(mul, expected);
}

[Fact(DisplayName = "x * 2x")]
public void MulSameVar4()
{
Expand Down
36 changes: 36 additions & 0 deletions xFunc.Tests/Analyzers/SimplifierTests/SubSimplifierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ public void SubSameVars4()
SimplifyTest(sub, expected);
}

[Fact(DisplayName = "(x + y) - 2 * (x + y)")]
public void SubComplexX()
{
var sub = new Sub(
new Add(Variable.X, new Variable("y")),
new Mul(Number.Two, new Add(Variable.X, new Variable("y")))
);
var expected = new UnaryMinus(new Add(Variable.X, new Variable("y")));

SimplifyTest(sub, expected);
}

[Fact(DisplayName = "x - (x * 2)")]
public void SubSameVars5()
{
Expand All @@ -210,6 +222,18 @@ public void SubSameVars5()
SimplifyTest(sub, expected);
}

[Fact(DisplayName = "2 * (x + y) - (x + y)")]
public void SubComplexX2()
{
var sub = new Sub(
new Mul(Number.Two, new Add(Variable.X, new Variable("y"))),
new Add(Variable.X, new Variable("y"))
);
var expected = new Add(Variable.X, new Variable("y"));

SimplifyTest(sub, expected);
}

[Fact(DisplayName = "2x - x")]
public void SubSameVars6()
{
Expand Down Expand Up @@ -240,6 +264,18 @@ public void SubSameVars8()
SimplifyTest(sub, expected);
}

[Fact(DisplayName = "3 * (x + y) - 2 * (x + y)")]
public void SubComplexX3()
{
var sub = new Sub(
new Mul(new Number(3), new Add(Variable.X, new Variable("y"))),
new Mul(Number.Two, new Add(Variable.X, new Variable("y")))
);
var expected = new Add(Variable.X, new Variable("y"));

SimplifyTest(sub, expected);
}

[Fact(DisplayName = "(x * 3) - (x * 2)")]
public void SubSameVars9()
{
Expand Down

0 comments on commit cf823f0

Please sign in to comment.