Skip to content

Commit

Permalink
Fix bugs when parsing and combining certain fractions
Browse files Browse the repository at this point in the history
  • Loading branch information
Calendis committed Sep 29, 2024
1 parent 41832ef commit d5de65e
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 21 deletions.
5 changes: 4 additions & 1 deletion magician/algebra/Notate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public static Oper Parse(string s)
{
List<Token> tokens = Tokenize(s);
Oper o = ParseExpression(tokens.ToArray());
return o.Copy();
// This Oper is in a weird state until we copy it
Oper c = o.Copy();
c.Reduce();
return c.Trim();
}

internal class Token
Expand Down
3 changes: 2 additions & 1 deletion magician/algebra/symbols/advanced/Factors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public FactorMap(params Oper[] fs)
OperLike ol = new();
foreach (Oper factor in fs)
{
Oper fc = factor.Copy().SimplifiedAll();
Oper fc = factor.Trim().Copy().SimplifiedAll();
// TODO: is this really necessary?
fc.Reduce(2);
fc.Combine(null, 2);
fc.Reduce(2);
Expand Down
2 changes: 1 addition & 1 deletion magician/algebra/symbols/arithmetic/Arithmetic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void Combine(Variable? axis)

A.Reduce(3);
B.Reduce(3);
Oper AB = A.Trim().CommonFactors(B.Trim());
Oper AB = A.Trim().CommonSymbolicFactors(B.Trim());
AB.Reduce(2);
AB = AB.Trim();

Expand Down
13 changes: 12 additions & 1 deletion magician/algebra/symbols/arithmetic/Fraction.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace Magician.Alg.Symbols;
using Core;
using Magician.Alg.Symbols.Commonfuncs;

// Fraction objects represent multiplication and division operations with any number of arguments

public class Fraction : Arithmetic
{
protected override int Identity => 1;
Expand Down Expand Up @@ -197,10 +199,19 @@ public override FactorMap Factors()
return new(posArgs.Concat(negArgs.Select(na => na.Pow(new Variable(-1)))).ToArray());
}

// TODO: this function is pretty bad, potentially rewrite it
protected override Oper Handshake(Variable axis, Oper A, Oper B, Oper AB, bool aPositive, bool bPositive)
{
Oper ABbar;
if (!(aPositive ^ bPositive))
if (AB is ExpLog && AB.posArgs.Count == 2 && AB.posArgs[1] is Min)
{
return axis.Pow(AB.posArgs[1].posArgs[1].Plus(AB.posArgs[1].posArgs[0]));
}
else if (A is ExpLog && B is ExpLog && A.posArgs.Count == 2 && B.posArgs.Count == 2 && A.negArgs.Count == 0 && B.negArgs.Count == 0 && A.posArgs[0].Like(B.posArgs[0]))
{
return A.posArgs[0].Pow(A.posArgs[1].Plus(B.posArgs[1]));
}
else if (!(aPositive ^ bPositive))
ABbar = A.Degree(AB).Plus(B.Degree(AB));
else if (aPositive)
ABbar = A.Degree(AB).Minus(B.Degree(AB));
Expand Down
2 changes: 1 addition & 1 deletion magician/algebra/symbols/base/Oper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ public virtual Oper Log(Oper o)
//public virtual Fraction Factors(){return new Fraction(new ExpLog(new List<Oper>{Copy(), new Variable(1)}, new List<Oper>{}));}
public virtual FactorMap Factors() => new(this);

public Oper CommonFactors(Oper o) => Factors().Common(o.Factors()).ToFraction();
public Oper CommonSymbolicFactors(Oper o) => Factors().Common(o.Factors()).ToFraction();

public static bool operator <(Oper o0, Oper o1)
{
Expand Down
40 changes: 24 additions & 16 deletions tests/MagicianTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,24 +154,24 @@ public void Factors()
}

[Test]
public void CommonFactors()
public void CommonSymbolicFactors()
{
Oper i0, i1, cf;

// Trivial 1 intersection
i0 = Var("x");
i1 = Val(242141);
Scribe.Info($" {i0} CF {i1}: {i0.CommonFactors(i1)}");
Assert.That(i0.CommonFactors(i1).Trim().Like(Val(1)));
Scribe.Info($" {i0} CF {i1}: {i0.CommonSymbolicFactors(i1)}");
Assert.That(i0.CommonSymbolicFactors(i1).Trim().Like(Val(1)));
// single x intersection
i0 = Var("x");
i1 = Var("x");
Scribe.Info($" {i0} CF {i1}: {i0.CommonFactors(i1)}");
Assert.That(i0.CommonFactors(i1).Trim().Like(Var("x")));
Scribe.Info($" {i0} CF {i1}: {i0.CommonSymbolicFactors(i1)}");
Assert.That(i0.CommonSymbolicFactors(i1).Trim().Like(Var("x")));
// double x intersection
i0 = new Fraction(new List<Oper> { Val(2), Var("x") }, new List<Oper> { });
i1 = Var("x");
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf}");
Assert.That(cf.Trim().Like(Var("x")));
Expand All @@ -181,66 +181,70 @@ public void CommonFactors()
new Fraction(new List<Oper>{Var("x"), Var("y")}, new List<Oper>{})
}, new List<Oper> { });
i1 = Var("y");
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf}");
Assert.That(cf.Trim().Like(Val(1)));
// quadratic-x intersection
i0 = Var("x");
i1 = new ExpLog(new List<Oper> { Var("x"), Val(2) }, new List<Oper> { });
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf}");
Assert.That(cf.Trim().Like(Var("x")));
// quad-quad intersection
i0 = new ExpLog(new List<Oper> { Var("x"), Val(2) }, new List<Oper> { });
i1 = new ExpLog(new List<Oper> { Var("x"), Val(2) }, new List<Oper> { });
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf}");
Assert.That(cf.Trim().Like(Var("x").Pow(Val(2))));
// quadratic-1/x intersection
i0 = new Fraction(Val(1), Var("x"));
i1 = new ExpLog(new List<Oper> { Var("x"), Val(2) }, new List<Oper> { });
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf} [{i0.Factors().ToFraction()}], [{i0.Factors().Common(i1.Factors()).ToFraction()}, {i1.Factors().Common(i0.Factors()).ToFraction()}]");
Assert.That(cf.Trim().Like(Val(1).Divide(Var("x"))));
// alternate quadratic-1/x intersection
i0 = new ExpLog(new List<Oper> { Var("x"), Val(-1) }, new List<Oper> { });
i1 = new ExpLog(new List<Oper> { Var("x"), Val(2) }, new List<Oper> { });
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf} [{i0.Factors().ToFraction()}], [{i0.Factors().Common(i1.Factors()).ToFraction()}, {i1.Factors().Common(i0.Factors()).ToFraction()}]");
Assert.That(cf.Trim().Like(Val(1).Divide(Var("x"))));
// quad-invquad intersection
i0 = Val(1).Divide(Var("x").Pow(Val(2)));
i1 = Var("x").Pow(Val(2));
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf} [{i0.Factors().ToFraction()}], [{i0.Factors().Common(i1.Factors()).ToFraction()}, {i1.Factors().Common(i0.Factors()).ToFraction()}]");
//Assert.That(cf.Trim().Like(Val(1).Divide(Var("x"))));
Assert.That(cf.Trim().Like(Val(1).Divide(Var("x").Pow(Val(2)))));
// alternate quad-invquad intersection
i0 = Var("x").Pow(Val(-2));
i1 = Var("x").Pow(Val(2));
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf} [{i0.Factors().ToFraction()}], [{i0.Factors().Common(i1.Factors()).ToFraction()}, {i1.Factors().Common(i0.Factors()).ToFraction()}]");
Assert.That(cf.Like(Val(1).Divide(Var("x").Pow(Val(2)))));
// alternate quad-invquad intersection
i0 = Val(1).Divide(Var("x").Mult(Var("x")));
i1 = Var("x").Pow(Val(2));
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf} [{i0.Factors().ToFraction()}], [{i1.Factors().ToFraction()}], [{i0.Factors().Common(i1.Factors()).ToFraction()}, {i1.Factors().Common(i0.Factors()).ToFraction()}]");
Assert.That(cf.Like(Val(1).Divide(Var("x").Pow(Val(2)))));
//general intersection
i0 = new ExpLog(new List<Oper> { Var("x"), Var("n") }, new List<Oper> { });
i1 = new ExpLog(new List<Oper> { Var("x"), Var("k") }, new List<Oper> { });
cf = i0.CommonFactors(i1);
cf = i0.CommonSymbolicFactors(i1);
cf.Reduce();
Scribe.Info($" {i0} CF {i1}: {cf}");
Assert.That(cf.Trim().Like(Var("x").Pow(new Min(Var("k"), Var("n")))));
// x with coefficient
i0 = Var("x");
i1 = Var("x").Mult(Val(2));
Assert.That(i0.CommonSymbolicFactors(i1).Trim().Like(Var("x")));
}

[Test]
Expand Down Expand Up @@ -930,6 +934,10 @@ public void PolynomialZeroes()
public void PowerLaws()
{
Oper a = Parse("x^n*x^k");
a.Combine();

Oper b = Parse("2^x*2^x");
b.Combine();
}
}

Expand Down

0 comments on commit d5de65e

Please sign in to comment.