예제 #1
0
        public void TestPatt2()
        {
            var y    = MathS.Var("y");
            var expr = (MathS.Sqr(MathS.Sin(x + 2 * y)) + MathS.Sqr(MathS.Cos(x + 2 * y))) / (2 * MathS.Sin(x - y) * MathS.Cos(x - y) + 1);

            Assert.IsTrue(expr.Simplify() == 1 / (MathS.Sin(2 * (x - y)) + 1));
        }
예제 #2
0
 public void Setup()
 {
     exprEasy     = x + MathS.Sqr(x) - 3;
     exprMedium   = MathS.Sin(x + MathS.Cos(x)) + MathS.Sqrt(x + MathS.Sqr(x));
     exprHard     = MathS.Sin(x + MathS.Arcsin(x)) / (MathS.Sqr(x) + MathS.Cos(x)) * MathS.Arccos(x / 1200 + 0.00032 / MathS.Cotan(x + 43));
     exprSolvable = MathS.FromString("3arccos(2x + a)3 + 6arccos(2x + a)2 - a3 + 3");
 }
예제 #3
0
    /// <summary>
    /// 根据旋转轴和旋转角生成单位四元数
    /// </summary>
    /// <param name="angle"></param>
    /// <param name="axisNormal"></param>
    /// <returns>单位四元数</returns>
    public static Quaternion AngleAxis(float angle, Vector3 axisNormal)
    {
        float   radian = MathS.DegToRad * angle * 0.5f;
        float   real   = MathS.Cos(radian);
        Vector3 imag   = MathS.Sin(radian) * axisNormal;

        return(new Quaternion(imag.x, imag.y, imag.z, real));
    }
예제 #4
0
        public void TestCosCustom()
        {
            var func     = MathS.Cos(MathS.Pow(x, 3));
            var expected = -3 * MathS.Sin(MathS.Pow(x, 3)) * MathS.Sqr(x);
            var actual   = func.Derive(x).Simplify();

            AssertEqEntity(expected.ToString(), actual.ToString());
        }
예제 #5
0
        public void TestCosCustom()
        {
            var func     = MathS.Cos(MathS.Pow(x, 3));
            var expected = -3 * MathS.Sin(MathS.Pow(x, 3)) * MathS.Sqr(x);
            var actual   = func.Differentiate(x).Simplify();

            Assert.Equal(expected, actual);
        }
예제 #6
0
        public CacheCompiledFunc()
        {
            notCompiled = MathS.Sin(MathS.Sqr(x)) + MathS.Cos(MathS.Sqr(x)) + MathS.Sqr(x) + MathS.Sin(MathS.Sqr(x));
            complexFunc = notCompiled.Compile(x);

            Expression <Func <Complex, Complex> > linqExpr = x => Complex.Sin(Complex.Pow(x, 2)) + Complex.Cos(Complex.Pow(x, 2)) + Complex.Pow(x, 2) + Complex.Sin(Complex.Pow(x, 2));

            linqComp = linqExpr.Compile();
        }
예제 #7
0
        private void EveryFrame(object sender, EventArgs e)
        {
            var B         = MathS.Var("B");
            var expr2     = B * MathS.Sin(t + B) * MathS.Pow(MathS.e, MathS.i * B * MathS.Cos(t));
            var niceFunc2 = expr2.Compile(B);

            plotter.Clear();
            plotter.PlotIterativeComplex(niceFunc2, 0, t);
            plotter.Render();
            t += 0.0005m;
        }
예제 #8
0
 public SubsTest()
 {
     IterCount = 10000;
     tests     = new List <Func <object> > {
         () => (x * MathS.Sin(x)).Substitute(x, 3).Eval(),
         () => (MathS.Cos(x) * MathS.Sin(x)).Substitute(x, 3).Eval(),
         () => (MathS.Sqr(MathS.Sin(x + 2 * x)) + MathS.Sqr(MathS.Cos(x + 2 * x))).Substitute(x, 3).Eval(),
         () => (x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))).Substitute(x, 3).Eval()
     };
 }
 public SimplificationTest()
 {
     IterCount = 1500;
     tests     = new List <Func <object> > {
         () => (x * MathS.Sin(x)).Simplify(),
         () => (MathS.Cos(x) * MathS.Sin(x)).Simplify(),
         () => (MathS.Sqr(MathS.Sin(x + 2 * y)) + MathS.Sqr(MathS.Cos(x + 2 * y))).Simplify(),
         () => (x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))).Simplify()
     };
 }
