public void Multiply_Number_FlatAdd() { //Arrange var expected = new FlatAddExpression(); expected.Add(new VariableExpression("u", 2)); expected.Add(new NumberExpression(3)); expected.Count = new Complex(12, 0); expected.Execute(); var c = new NumberExpression(3); var n = new FlatAddExpression(); n.Add(new VariableExpression("u", 2)); n.Add(new NumberExpression(3)); n.Count = new Complex(4, 0); var expr = new BinaryExpression(c, OperatorTypes.Multiply, n); //Act var actual = expr.Execute(); //Assert Assert.AreEqual(expected.Count.Re.ToNumber(), actual.Count.Re.ToNumber()); Assert.AreEqual(expected.Count.Im.ToNumber(), actual.Count.Im.ToNumber()); }
public void Clone_FlatAddExpression() { //Arrange var expression = new FlatAddExpression(); expression.Add(new VariableExpression("x", 1)); expression.Add(new NumberExpression(3)); //Act var clone = (FlatAddExpression)expression.Clone(); //Assert Assert.IsTrue(DimensionKey.Compare(expression.DimensionKey, clone.DimensionKey)); Assert.IsTrue(FlatExpression.Compare(expression, clone)); }
public void Clone_FlatAddExpression_Inversed() { //Arrange var flatAdd = new FlatAddExpression(); flatAdd.Add(new VariableExpression("x", 1)); flatAdd.Add(new NumberExpression(3)); var expression = (FlatAddExpression)(new BinaryExpression(flatAdd, OperatorTypes.Power, new NumberExpression(-1)).Execute()); //Act var clone = (FlatAddExpression)expression.Clone(); //Assert Assert.IsTrue(DimensionKey.Compare(expression.DimensionKey, clone.DimensionKey)); Assert.IsTrue(FlatExpression.Compare(expression, clone)); }
private IExpression Delta(IExpression a, IExpression b, IExpression c) { var b2 = new BinaryExpression(b, Enums.Operators.OperatorTypes.Power, new NumberExpression(2)); var ac4 = new FlatMultExpression(); ac4.Add(new NumberExpression(-4)); ac4.Add(a); ac4.Add(c); var d2 = new FlatAddExpression(); d2.Add(b2); d2.Add(ac4); return(d2); }
private IExpression X1X2(IExpression b, IExpression dsqrt, IExpression a, bool isAdd) { var oneOvera2 = new BinaryExpression(new BinaryExpression(new NumberExpression(2), Enums.Operators.OperatorTypes.Multiply, a), Enums.Operators.OperatorTypes.Power, new NumberExpression(-1)); var bds = new FlatAddExpression(); bds.Add(new UnaryExpression(Enums.Operators.OperatorTypes.Sign, b)); if (isAdd) { bds.Add(dsqrt); } else { bds.Add(new UnaryExpression(Enums.Operators.OperatorTypes.Sign, dsqrt)); } return(new BinaryExpression(bds, Enums.Operators.OperatorTypes.Multiply, oneOvera2)); }
public void RecognizesVariable() { //Arrange var text = "2 + x"; var expected = new FlatAddExpression(); expected.Add(new NumberExpression(1)); var x = new VariableExpression("x", 1m); expected.Add(new UnaryExpression(Mathema.Enums.Operators.OperatorTypes.Sign, x)); //Act var rpn = RPNParser.Parse(text); var actual = (FlatAddExpression)(ExpressionBuilder.BuildFlat(rpn.Output).Execute()); //Assert Assert.IsTrue(actual.Expressions.ContainsKey(Dimensions.Number) || actual.Expressions.ContainsKey(Dimensions.Complex)); Assert.IsTrue(actual.Expressions.ContainsKey("x")); }
public void Clone_FlatAddExpression() { //Arrange var expected = new FlatAddExpression(); expected.Add(new VariableExpression("x", 1)); expected.Add(new VariableExpression("y", 1)); expected.Count = new Complex(3, 2); //Act var actual = (FlatAddExpression)expected.Clone(); //Assert Assert.IsTrue(!Object.ReferenceEquals(actual, expected)); CollectionAssert.AreEquivalent(expected.Expressions, actual.Expressions); Assert.AreEqual(expected.Count.Re.Numerator, actual.Count.Re.Numerator); Assert.AreEqual(expected.Count.Re.Denominator, actual.Count.Re.Denominator); Assert.AreEqual(expected.Count.Im.Numerator, actual.Count.Im.Numerator); Assert.AreEqual(expected.Count.Im.Denominator, actual.Count.Im.Denominator); }
private static void RecursiveSolve(string variable, IEquationSolutions sols, IEquationSolutions newSols) { var keys = sols.Solutions.Keys.ToList(); foreach (var k in keys) { if (k != variable) { var s = sols.Solutions[k]; foreach (var e in s.Item2) { var tmpEq = new FlatAddExpression(); tmpEq.Add(s.Item1); tmpEq.Add(new UnaryExpression(Enums.Operators.OperatorTypes.Sign, e)); var emp = tmpEq.Execute(); var c = EquationClassifier.Classify(emp, variable); var tmp = Solve(variable, tmpEq, c); foreach (var ns in tmp.Solutions) { RecursiveSolve(variable, tmp, newSols); } } } else { var s = sols.Solutions[k]; if (!newSols.Solutions.ContainsKey(variable)) { newSols.Solutions.Add(variable, new Tuple <IExpression, List <IExpression> >(s.Item1, new List <IExpression>())); } newSols.Solutions[variable].Item2.AddRange(s.Item2); } } }
public IEquationSolutions Solve(IExpression expression, string variable, IClassificationResult classification) { var res = new EquationSolutions(); if (expression is FlatAddExpression fa) { IExpression a = null; IExpression b = null; IExpression c = null; List <IExpression> ca = new List <IExpression>(); for (int i = 0; i < fa.Expressions.Count; i++) { var kv = fa.Expressions.ElementAt(i); var deg = kv.Value[0].DimensionKey.Value; var key = kv.Value[0].DimensionKey.Key; var expr = kv.Value[0]; if (deg.ToNumber() == 2 && key == variable) { if (expr is VariableExpression) { a = new ComplexExpression(expr.Count); } else if (expr is IFunctionExpression) { a = new ComplexExpression(expr.Count); } else { var tmp = (FlatExpression)expr.Clone(); tmp.Remove(variable, 2); a = tmp; } } else if (deg.ToNumber() == 1 && key == variable) { if (expr is VariableExpression) { b = new ComplexExpression(expr.Count); } else if (expr is IFunctionExpression) { b = new ComplexExpression(expr.Count); } else { var tmp = (FlatExpression)expr.Clone(); tmp.Remove(variable, 2); b = tmp; } } else { ca.Add(kv.Value[0]); } } if (ca.Count > 1) { c = new FlatAddExpression(); var ct = (FlatAddExpression)c; foreach (var ci in ca) { ct.Add(ci); } } else if (ca.Count == 1) { c = ca[0]; } if (a != null && c != null) { var delta = this.Delta(a, b, c); var ds = new BinaryExpression(delta, Enums.Operators.OperatorTypes.Power, new NumberExpression(new Fraction(1, 2))); var dsqrt = ds.Execute(); var r1 = X1X2(b, dsqrt, a, true); var r2 = X1X2(b, dsqrt, a, false); res.Solutions.Add(variable, new Tuple <IExpression, List <IExpression> >(classification.SearchResult[variable].Item1, new List <IExpression>() { r1.Execute() })); res.Solutions[variable].Item2.Add(r2.Execute()); } } return(res); }
public static IExpression BuildFlat(List <ISymbol> RPNStack) { List <IExpression> stack = new List <IExpression>(); var i = 0; try { for (i = 0; i < RPNStack.Count; i++) { var s = RPNStack[i]; if (s.Type != SymbolTypes.Number && s.Type != SymbolTypes.Variable && s.Type != SymbolTypes.Imaginary) { if (s.Type == SymbolTypes.BinaryOperator) { var type = Operators.Get(s.Value).Type; if (type == OperatorTypes.Add) { var tmp = new FlatAddExpression(); if (stack[stack.Count - 1] is FlatAddExpression) { tmp = (FlatAddExpression)stack[stack.Count - 1] + stack[stack.Count - 2]; } else if (stack[stack.Count - 2] is FlatAddExpression) { tmp = (FlatAddExpression)stack[stack.Count - 2] + stack[stack.Count - 1]; } else { tmp.Add(stack[stack.Count - 1]); tmp.Add(stack[stack.Count - 2]); } stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } else if (type == OperatorTypes.Subtract) { var tmp = new FlatAddExpression(); if (stack[stack.Count - 1] is FlatAddExpression) { tmp = (FlatAddExpression)stack[stack.Count - 1] + stack[stack.Count - 2]; } else if (stack[stack.Count - 2] is FlatAddExpression) { tmp = (FlatAddExpression)stack[stack.Count - 2] + new UnaryExpression(OperatorTypes.Sign, stack[stack.Count - 1]); } else { tmp.Add(new UnaryExpression(OperatorTypes.Sign, stack[stack.Count - 1])); tmp.Add(stack[stack.Count - 2]); } stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } else if (type == OperatorTypes.Multiply) { var tmp = new FlatMultExpression(); if (stack[stack.Count - 1] is FlatMultExpression) { ((FlatMultExpression)stack[stack.Count - 1]).Add(stack[stack.Count - 2]); tmp = (FlatMultExpression)stack[stack.Count - 1]; } else if (stack[stack.Count - 2] is FlatMultExpression) { ((FlatMultExpression)stack[stack.Count - 2]).Add(stack[stack.Count - 1]); tmp = (FlatMultExpression)stack[stack.Count - 2]; } else { tmp.Add(stack[stack.Count - 1]); tmp.Add(stack[stack.Count - 2]); } stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } else if (type == OperatorTypes.Divide) { var tmp = new FlatMultExpression(); //TODO when both are flatmult if (stack[stack.Count - 1] is FlatMultExpression) { tmp.Add(stack[stack.Count - 2]); tmp.Add(new BinaryExpression(stack[stack.Count - 1], OperatorTypes.Power, new NumberExpression(-1))); } else if (stack[stack.Count - 2] is FlatMultExpression) { tmp = ((FlatMultExpression)stack[stack.Count - 2]); tmp.Add(new BinaryExpression(stack[stack.Count - 1], OperatorTypes.Power, new NumberExpression(-1))); } else { //we add inversion and expr to flatmult tmp.Add(new BinaryExpression(stack[stack.Count - 1], OperatorTypes.Power, new NumberExpression(-1))); tmp.Add(stack[stack.Count - 2]); } stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } else { var tmp = new BinaryExpression(stack[stack.Count - 2], Operators.Get(s.Value).Type, stack[stack.Count - 1]); stack.RemoveAt(stack.Count - 1); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } } else if (s.Type == SymbolTypes.UnaryOperator) { var tmp = new UnaryExpression(Operators.Get(s.Value).Type, stack[stack.Count - 1]); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } else if (s.Type == SymbolTypes.Function) { var tmp = Functions.Get(s.Value, stack[stack.Count - 1]); stack.RemoveAt(stack.Count - 1); stack.Add(tmp); } } else { if (s.Type == SymbolTypes.Number) { stack.Add(new NumberExpression(s.Value)); } else if (s.Type == SymbolTypes.Variable) { stack.Add(new VariableExpression(s.Value, 1m)); } else if (s.Type == SymbolTypes.Imaginary) { stack.Add(new ComplexExpression(1m)); } } } } catch (Exception ex) { var msg = "I couldn't undertand what you mean by '" + RPNStack[i].Value + "' after " + string.Join(" ", stack); throw new WrongSyntaxException(msg, ex); } if (stack.Count > 1) { var msg = "I couldn't understand what you mean. Please rephrase your equation. What I understood " + Environment.NewLine + stack[0].ToString(); throw new WrongSyntaxException(msg); } return(stack[0]); }
public IEquationSolutions Solve(IExpression expression, string variable, IClassificationResult classification) { var res = new EquationSolutions(); List <IExpression> al = new List <IExpression>(); List <IExpression> bl = new List <IExpression>(); List <IExpression> cl = new List <IExpression>(); if (expression is FlatAddExpression fa) { foreach (var kv in fa.Expressions) { var expr = kv.Value[0]; if (expr is IFunctionExpression) { if (expr is CosExpression) { al.Add(expr); } else if (expr is SinExpression) { al.Add(expr); } else if (expr is TanExpression) { al.Add(expr); } else if (expr is CotExpression) { al.Add(expr); } else { bl.Add(expr); } } else if (expr is FlatExpression fe) { if (fe.Expressions.Any(e => e.Key == variable)) { bl.Add(expr); } else { cl.Add(expr); } } else if (expr.DimensionKey.Key == variable) { bl.Add(expr); } else { cl.Add(expr); } } if (bl.Count > 0) { //General way of solving } if (al.Count > 1) { //General way of solving ? } if (al.Count == 1) { var expr = (IFunctionExpression)al[0]; if (expr.InverseFunction != 0) { var arg = new FlatAddExpression(); foreach (var e in cl) { arg.Add(new UnaryExpression(Enums.Operators.OperatorTypes.Sign, e).Execute()); } arg.Execute(); var sol = Functions.Get(expr.InverseFunction.ToString(), arg).Execute(); var solFor = expr.Argument.DimensionKey.Key; res.Solutions.Add(solFor, new Tuple <IExpression, List <IExpression> >(expr.Argument, new List <IExpression>() { sol })); } else { //No inverse function => Numeric solution ? } } } return(res); }
public static IExpression Multiply(IExpression lhe, IExpression rhe) { var res = lhe.Clone(); var lc = (IFlatExpression)res; if (rhe is INumberExpression) { lc.Count.Multiply(rhe.Count); return(res); } //else if (rhe is IVariableExpression) //{ // var tmp = rhe.DimensionKey.Key; // if (lc.Expressions.ContainsKey(tmp)) // { // lc.Expressions[tmp].Add(rhe); // } // else // { // lc.Expressions.Add(tmp, new List<IExpression>() { rhe }); // } // foreach (var key in rhe.DimensionKey.Key) // { // res.DimensionKey.Add(key.Key, key.Value); // } // return res; //} //else if (rhe is IFlatMultExpression) //{ // foreach (var key in rhe.DimensionKey.Key) // { // res.DimensionKey.Add(key.Key, key.Value); // } // return res; //} else if (rhe is FlatAddExpression rc) { var ret = new FlatAddExpression(); if (lc.DimensionKey.Key == rc.DimensionKey.Key) { lc.DimensionKey.Value += (Fraction)rc.DimensionKey.Value; if (lc.DimensionKey.Value.Numerator == 0) { return(new NumberExpression(1)); } return(lc); } else { foreach (var expl in lc.Expressions) { foreach (var li in expl.Value) { foreach (var expr in rc.Expressions) { foreach (var ri in expr.Value) { var tmp = li.BinaryOperations[OperatorTypes.Multiply](li, ri); ret.Add(tmp); } } } } } return(ret); } return(null); }
public IEquationSolutions Solve(IExpression expression, string variable, IClassificationResult classification) { var res = new EquationSolutions(); IExpression a = null; IExpression b = null; List <IExpression> ba = new List <IExpression>(); if (expression is FlatAddExpression fa) { foreach (var expr in fa.Expressions) { if (expr.Value[0] is FlatExpression fe) { if (fe.Expressions.Any(e => e.Key == variable)) { if (expr.Value[0] is VariableExpression) { a = new ComplexExpression(expr.Value[0].Count); } else { var tmp = (FlatExpression)expr.Value[0].Clone(); tmp.Remove(variable, 1); a = tmp; } } } else if (expr.Key == variable) { if (expr.Value[0] is VariableExpression) { a = new ComplexExpression(expr.Value[0].Count); } else { var tmp = (FlatExpression)expr.Value[0].Clone(); tmp.Remove(variable, 1); a = tmp; } } else { ba.Add(expr.Value[0]); } } if (ba.Count > 1) { b = new FlatAddExpression(); var ct = (FlatAddExpression)b; foreach (var ci in ba) { ct.Add(ci); } } else if (ba.Count == 1) { b = ba[0]; } var sol = new BinaryExpression(new UnaryExpression(Enums.Operators.OperatorTypes.Sign, b), Enums.Operators.OperatorTypes.Divide, a).Execute(); res.Solutions.Add(variable, new Tuple <IExpression, List <IExpression> >(classification.SearchResult[variable].Item1, new List <IExpression>() { sol })); } return(res); }