Processing does not end
dhq-boiler opened this issue · 0 comments
dhq-boiler commented
Hello.
I want to solve a system of equations for a straight line and a tangent to an ellipse.
A straight line: y - y1 = (y2 - y1) / (x2 - x1) * (x - x1)
A tangent to an ellipse: x * x3 / a ^ 2 + y * y3 / b ^ 2 = 1
So I ran the following test code and it didn't finish.
Apparently the Rational.Simplify method is taking a long time.
My operating environment is as follows.
- Windows 11
- Visual Studio 2019
- C# NUnit Test project
- AMD Ryzen 9 5950X
- 32GB RAM
The dependent libraries are:
- FParsec 1.0.3
- FSharp.Core 4.6.0
- MathNet.Numerics 4.15.0
- MathNet.Numerics.FSharp 4.15.0
- MathNet.Symbolics 0.24.0
- NUnit 3.13.2
- NUnit.ConsoleRunner 3.12.0
- etc...
Is there any good solution to reduce the processing time?
Thank you.
using MathNet.Symbolics;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace boilersGraphics.Test
{
using Expr = MathNet.Symbolics.Expression;
[TestFixture]
public class MathNetTest
{
[Test]
public void Basic()
{
var x = Expr.Symbol("x");
var y = Expr.Symbol("y");
var x1 = Expr.Symbol("x1");
var y1 = Expr.Symbol("y1");
var x2 = Expr.Symbol("x2");
var y2 = Expr.Symbol("y2");
var x3 = Expr.Symbol("x3");
var y3 = Expr.Symbol("y3");
var a = Expr.Symbol("a");
var b = Expr.Symbol("b");
Expr left_line = y - y1;
Expr right_line = (y2 - y1) / (x2 - x1) * (x - x1);
Expr left_tangent = x * x3 / Expr.Pow(a, 2) + y * y3 / Expr.Pow(b, 2);
Expr right_tangent = 1;
Expr line_x = null;
Expr tangent_x = null;
Parallel.Invoke(
() =>
{
line_x = SolveSimpleRoot(x, left_line - right_line);
},
() =>
{
tangent_x = SolveSimpleRoot(x, left_tangent - right_tangent);
}
);
Expr cy = SolveSimpleRoot(y, line_x - tangent_x);
Expr cx = Algebraic.Expand(Structure.Substitute(y, cy, line_x));
Console.WriteLine(Infix.Format(cx));
Console.WriteLine(Infix.Format(cy));
}
// Quote from https://stackoverflow.com/questions/31223380/solving-system-of-linear-equations-using-mathdotnet
Expr SolveSimpleRoot(Expr variable, Expr expr)
{
// try to bring expression into polynomial form
Expr simple = Algebraic.Expand(Rational.Numerator(Rational.Simplify(variable, expr)));
// extract coefficients, solve known forms of order up to 1
Expr[] coeff = MathNet.Symbolics.Polynomial.Coefficients(variable, simple);
switch (coeff.Length)
{
case 1: return Expr.Zero.Equals(coeff[0]) ? variable : Expr.Undefined;
case 2: return Rational.Simplify(variable, Algebraic.Expand(-coeff[0] / coeff[1])); //heavy code
default: return Expr.Undefined;
}
}
}
}