예제 #10
0
 public DerivationTest()
 {
     IterCount = 10000;
     tests     = new List <Func <object> > {
         () => x.Derive(x),
         () => (MathS.Cos(x) * MathS.Sin(x)).Derive(x),
         () => (MathS.Sqr(MathS.Sin(x + 2 * y)) + MathS.Sqr(MathS.Cos(x + 2 * y))).Derive(x),
         () => (x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))
                * x * MathS.Cos(x) / MathS.Sin(MathS.Sqrt(x / MathS.Ln(x)))).Derive(x)
     };
 }
예제 #11
0
        public void TestSin()
        {
            var func = MathS.Sin(x);

            AssertEqEntity(func.Derive(x).Simplify(), MathS.Cos(x));
        }
예제 #12
0
        public void Test2()
        {
            var func = (MathS.Sin(x) + MathS.Cos(x)).Compile(x);

            Assert.IsTrue(func.Substitute(0) == 1);
        }
예제 #13
0
 [TestMethod] public void Trig() =>
 TestSimplify(@"\sin\left(\cos\left(\tan\left(\cot\left(x\right)\right)\right)\right)", MathS.Sin(MathS.Cos(MathS.Tan(MathS.Cotan(x)))));
예제 #14
0
 public void Test4()
 {
     MathS.FromString((MathS.Sin(x) / MathS.Cos(x)).Derive(x).ToString());
 }
예제 #15
0
        /// <summary>
        /// Returns a set of possible roots of a function, e. g.
        /// sin(x) = a =>
        /// x = arcsin(a) + 2 pi n
        /// x = pi - arcsin(a) + 2 pi n
        /// </summary>
        /// <param name="func"></param>
        /// <param name="value"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        public static Set InvertFunctionEntity(FunctionEntity func, Entity value, Entity x)
        {
            Entity a   = func.Children[0];
            Entity b   = func.Children.Count == 2 ? func.Children[1] : null;
            int    arg = func.Children.Count == 2 && func.Children[1].FindSubtree(x) != null ? 1 : 0;
            var    n   = Utils.FindNextIndex(func + value, "n");
            var    res = new Set();
            var    pi  = MathS.pi;

            Set GetNotNullEntites(Set set)
            {
                return(set.FiniteWhere(el => el.entType != Entity.EntType.NUMBER || el.GetValue().IsDefinite()));
            }

            switch (func.Name)
            {
            // Consider case when sin(sin(x)) where double-mention of n occures
            case "sinf":
            {
                // sin(x) = value => x = arcsin(value) + 2pi * n
                res.AddRange(GetNotNullEntites(FindInvertExpression(a, MathS.Arcsin(value) + 2 * pi * n, x)));
                // sin(x) = value => x = pi - arcsin(value) + 2pi * n
                res.AddRange(GetNotNullEntites(FindInvertExpression(a, pi - MathS.Arcsin(value) + 2 * pi * n, x)));
                return(res);
            }

            case "cosf":
            {
                // cos(x) = value => x = arccos(value) + 2pi * n
                res.AddRange(GetNotNullEntites(FindInvertExpression(a, MathS.Arccos(value) + 2 * pi * n, x)));
                // cos(x) = value => x = -arccos(value) + 2pi * n
                res.AddRange(GetNotNullEntites(FindInvertExpression(a, -MathS.Arccos(value) - 2 * pi * n, x)));
                return(res);
            }

            case "tanf":
            {
                var inverted = FindInvertExpression(a, MathS.Arctan(value) + pi * n, x);
                // tan(x) = value => x = arctan(value) + pi * n
                res.AddRange(GetNotNullEntites(inverted));
                return(res);
            }

            case "cotanf":
            {
                var inverted = FindInvertExpression(a, MathS.Arccotan(value) + pi * n, x);
                // cotan(x) = value => x = arccotan(value)
                res.AddRange(GetNotNullEntites(inverted));
                return(res);
            }

            case "arcsinf":
                // arcsin(x) = value => x = sin(value)
                if (EntityInBounds(value, ArcsinFrom, ArcsinTo))
                {
                    return(GetNotNullEntites(FindInvertExpression(a, MathS.Sin(value), x)));
                }
                else
                {
                    return(Empty);
                }

            case "arccosf":
                // arccos(x) = value => x = cos(value)
                if (EntityInBounds(value, ArccosFrom, ArccosTo))
                {
                    return(GetNotNullEntites(FindInvertExpression(a, MathS.Cos(value), x)));
                }
                else
                {
                    return(Empty);
                }

            case "arctanf":
                // arctan(x) = value => x = tan(value)
                return(GetNotNullEntites(FindInvertExpression(a, MathS.Tan(value), x)));

            case "arccotanf":
                // arccotan(x) = value => x = cotan(value)
                return(GetNotNullEntites(FindInvertExpression(a, MathS.Cotan(value), x)));

            case "logf":
                if (arg != 0)
                {
                    // log(x, a) = value => x = a ^ value
                    return(GetNotNullEntites(FindInvertExpression(b, MathS.Pow(a, value), x)));
                }
                else
                {
                    // log(a, x) = value => a = x ^ value => x = a ^ (1 / value)
                    return(GetNotNullEntites(FindInvertExpression(a, MathS.Pow(b, 1 / value), x)));
                }

            default:
                throw new SysException("Unknown function");
            }
        }
 TreeAnalyzer.TryGetPolyLinear(arg, x, out var a, out _) =>
 - MathS.Ln(MathS.Cos(arg)) / a,
