mathnet / mathnet-symbolics

Math.NET Symbolics
http://symbolics.mathdotnet.com
MIT License
341 stars 66 forks source link

Processing does not end #100

Open dhq-boiler opened 2 years ago

dhq-boiler commented 2 years ago

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.

The dependent libraries are:

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;
            }
        }
    }
}