예제 #17
0
        // sin(x) -> sin(1 * x)
        // sin(x) + sin(a * x)


        // if x * a
        //     x * a => a * x
        // if ! a * x
        //     x => 1 * x
        // if ! a * x + b
        //     a * x => a * x + 0
        private static Entity ReplaceTrigonometry(Entity expr, VariableEntity variable, VariableEntity replacement)
        {
            // SolveLinear should also solve tan and cotan equations, but currently Polynomial solver cannot handle big powers
            // uncomment lines above when it will be fixed (TODO)

            var sin = expr.FindSubtree(MathS.Sin(variable));
            var cos = expr.FindSubtree(MathS.Cos(variable));
            //var tan = expr.FindSubtree(MathS.Tan  (variable));
            //var cot = expr.FindSubtree(MathS.Cotan(variable));
            var sinReplacement = replacement / (2 * MathS.i) - MathS.Pow(replacement, -1) / (2 * MathS.i);
            var cosReplacement = replacement / 2 + MathS.Pow(replacement, -1) / 2;

            // var tanReplacement = (1 - MathS.Sqr(replacement)) * MathS.i * MathS.Pow(MathS.Sqr(replacement) + 1, -1);
            // var cotReplacement = (MathS.Sqr(replacement) + 1) * MathS.i * MathS.Pow(MathS.Sqr(replacement) - 1, -1);
            TreeAnalyzer.FindAndReplace(ref expr, sin, sinReplacement);
            TreeAnalyzer.FindAndReplace(ref expr, cos, cosReplacement);
            // TreeAnalyzer.FindAndReplace(ref expr, tan, tanReplacement);
            // TreeAnalyzer.FindAndReplace(ref expr, cot, cotReplacement);

            // workaround for missing Patterns.Variable(x), replace all expressions, false-matching pattern to variables
            // which will be returned back after all actual replacements
            var    falseReplacements    = new List <KeyValuePair <VariableEntity, Entity> >();
            string falseReplacementName = "trig";

            void ReplaceSinSubExpression(ref Entity expr, Entity toReplace, Entity a, Entity b, VariableEntity replacement)
            {
                // sin(ax + b) = (t^a * e^(i*b) - t^(-a) * e^(-i*b)) / (2i)
                var resultReplacement = (MathS.Pow(replacement, a) * (MathS.Pow(MathS.e, b * MathS.i) / (2 * MathS.i)) - MathS.Pow(replacement, -a) * (MathS.Pow(MathS.e, -b * MathS.i)) / (2 * MathS.i));

                TreeAnalyzer.FindAndReplace(ref expr, toReplace, resultReplacement);
            }

            void ReplaceCosSubExpression(ref Entity expr, Entity toReplace, Entity a, Entity b, VariableEntity replacement)
            {
                // cos(ax + b) = (t^a * e^(i*b) + t^(-a) * e^(-i*b)) / 2
                var resultReplacement = (MathS.Pow(replacement, a) * (MathS.Pow(MathS.e, b * MathS.i) / 2) + MathS.Pow(replacement, -a) * (MathS.Pow(MathS.e, -b * MathS.i)) / 2);

                TreeAnalyzer.FindAndReplace(ref expr, toReplace, resultReplacement);
            }

            // checks if pattern-matching succeeded. If not, replace subexpression with some variable
            bool CheckIfReplacementIsSuitable(ref Entity expr, Entity found, Entity variable, Entity variableToCheckFor)
            {
                if (variable != variableToCheckFor)
                {
                    var repl = Utils.FindNextIndex(expr, falseReplacementName);
                    falseReplacements.Add(new KeyValuePair <VariableEntity, Entity>(repl, found));
                    TreeAnalyzer.FindAndReplace(ref expr, found, repl);
                    return(false);
                }
                return(true);
            }

            void MatchSinUntil(Pattern p, Func <Entity, (Entity, Entity, Entity)> variableGetter)
            {
                Entity found;

                while ((found = expr.FindPatternSubtree(p)) != null)
                {
                    (Entity x, Entity a, Entity b) = variableGetter(found.Children[0]);
                    if (CheckIfReplacementIsSuitable(ref expr, found, x, variable))
                    {
                        ReplaceSinSubExpression(ref expr, found, a, b, replacement);
                    }
                }
            }

            void MatchCosUntil(Pattern p, Func <Entity, (Entity, Entity, Entity)> variableGetter)
            {
                Entity found;

                while ((found = expr.FindPatternSubtree(p)) != null)
                {
                    (Entity x, Entity a, Entity b) = variableGetter(found.Children[0]);
                    if (CheckIfReplacementIsSuitable(ref expr, found, x, variable))
                    {
                        ReplaceCosSubExpression(ref expr, found, a, b, replacement);
                    }
                }
            }

            // arg => (x, a, b)
            // TODO: refactor this. Move to a list
            var variablePattern = new Pattern(1000, Entity.PatType.VARIABLE,
                                              tree => tree.entType == Entity.EntType.VARIABLE && tree.Name == variable.Name);
            var pattern1 = Sinf.PHang(Patterns.const1 * variablePattern + Patterns.any1);

            MatchSinUntil(pattern1, arg => (arg.Children[0].Children[1], arg.Children[0].Children[0], arg.Children[1]));
            var pattern2 = Sinf.PHang(variablePattern * Patterns.const1 + Patterns.any1);

            MatchSinUntil(pattern2, arg => (arg.Children[0].Children[0], arg.Children[0].Children[1], arg.Children[1]));

            var pattern3 = Sinf.PHang(Patterns.any1 + Patterns.const1 * variablePattern);

            MatchSinUntil(pattern3, arg => (arg.Children[1].Children[1], arg.Children[1].Children[0], arg.Children[0]));
            var pattern4 = Sinf.PHang(Patterns.any1 + variablePattern * Patterns.const1);

            MatchSinUntil(pattern4, arg => (arg.Children[1].Children[0], arg.Children[1].Children[1], arg.Children[0]));

            var pattern5 = Sinf.PHang(Patterns.const1 * variablePattern);

            MatchSinUntil(pattern5, arg => (arg.Children[1], arg.Children[0], 0));
            var pattern6 = Sinf.PHang(variablePattern * Patterns.const1);

            MatchSinUntil(pattern6, arg => (arg.Children[0], arg.Children[1], 0));
            var pattern7 = Sinf.PHang(Patterns.any1 + variablePattern);

            MatchSinUntil(pattern7, arg => (arg.Children[1], 1, arg.Children[0]));
            var pattern8 = Sinf.PHang(variablePattern + Patterns.any1);

            MatchSinUntil(pattern8, arg => (arg.Children[0], 1, arg.Children[1]));

            var pattern9 = Cosf.PHang(Patterns.const1 * variablePattern + Patterns.any1);

            MatchCosUntil(pattern9, arg => (arg.Children[0].Children[1], arg.Children[0].Children[0], arg.Children[1]));
            var pattern10 = Cosf.PHang(variablePattern * Patterns.const1 + Patterns.any1);

            MatchCosUntil(pattern10, arg => (arg.Children[0].Children[0], arg.Children[0].Children[1], arg.Children[1]));

            var pattern11 = Cosf.PHang(Patterns.any1 + Patterns.const1 * variablePattern);

            MatchCosUntil(pattern11, arg => (arg.Children[1].Children[1], arg.Children[1].Children[0], arg.Children[0]));
            var pattern12 = Cosf.PHang(Patterns.any1 + variablePattern * Patterns.const1);

            MatchCosUntil(pattern12, arg => (arg.Children[1].Children[0], arg.Children[1].Children[1], arg.Children[0]));

            var pattern13 = Cosf.PHang(Patterns.const1 * variablePattern);

            MatchCosUntil(pattern13, arg => (arg.Children[1], arg.Children[0], 0));
            var pattern14 = Cosf.PHang(variablePattern * Patterns.const1);

            MatchCosUntil(pattern14, arg => (arg.Children[0], arg.Children[1], 0));
            var pattern15 = Cosf.PHang(Patterns.any1 + variablePattern);

            MatchCosUntil(pattern15, arg => (arg.Children[1], 1, arg.Children[0]));
            var pattern16 = Cosf.PHang(variablePattern + Patterns.any1);

            MatchCosUntil(pattern16, arg => (arg.Children[0], 1, arg.Children[1]));

            // re-substitute all false replacement to return expression to normal
            foreach (var repl in falseReplacements)
            {
                TreeAnalyzer.FindAndReplace(ref expr, repl.Key, repl.Value);
            }

            return(expr);
        }
예제 #18
0
        public void TestTan()
        {
            var func = MathS.Tan(2 * x);

            Assert.Equal(2 / MathS.Pow(MathS.Cos(2 * x), 2), func.Differentiate(x).Simplify());
        }
예제 #19
0
 public void Test4()
 {
     Assert.IsTrue(MathS.FromString("sin(x)").Derive(MathS.Var("x")).Simplify() == MathS.Cos(MathS.Var("x")));
 }
예제 #20
0
        public void TestSin()
        {
            var func = MathS.Sin(x);

            Assert.Equal(MathS.Cos(x), func.Differentiate(x).Simplify());
        }
예제 #21
0
        public void TestTan()
        {
            var func = MathS.Tan(2 * x);

            Assert.IsTrue(func.Derive(x).Simplify() == 2 / MathS.Pow(MathS.Cos(2 * x), 2));
        }
예제 #22
0
        public void TestSin()
        {
            var func = MathS.Sin(x);

            Assert.IsTrue(func.Derive(x).Simplify() == MathS.Cos(x));
        }
예제 #23
0
        public void TestTan()
        {
            var func = MathS.Tan(2 * x);

            AssertEqEntity(func.Derive(x).Simplify(), 2 / MathS.Pow(MathS.Cos(2 * x), 2));
        }
 public void Test4() => MathS.FromString((MathS.Sin(x) / MathS.Cos(x)).Differentiate(x).Stringize() ?? "");
예제 #25
0
        public void Test2()
        {
            var func = (MathS.Sin(x) + MathS.Cos(x)).Compile(x);

            Assert.Equal(1, func.Substitute(0));
        }