public void ThenResolveReturnsTrue()
        {
            var subject = new And(0, 1);

            var result = subject.Resolve(new object(), new List<IExpression> { new TrueExpression(), new TrueExpression() });
            Assert.That(result, Is.True);
        }
Ejemplo n.º 2
0
 public void AndZero()
 {
     INode root = new And(VariableNode.Make<bool>(0, "x"), new Constant<bool>(false));
     Assert.AreEqual(
         bool.FalseString,
         SimplifyLogicTree(root).ToString());
 }
Ejemplo n.º 3
0
 public void AndOne()
 {
     INode root = new And(VariableNode.Make<bool>(0, "x"), new Constant<bool>(true));
     Assert.AreEqual(
         VariableNode.Make<bool>(0, "x").ToString(),
         SimplifyLogicTree(root).ToString());
 }
Ejemplo n.º 4
0
 public void TestSimpleAnd()
 {
     var and = new And(new Property("False"), new Property("False"));
     Assert.That(and.Evaluate(new Reflection(this)), Is.EqualTo(false));
     and = new And(new Property("True"), new Property("False"));
     Assert.That(and.Evaluate(new Reflection(this)), Is.EqualTo(false));
     and = new And(new Property("True"), new Property("True"));
     Assert.That(and.Evaluate(new Reflection(this)), Is.EqualTo(true));
 }
Ejemplo n.º 5
0
        public void Evaluate_And_True_Test()
        {
            Expression left = CreateBoolLiteral(true);
            Expression right = CreateBoolLiteral(true);

            Expression and = new And(left, right, pos);

            Values.Bool value = ((Values.Bool)and.Accept(evaluator));

            Assert.IsTrue(value.GetValue());
        }
Ejemplo n.º 6
0
        private static Condition GetWhereCondition(List<Compare> conditions, bool andOperator = true)
        {
            if (conditions.Count == 1)
                return conditions[0];
            LogicalCondition result;
            if (andOperator)
                result = new And();
            else
                result = new Or();

            result.Conditions =(Condition[]) Convert.ChangeType( conditions.ToArray(),typeof(Condition[]));
            return result;
        }
Ejemplo n.º 7
0
 public Type Visit(And node)
 {
     VisitBinaryOperator("AND", node, Type.BOOL);
     return(Type.BOOL);
 }
 public void Visit(And expression)
 {
     (var left, var right) = VisitBinary(expression);
     _result = new QLBoolean(AsBool(left) && AsBool(right));
 }
Ejemplo n.º 9
0
        public void ResultTypeBoolVarTest()
        {
            var exp = new And(new Bool(true), new Variable("x"));

            Assert.Equal(ExpressionResultType.Boolean, exp.ResultType);
        }
 //-----------------------------------------------------------
 public Type Visit(And node)
 {
     VisitBinaryOperator(".and.", node, Type.LOGICAL);
     return(Type.LOGICAL);
 }
Ejemplo n.º 11
0
 public virtual Result Visit(And and)
 {
     return(default(Result));
 }
Ejemplo n.º 12
0
 public void Visit(And and)
 {
     // "And" operator must be short circuited.
     and.Left.Accept(this);
     var br = Instruction.Create(OpCodes.Ldc_I4_0);
     _instructions.Add(Instruction.Create(OpCodes.Brfalse_S, br));
     and.Right.Accept(this);
     var end = Instruction.Create(OpCodes.Nop);
     _instructions.Add(Instruction.Create(OpCodes.Br, end));
     _instructions.Add(br);
     _instructions.Add(end);
 }
Ejemplo n.º 13
0
	void Awake()
	{
		node = new And(null, null);
		lChild.OnSlotFilled += LeftChildFilled;
		rChild.OnSlotFilled += RightChildFilled;
	}
Ejemplo n.º 14
0
        public void Conditional_Expression_Is_BoolType_True_Test()
        {
            List<FormObject> formObjects = new List<FormObject>();

            Expression and = new And(
                new Bool(false,position),
                new Bool(true,position),
                position);

            Conditional conditional = new Conditional(and, null, position);

            formObjects.Add(conditional);

            ExpressionContainerChecker expressionContainerChecker = new ExpressionContainerChecker(manager,null);
            INotificationManager notificationManager =  expressionContainerChecker.AnalyzeAndReport(formObjects);

            Assert.IsTrue(notificationManager.GetNotifications().Count == 0);
        }
Ejemplo n.º 15
0
 private Node ApplyDeMorgan(Node current)
 {
     // Pending: There should be a cleaner way of resolving all this casting
     if (current is LiteralNode)
     {
         return new ComplementNode(current.cargo);
     }
     else if (current is ComplementNode)
     {
         return new LiteralNode(current.cargo);
     }
     else if (current is And)
     {
         Or result = new Or(new OrOperator());
         result.left = ApplyDeMorgan((current as And).left);
         result.right = ApplyDeMorgan((current as And).right);
         return result;
     }
     else if (current is Or)
     {
         And result = new And(new AndOperator());
         result.left = ApplyDeMorgan((current as Or).left);
         result.right = ApplyDeMorgan((current as Or).right);
         return result;
     }
     else
     {
         return (current as Not).left;
     }
 }
Ejemplo n.º 16
0
 private Node term()
 {
     Node n = factor();
     while (_tokens.Current is AndOperator)
     {
         And and = new And(_tokens.Current);
         and.left = n;
         _tokens.MoveNext();
         n = factor();
         and.right = n;
         n = and;
     }
     return n;
 }
Ejemplo n.º 17
0
 private Node ApplyDistributiveProperty(Node current)
 {
     if ((current == null) || (current is TerminalNode))
     {
         return current;
     }
     else if (!(current is And))
     {
         NonTerminalNode nt = (NonTerminalNode)current;
         nt.left = ApplyDistributiveProperty(nt.left);
         nt.right = ApplyDistributiveProperty(nt.right);
         return nt;
     }
     else
     {
         And and = (And) current;
         // Check for an OR child
         Or childOr = (and.left as Or);
         Node otherChild = and.right;
         if (childOr == null)
         {
             childOr = (and.right as Or);
             otherChild = and.left;
         }
         // If neither child is an OR simply recurse
         if (childOr == null)
         {
             and.left = ApplyDistributiveProperty(and.left);
             and.right = ApplyDistributiveProperty(and.right);
             return and;
         }
         // If either child is an OR
         // convert (child.left OR child.right) AND otherChild into
         // (child.left AND otherChild) OR (child.right AND otherChild)
         else
         {
             // Create new operator nodes
             Or or = new Or(new OrOperator());
             And left = new And(new AndOperator());
             And right = new And(new AndOperator());
             // Populate new terms
             left.left = childOr.left;
             left.right = otherChild;
             right.left = childOr.right;
             right.right = otherChild;
             // Recursively apply distributive rule to new terms
             or.left = ApplyDistributiveProperty(left);
             or.right = ApplyDistributiveProperty(right);
             return or;
         }
     }
 }
        private void Initialize()
        {
            var add      = new Addition();
            var sub      = new Subtraction();
            var mul      = new Multiplication();
            var div      = new Division();
            var mean     = new Average();
            var sin      = new Sine();
            var cos      = new Cosine();
            var tan      = new Tangent();
            var log      = new Logarithm();
            var exp      = new Exponential();
            var @if      = new IfThenElse();
            var gt       = new GreaterThan();
            var lt       = new LessThan();
            var and      = new And();
            var or       = new Or();
            var not      = new Not();
            var constant = new Constant();

            constant.MinValue = -20;
            constant.MaxValue = 20;
            variableSymbol    = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable();

            var allSymbols = new List <Symbol>()
            {
                add, sub, mul, div, mean, sin, cos, tan, log, exp, @if, gt, lt, and, or, not, constant, variableSymbol
            };
            var unaryFunctionSymbols = new List <Symbol>()
            {
                sin, cos, tan, log, exp, not
            };
            var binaryFunctionSymbols = new List <Symbol>()
            {
                gt, lt
            };
            var functionSymbols = new List <Symbol>()
            {
                add, sub, mul, div, mean, and, or
            };

            foreach (var symb in allSymbols)
            {
                AddSymbol(symb);
            }

            foreach (var funSymb in functionSymbols)
            {
                SetSubtreeCount(funSymb, 1, 3);
            }
            foreach (var funSymb in unaryFunctionSymbols)
            {
                SetSubtreeCount(funSymb, 1, 1);
            }
            foreach (var funSymb in binaryFunctionSymbols)
            {
                SetSubtreeCount(funSymb, 2, 2);
            }

            SetSubtreeCount(@if, 3, 3);
            SetSubtreeCount(constant, 0, 0);
            SetSubtreeCount(variableSymbol, 0, 0);

            // allow each symbol as child of the start symbol
            foreach (var symb in allSymbols)
            {
                AddAllowedChildSymbol(StartSymbol, symb, 0);
            }

            // allow each symbol as child of every other symbol (except for terminals that have maxSubtreeCount == 0)
            foreach (var parent in allSymbols)
            {
                for (int i = 0; i < GetMaximumSubtreeCount(parent); i++)
                {
                    foreach (var child in allSymbols)
                    {
                        AddAllowedChildSymbol(parent, child, i);
                    }
                }
            }
        }
Ejemplo n.º 19
0
 public IFormula visit(And f)
 {
     return(new And(f.f1.visit(this), f.f2.visit(this)));
 }
Ejemplo n.º 20
0
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;

            Action<Equation> AssertIsTrue = (eq) =>
            {
                if (!eq) Console.WriteLine(eq.ToString());
            };

            Action<Equation> AssertIsFalse = (eq) =>
            {
                if (eq) Console.WriteLine(eq.ToString());
            };

            {
                var a = new Symbol("a");
                var b = new Symbol("b");
                var c = new Symbol("c");
                var d = new Symbol("d");

                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                Func<int, Integer> Int = (n) => new Integer(n);

                {
                    DoubleFloat.tolerance = 0.000000001;

                    Assert(new DoubleFloat(1.2).Equals(new DoubleFloat(1.2)), "new DoubleFloat(1.2).Equals(new DoubleFloat(1.2))");

                    Assert(new DoubleFloat(1.20000001).Equals(new DoubleFloat(1.20000002)) == false, "new DoubleFloat(1.20000001).Equals(new DoubleFloat(1.20000002)) == false");

                    Assert(new DoubleFloat(1.2000000000001).Equals(new DoubleFloat(1.200000000002)), "new DoubleFloat(1.2000000000001).Equals(new DoubleFloat(1.200000000002))");

                    Assert(new DoubleFloat(1.2).Equals(new DoubleFloat(1.23)) == false, "new DoubleFloat(1.2).Equals(new DoubleFloat(1.23)) == false");

                    DoubleFloat.tolerance = null;
                }

                #region Const

                AssertIsTrue((2 * x * y).Const() == 2);

                AssertIsTrue((x * y / 2).Const() == new Integer(1) / 2);

                AssertIsTrue((0.1 * x * y).Const() == 0.1);

                AssertIsTrue((x * y).Const() == 1);

                #endregion
            
                #region Simplify

                AssertIsTrue(x + x == 2 * x);

                AssertIsTrue(x + x == 2 * x);

                AssertIsTrue(x + x + x == 3 * x);

                AssertIsTrue(5 + x + 2 == 7 + x);

                AssertIsTrue(3 + x + 5 + x == 8 + 2 * x);

                AssertIsTrue(4 * x + 3 * x == 7 * x);

                AssertIsTrue(x + y + z + x + y + z == 2 * x + 2 * y + 2 * z);

                AssertIsTrue(10 - x == 10 + x * -1);

                AssertIsTrue(x * y / 3 == Int(1) / 3 * x * y);

                AssertIsTrue(x / y == x * (y ^ -1));

                AssertIsTrue(x / 3 == x * (Int(1) / 3));

                AssertIsTrue(6 * x * y / 3 == 2 * x * y);

                AssertIsTrue((((x ^ Int(1) / 2) ^ Int(1) / 2) ^ 8) == (x ^ 2));

                AssertIsTrue(((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2) == (x * y * (z ^ 4)));

                AssertIsTrue(x / x == 1);

                AssertIsTrue(x / y * y / x == 1);

                AssertIsTrue((x ^ 2) * (x ^ 3) == (x ^ 5));

                AssertIsTrue(x + y + x + z + 5 + z == 5 + 2 * x + y + 2 * z);

                AssertIsTrue(((Int(1) / 2) * x + (Int(3) / 4) * x) == Int(5) / 4 * x);

                AssertIsTrue(1.2 * x + 3 * x == 4.2 * x);

                AssertIsTrue(3 * x + 1.2 * x == 4.2 * x);

                AssertIsTrue(1.2 * x * 3 * y == 3.5999999999999996 * x * y);

                AssertIsTrue(3 * x * 1.2 * y == 3.5999999999999996 * x * y);

                AssertIsTrue(3.4 * x * 1.2 * y == 4.08 * x * y);

                AssertIsTrue((a == b) == (a == b));

                #endregion

                #region Power.Simplify

                AssertIsTrue((0 ^ x) == 0);
                AssertIsTrue((1 ^ x) == 1);
                AssertIsTrue((x ^ 0) == 1);
                AssertIsTrue((x ^ 1) == x);

                #endregion

                // Product.Simplify

                AssertIsTrue(x * 0 == 0);

                // Difference

                AssertIsTrue(-x == -1 * x);

                AssertIsTrue(x - y == x + -1 * y);

                #region Substitute

                AssertIsTrue(Int(10).Substitute(Int(10), 20) == 20);
                AssertIsTrue(Int(10).Substitute(Int(15), 20) == 10);

                AssertIsTrue(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.0), 2.0) == 2.0);
                AssertIsTrue(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.5), 2.0) == 1.0);

                AssertIsTrue((Int(1) / 2).Substitute(Int(1) / 2, Int(3) / 4) == Int(3) / 4);
                AssertIsTrue((Int(1) / 2).Substitute(Int(1) / 3, Int(3) / 4) == Int(1) / 2);

                AssertIsTrue(x.Substitute(x, y) == y);
                AssertIsTrue(x.Substitute(y, y) == x);

                AssertIsTrue((x ^ y).Substitute(x, 10) == (10 ^ y));
                AssertIsTrue((x ^ y).Substitute(y, 10) == (x ^ 10));

                AssertIsTrue((x ^ y).Substitute(x ^ y, 10) == 10);

                AssertIsTrue((x * y * z).Substitute(x, y) == ((y ^ 2) * z));
                AssertIsTrue((x * y * z).Substitute(x * y * z, x) == x);

                AssertIsTrue((x + y + z).Substitute(x, y) == ((y * 2) + z));
                AssertIsTrue((x + y + z).Substitute(x + y + z, x) == x);

                AssertIsTrue(
                    ((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2)
                        .Substitute(x, 10)
                        .Substitute(y, 20)
                        .Substitute(z, 3)
                        == 16200
                        );

                #region Equation.Substitute

                AssertIsTrue((x == y).Substitute(y, z) == (x == z));

                AssertIsTrue((x != y).Substitute(y, z) == (x != z));

                (x == 0).Substitute(x, 0).AssertEqTo(true);

                (x == 0).Substitute(x, 1).AssertEqTo(false);

                (x != 0).Substitute(x, 0).AssertEqTo(false);

                (x != 0).Substitute(x, 1).AssertEqTo(true);

                #endregion

                #endregion

                AssertIsTrue(sin(new DoubleFloat(3.14159 / 2)) == 0.99999999999911982);

                AssertIsTrue(sin(x + y) + sin(x + y) == 2 * sin(x + y));

                AssertIsTrue(sin(x + x) == sin(2 * x));

                AssertIsTrue(sin(x + x).Substitute(x, 1) == sin(Int(2)));

                AssertIsTrue(sin(x + x).Substitute(x, 1.0) == 0.90929742682568171);

                AssertIsTrue(sin(2 * x).Substitute(x, y) == sin(2 * y));

                // Product.RecursiveSimplify

                AssertIsTrue(1 * x == x);

                AssertIsTrue(x * 1 == x);

                AssertIsTrue(x != y);

                AssertIsTrue(x != 10);

                // ==(double a, MathObject b)

                AssertIsTrue(1.0 == new DoubleFloat(3.0) - 2.0);

                AssertIsTrue((a == b) != (a != b));
                
                (sqrt(a * b) * (sqrt(a * b) / a) / c)
                    .AssertEqTo(b / c);


                Action<MathObject, string> AssertToStringMatch = 
                    (MathObject obj, string str) => Assert(obj.ToString() == str, $"({str}).ToString()");
                
                MathObject.ToStringForm = MathObject.ToStringForms.Full;
                                
                AssertToStringMatch(x + y + z, "x + y + z");
                                
                AssertToStringMatch(x + y * z, "x + y * z");
                                                
                AssertToStringMatch((x + y) * z, "(x + y) * z");
                
                Assert((sin(x) * cos(y)).ToString() == "cos(y) * sin(x)", "(sin(x) * cos(y)).ToString()");
                                
                AssertToStringMatch(and(x, y, z), "and(x, y, z)");
                                
                AssertToStringMatch(x ^ y, "x ^ y");
                                
                AssertToStringMatch((x * y) ^ (x + z), "(x * y) ^ (x + z)");


                
                Assert((x - y).ToString() == "x + -1 * y", "(x - y).ToString()");

                Assert((x - y - z).ToString() == "x + -1 * y + -1 * z", "(x - y - z).ToString()");

                Assert((x / y).ToString() == "x * y ^ -1", "(x / y).ToString()");
                
                Assert((x - (y - z)).ToString() == "x + -1 * (y + -1 * z)", "(x - (y - z)).ToString()");


                MathObject.ToStringForm = MathObject.ToStringForms.Standard;
                
                Assert((x + y).ToString() == "x + y", "(x + y).ToString()");

                Assert((x - y).ToString() == "x - y", "(x - y).ToString()");
                    
                Assert((x - y - z).ToString() == "x - y - z", "(x - y - z).ToString()");
                    
                Assert((-x - y - z).ToString() == "-x - y - z", "(x - y - z).ToString()");
                    
                Assert((2 * x - 3 * y - 4 * z).ToString() == "2 * x - 3 * y - 4 * z", "(2 * x - 3 * y - 4 * z).ToString()");
                    
                Assert((x - (y - z)).ToString() == "x - (y - z)", "(x - (y - z)).ToString()");
                
                Assert((x - y + z).ToString() == "x - y + z", "(x - y + z).ToString()");
                    
                Assert((-x).ToString() == "-x", "(-x).ToString()");
                    
                Assert((x / y).ToString() == "x / y", "(x / y).ToString()");
                    
                Assert((x / (y + z)).ToString() == "x / (y + z)", "(x / (y + z)).ToString()");
                                        
                Assert(((x + y) / (x + z)).ToString() == "(x + y) / (x + z)", "((x + y) / (x + z)).ToString()");
                                        
                Assert((-x * y).ToString() == "-x * y", "(-x * y).ToString()");

                Assert((x * -y).ToString() == "-x * y", "(x * -y).ToString()");


                Assert(sin(x / y).ToString() == "sin(x / y)", "sin(x / y).ToString()");
                                                
                Assert(
                    (x == -sqrt(2 * y * (-z * a + y * (b ^ 2) / 2 - c * y * d + c * y * z * sin(x))) / y).ToString() ==
                    "x == -sqrt(2 * y * ((b ^ 2) * y / 2 - c * d * y - a * z + c * sin(x) * y * z)) / y",
                    "(x == -sqrt(2 * y * (-z * a + y * (b ^ 2) / 2 - c * y * d + c * y * z * sin(x))) / y).ToString()");
                
                Assert((x * (y ^ z)).ToString() == "x * (y ^ z)", "(x * (y ^ z)).ToString()");

                Assert((x + (y ^ z)).ToString() == "x + (y ^ z)", "((x + (y ^ z)).ToString()");
                
                Assert(sqrt(x).ToString() == "sqrt(x)", "sqrt(x).ToString()");
                
                Assert(sqrt(x).FullForm().ToString() == "x ^ 1/2", "sqrt(x).FullForm()");
                
                Assert((x ^ (new Integer(1) / 3)).ToString() == "x ^ 1/3", "(x ^ (new Integer(1) / 3)).ToString()");

                Assert(and(and(x, y), and(x, z)).SimplifyLogical().ToString() == "and(x, y, z)", 
                    "and(and(x, y), and(x, z)).SimplifyLogical().ToString()");

                AssertToStringMatch(x == sqrt(2 * (y * z - cos(a) * y * z)), "x == sqrt(2 * (y * z - cos(a) * y * z))");
                                
                AssertToStringMatch(
                     a == (-c * cos(d) - b * c * sin(d) + x * y + b * x * z) / (-y - z),
                    "a == (-c * cos(d) - b * c * sin(d) + x * y + b * x * z) / (-y - z)");
                
                AssertToStringMatch(
                     x == -(sin(y) / cos(y) + sqrt((sin(y) ^ 2) / (cos(y) ^ 2))) * (z ^ 2) / a,
                    "x == -(sin(y) / cos(y) + sqrt((sin(y) ^ 2) / (cos(y) ^ 2))) * (z ^ 2) / a");
                                
                AssertToStringMatch(x * sqrt(y), "x * sqrt(y)");
                                
                AssertToStringMatch(x / sqrt(y), "x / sqrt(y)");

                AssertToStringMatch(sqrt(y) / x, "sqrt(y) / x");
                
                AssertToStringMatch((x ^ 2) / (y ^ 3), "(x ^ 2) / (y ^ 3)");
                                                               
                AssertToStringMatch(
                     x == y * sqrt(-8 * a / (y * (z ^ 2))) * (z ^ 2) / (4 * a),
                    "x == y * sqrt(-8 * a / (y * (z ^ 2))) * (z ^ 2) / (4 * a)");
                
                AssertToStringMatch(-(-1 + x), "-(-1 + x)");
                
                #region Equation.ToString

                Assert((x == y).ToString() == "x == y", "x == y");

                Assert((x != y).ToString() == "x != y", "x != y");

                #endregion

                #region Function.ToString

                Assert(new And().ToString() == "and()", "and()");
               
                #endregion

                #region Equation.Simplify

                (new Integer(0) == new Integer(0)).Simplify().AssertEqTo(true);

                (new Integer(0) == new Integer(1)).Simplify().AssertEqTo(false);

                (new Integer(0) != new Integer(1)).Simplify().AssertEqTo(true);

                (new Integer(0) != new Integer(0)).Simplify().AssertEqTo(false);

                #endregion

                #region And

                and().AssertEqTo(true);

                and(10).AssertEqTo(10);

                and(true).AssertEqTo(true);

                and(false).AssertEqTo(false);

                and(10, 20, 30).AssertEqTo(and(10, 20, 30));

                and(10, false, 20).AssertEqTo(false);

                and(10, true, 20).AssertEqTo(and(10, 20));

                and(10, and(20, 30), 40)
                    
                    .AssertEqTo(and(10, 20, 30, 40));

                #endregion

                #region Or

                or(10).AssertEqTo(10);

                or(true).AssertEqTo(true);

                or(false).AssertEqTo(false);

                or(10, 20, false).AssertEqTo(or(10, 20));

                or(false, false).AssertEqTo(false);

                or(10, true, 20, false).AssertEqTo(true);

                or(10, false, 20).AssertEqTo(or(10, 20));

                or(10, or(20, 30), 40)
                    
                    .AssertEqTo(or(10, 20, 30, 40));

                #endregion

                #region Function.Map

                new And(1, 2, 3, 4, 5, 6).Map(elt => elt * 2)
                    .AssertEqTo(and(2, 4, 6, 8, 10, 12));

                new And(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
                    .AssertEqTo(false);

                new Or(1, 2, 3).Map(elt => elt * 2)
                    .AssertEqTo(or(2, 4, 6));

                new Or(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
                    .AssertEqTo(or(2, 4, 6));

                #endregion Function.Map

                #region Sum

                Assert((x + y).Equals(x * y) == false, "(x + y).Equals(x * y)");

                #endregion
                
                {
                    (x < y).Substitute(x, 10).Substitute(y, 20).AssertEqTo(true);

                    (x > y).Substitute(x, 10).Substitute(y, 20).AssertEqTo(false);
                }

                var Pi = new Symbol("Pi");

                var half = new Integer(1) / 2;

                #region Sin



                {
                    sin(0).AssertEqTo(0);

                    sin(Pi).AssertEqTo(0);

                    sin(-10).AssertEqTo(-sin(10));

                    sin(-x).AssertEqTo(-sin(x));

                    sin(-5 * x).AssertEqTo(-sin(5 * x));

                    // sin(k/n pi) for n = 1 2 3 4 6

                    sin(-2 * Pi).AssertEqTo(0);
                    sin(-1 * Pi).AssertEqTo(0);
                    sin( 2 * Pi).AssertEqTo(0);
                    sin( 3 * Pi).AssertEqTo(0);

                    sin(-7 * Pi / 2).AssertEqTo(1);
                    sin(-5 * Pi / 2).AssertEqTo(-1);
                    sin(-3 * Pi / 2).AssertEqTo(1);
                    sin(-1 * Pi / 2).AssertEqTo(-1);
                    sin( 1 * Pi / 2).AssertEqTo(1);
                    sin( 3 * Pi / 2).AssertEqTo(-1);
                    sin( 5 * Pi / 2).AssertEqTo(1);
                    sin( 7 * Pi / 2).AssertEqTo(-1);
                    
                    sin(-4 * Pi / 3).AssertEqTo( sqrt(3)/2);
                    sin(-2 * Pi / 3).AssertEqTo(-sqrt(3)/2);
                    sin(-1 * Pi / 3).AssertEqTo(-sqrt(3)/2);
                    sin( 1 * Pi / 3).AssertEqTo( sqrt(3)/2);
                    sin( 2 * Pi / 3).AssertEqTo( sqrt(3)/2);
                    sin( 4 * Pi / 3).AssertEqTo(-sqrt(3)/2);
                    sin( 5 * Pi / 3).AssertEqTo(-sqrt(3)/2);
                    sin( 7 * Pi / 3).AssertEqTo( sqrt(3)/2);

                    sin(-3 * Pi / 4).AssertEqTo(-1/sqrt(2));
                    sin(-1 * Pi / 4).AssertEqTo(-1/sqrt(2));
                    sin( 1 * Pi / 4).AssertEqTo( 1/sqrt(2));
                    sin( 3 * Pi / 4).AssertEqTo( 1/sqrt(2));
                    sin( 5 * Pi / 4).AssertEqTo(-1/sqrt(2));
                    sin( 7 * Pi / 4).AssertEqTo(-1/sqrt(2));
                    sin( 9 * Pi / 4).AssertEqTo( 1/sqrt(2));
                    sin(11 * Pi / 4).AssertEqTo( 1/sqrt(2));

                    // var half = new Integer(1) / 2;

                    sin(-5 * Pi / 6).AssertEqTo(-half);
                    sin(-1 * Pi / 6).AssertEqTo(-half);
                    sin( 1 * Pi / 6).AssertEqTo( half);
                    sin( 5 * Pi / 6).AssertEqTo( half);
                    sin( 7 * Pi / 6).AssertEqTo(-half);
                    sin(11 * Pi / 6).AssertEqTo(-half);
                    sin(13 * Pi / 6).AssertEqTo( half);
                    sin(17 * Pi / 6).AssertEqTo( half);

                    // sin(a/b pi) where a/b > 1/2 (i.e. not in first quadrant)

                    sin(15 * Pi / 7).AssertEqTo( sin(1 * Pi / 7));
                    sin( 8 * Pi / 7).AssertEqTo(-sin(1 * Pi / 7));
                    sin( 4 * Pi / 7).AssertEqTo( sin(3 * Pi / 7));

                    // sin( a + b + ... + n * pi ) where abs(n) >= 2

                    sin(x - 3 * Pi).AssertEqTo(sin(x + Pi));
                    sin(x - 2 * Pi).AssertEqTo(sin(x));
                    sin(x + 2 * Pi).AssertEqTo(sin(x));
                    sin(x + 3 * Pi).AssertEqTo(sin(x + Pi));
                    sin(x + 7 * Pi / 2).AssertEqTo(sin(x + 3 * Pi / 2));

                    // sin( a + b + ... + n/2 * pi )

                    sin(x - 3 * Pi / 2).AssertEqTo( cos(x));
                    sin(x - 1 * Pi / 2).AssertEqTo(-cos(x));
                    sin(x + 1 * Pi / 2).AssertEqTo( cos(x));
                    sin(x + 3 * Pi / 2).AssertEqTo(-cos(x));
                }


                {
                    sin(Pi + x).AssertEqTo(-sin(x));
                    
                    sin(Pi + x + y).AssertEqTo(-sin(x + y));
                }

                {
                    // var Pi = new Symbol("Pi");

                    cos(Pi + x).AssertEqTo(-cos(x));

                    cos(Pi + x + y).AssertEqTo(-cos(x + y));
                }


                #endregion

                #region Cos

                {
                    // var Pi = new Symbol("Pi");

                    cos(0).AssertEqTo(1);

                    cos(Pi).AssertEqTo(-1);

                    cos(-10).AssertEqTo(cos(10));

                    cos(-10 * x).AssertEqTo(cos(10 * x));

                    cos(3 * Pi).AssertEqTo(-1);

                    cos(2 * Pi * 3 / 4).AssertEqTo(0);

                    // cos( a + b + ... + n * pi ) where abs(n) >= 2

                    cos(x - 3 * Pi).AssertEqTo(cos(x + Pi));
                    cos(x + 3 * Pi).AssertEqTo(cos(x + Pi));

                    cos(x - 2 * Pi).AssertEqTo(cos(x));
                    cos(x + 2 * Pi).AssertEqTo(cos(x));

                    cos(x + Pi * 7 / 2).AssertEqTo(cos(x + Pi * 3 / 2));

                    // cos( a + b + ... + n/2 * pi )

                    cos(x - Pi * 3 / 2).AssertEqTo(-sin(x));
                    cos(x - Pi * 1 / 2).AssertEqTo(sin(x));
                    cos(x + Pi * 1 / 2).AssertEqTo(-sin(x));
                    cos(x + Pi * 3 / 2).AssertEqTo(sin(x));
                }


                #endregion
                
                #region Has

                Assert(a.Has(elt => elt == a), "a.Has(elt => elt == a)");

                Assert(a.Has(elt => elt == b) == false, "a.Has(elt => elt == b) == false");

                Assert((a == b).Has(elt => elt == a), "Has - 3");

                Assert((a == b).Has(elt => elt == c) == false, "Has - 4");

                Assert(((a + b) ^ c).Has(elt => elt == a + b), "Has - 5");

                Assert(((a + b) ^ c).Has(elt => (elt is Power) && (elt as Power).exp == c), "Has - 6");

                Assert((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).Has(b)), "Has - 7");

                Assert((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).elts.Any(obj => obj == b)), "Has - 8");

                Assert((x * (a + b + c)).Has(elt => (elt is Product) && (elt as Product).elts.Any(obj => obj == b)) == false, "Has - 9");

                #endregion

                #region FreeOf

                Assert((a + b).FreeOf(b) == false, "(a + b).FreeOf(b)");
                Assert((a + b).FreeOf(c) == true, "(a + b).FreeOf(c)");
                Assert(((a + b) * c).FreeOf(a + b) == false, "((a + b) * c).FreeOf(a + b)");
                Assert((sin(x) + 2 * x).FreeOf(sin(x)) == false, "(sin(x) + 2 * x).FreeOf(sin(x))");
                Assert(((a + b + c) * d).FreeOf(a + b) == true, "((a + b + c) * d).FreeOf(a + b)");
                Assert(((y + 2 * x - y) / x).FreeOf(x) == true, "((y + 2 * x - y) / x).FreeOf(x)");
                Assert(((x * y) ^ 2).FreeOf(x * y) == true, "((x * y) ^ 2).FreeOf(x * y)");

                #endregion

                // Symbolism.Numerator.Extensions.Numerator(x ^ -2).Disp();

                #region Numerator

                AssertIsTrue((x ^ -1).Numerator() == 1);

                AssertIsTrue((x ^ -half).Numerator() == 1);
                

                #endregion

                #region Denominator
                {


                    ((new Integer(2) / 3) * ((x * (x + 1)) / (x + 2)) * (y ^ z))
                        .Denominator()
                        .AssertEqTo(3 * (x + 2));
                }
                #endregion
                
                #region LogicalExpand

                and(or(a, b), c)
                    .LogicalExpand()
                    .AssertEqTo(
                        or(
                            and(a, c),
                            and(b, c)));

                and(a, or(b, c))
                    .LogicalExpand()
                    .AssertEqTo(or(and(a, b), and(a, c)));

                and(a, or(b, c), d)
                    .LogicalExpand()
                    .AssertEqTo(
                        or(
                            and(a, b, d),
                            and(a, c, d)));

                and(or(a == b, b == c), x == y)
                    .LogicalExpand()
                    .AssertEqTo(
                        or(
                            and(a == b, x == y),
                            and(b == c, x == y)));

                and(
                    or(a == b, b == c),
                    or(c == d, d == a),
                    x == y)
                    .LogicalExpand()
                    .AssertEqTo(
                        or(
                            and(a == b, c == d, x == y),
                            and(a == b, d == a, x == y),
                            and(b == c, c == d, x == y),
                            and(b == c, d == a, x == y)));

                #endregion

                #region SimplifyEquation

                (2 * x == 0)
                    .SimplifyEquation()
                    .AssertEqTo(x == 0);

                (2 * x != 0)
                    .SimplifyEquation()
                    .AssertEqTo(x != 0);

                ((x ^ 2) == 0)
                    .SimplifyEquation()
                    .AssertEqTo(x == 0);

                #endregion

                #region SimplifyLogical

                and(a, b, c, a)
                    .SimplifyLogical()
                    .AssertEqTo(and(a, b, c));

                #endregion SimplifyLogical

                #region DegreeGpe

                {
                    var w = new Symbol("w");

                    Assert(
                        ((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z }) == 6,
                        "((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z })");

                    Assert(
                        ((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x }) == 2,
                        "((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x })");

                    Assert(
                        (a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) }) == 2,
                        "(a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) })");

                    Assert(
                        (2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z }) == 7,
                        "(2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z })");
                }

                #endregion

                #region CoefficientGpe

                AssertIsTrue((a * (x ^ 2) + b * x + c).CoefficientGpe(x, 2) == a);

                AssertIsTrue((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 1) == 3 * (y ^ 2) + 7);

                AssertIsTrue((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 3) == 0);

                Assert(
                    (3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null,
                    "(3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null");

                #endregion

                #region AlgebraicExpand

                AssertIsTrue(
                    ((x + 2) * (x + 3) * (x + 4)).AlgebraicExpand()
                    ==
                    24 + 26 * x + 9 * (x ^ 2) + (x ^ 3));

                AssertIsTrue(
                    ((x + y + z) ^ 3).AlgebraicExpand()
                    ==
                    (x ^ 3) + (y ^ 3) + (z ^ 3) +
                    3 * (x ^ 2) * y +
                    3 * (y ^ 2) * x +
                    3 * (x ^ 2) * z +
                    3 * (y ^ 2) * z +
                    3 * (z ^ 2) * x +
                    3 * (z ^ 2) * y +
                    6 * x * y * z);

                AssertIsTrue(
                    (((x + 1) ^ 2) + ((y + 1) ^ 2)).AlgebraicExpand()
                    ==
                    2 + 2 * x + (x ^ 2) + 2 * y + (y ^ 2));

                AssertIsTrue(
                    ((((x + 2) ^ 2) + 3) ^ 2).AlgebraicExpand()
                    ==
                    49 + 56 * x + 30 * (x ^ 2) + 8 * (x ^ 3) + (x ^ 4));

                AssertIsTrue(
                    sin(x * (y + z)).AlgebraicExpand()
                    ==
                    sin(x * y + x * z));


                AssertIsTrue(
                    (a * (b + c) == x * (y + z)).AlgebraicExpand()
                    ==
                    (a * b + a * c == x * y + x * z));

                (5 * x * (500 / (x ^ 2) * (sqrt(3.0) / 4) + 1) + 2 * (x ^ 2) + (sqrt(3.0) / 2) * (x ^ 2))
                    .AlgebraicExpand()
                    .AssertEqTo(1082.5317547305483 / x + 5 * x + 2.8660254037844384 * (x ^ 2));

                #endregion

                #region IsolateVariable

                (x + y + z == 0).IsolateVariable(a).AssertEqTo(x + y + z == 0);

                // (x * a + x * b == 0).IsolateVariable(x).Disp();

                (x * (a + b) - x * a - x * b + x == c)
                    .IsolateVariable(x)
                    .AssertEqTo(x == c);

                and(x == y, a == b)
                    .IsolateVariable(b)
                    .AssertEqTo(and(x == y, b == a));

                or(and(y == x, z == x), and(b == x, c == x))
                    .IsolateVariable(x)
                    .AssertEqTo(or(and(x == y, x == z), and(x == b, x == c)));

                Assert((0 == x - y).IsolateVariableEq(x).Equals(x == y), "(0 == x - y).IsolateVariable(x).Equals(x == y)");

                

                (a * (x ^ 2) + b * x + c == 0)
                    .IsolateVariable(x)
                    .AssertEqTo(

                        or(

                            and(
                                x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            and(
                                x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            and(x == -c / b, a == 0, b != 0),

                            and(a == 0, b == 0, c == 0)
                        )
                    );

                (a * (x ^ 2) + c == 0)
                    .IsolateVariable(x)
                    .AssertEqTo(

                        or(
                            and(
                                x == sqrt(-4 * a * c) / (2 * a),
                                a != 0
                            ),

                            and(
                                x == -sqrt(-4 * a * c) / (2 * a),
                                a != 0
                            ),

                            and(a == 0, c == 0)
                        )
                    );

                // a x^2 + b x + c == 0
                // a x^2 + c == - b x
                // (a x^2 + c) / x == - b

                ((a * (x ^ 2) + c) / x == -b)
                    .IsolateVariable(x)
                    .AssertEqTo(

                    or(

                            and(
                                x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            and(
                                x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            and(x == -c / b, a == 0, b != 0),

                            and(a == 0, b == 0, c == 0)
                        )
                );

                (sqrt(x + y) == z).IsolateVariable(x).AssertEqTo(x == (z ^ 2) - y);

                (a * b + a == c)
                    .IsolateVariable(a)
                    .AssertEqTo(a == c / (b + 1));

                (a * b + a * c == d)
                    .IsolateVariable(a)
                    .AssertEqTo(a == d / (b + c));

                (1 / sqrt(x) == y)
                    .IsolateVariable(x)
                    .AssertEqTo(x == (y ^ -2));

                (y == sqrt(x) / x)
                    .IsolateVariable(x)
                    .AssertEqTo(x == (y ^ -2));

                (-sqrt(x) + z * x == y)
                    .IsolateVariable(x)
                    .AssertEqTo(-sqrt(x) + z * x == y);

                (sqrt(a + x) - z * x == -y)
                    .IsolateVariable(x)
                    .AssertEqTo(sqrt(a + x) - z * x == -y);

                (sqrt(2 + x) * sqrt(3 + x) == y)
                    .IsolateVariable(x)
                    .AssertEqTo(sqrt(2 + x) * sqrt(3 + x) == y);
                
                ((x + 1) / (x + 2) == 3)
                    .IsolateVariable(x)
                    .AssertEqTo(x == -new Integer(5) / 2);

                ((1 + 2 * x) / (3 * x - 4) == 5)
                    .IsolateVariable(x)
                    .AssertEqTo(x == new Integer(21) / 13);

                #endregion

                #region EliminateVariable

                and((x ^ 3) == (y ^ 5), z == x)
                .EliminateVariable(x)
                .AssertEqTo((z ^ 3) == (y ^ 5));

                and((x ^ 3) == (y ^ 5), z == (x ^ 7))
                .EliminateVariable(x)
                .AssertEqTo(and((x ^ 3) == (y ^ 5), z == (x ^ 7)));

                #endregion

                and(x + y == z, x / y == 0, x != 0).CheckVariable(x).AssertEqTo(false);
            }

            #region EliminateVariable
            
            {
                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");
                                
                var eqs = and(
                    (x ^ 2) - 4 == 0,
                    y + x == 0,
                    x + z == 10
                );
                
                var half = new Integer(1) / 2;
                                
                ((x ^ 2) - 4 == 0)
                    .IsolateVariableEq(x)
                    .AssertEqTo(or(x == half * sqrt(16), x == -half * sqrt(16)));

                eqs.EliminateVariable(x)
                    .AssertEqTo(
                        or(
                            and(
                                half * sqrt(16) + y == 0,
                                half * sqrt(16) + z == 10
                            ),
                            and(
                                -half * sqrt(16) + y == 0,
                                -half * sqrt(16) + z == 10
                            )
                        )
                    );
            }
            
            {
                var a = new Symbol("a");
                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                or(
                    and(x == y, x == z, x == a),
                    and(x == -y, x == z, x == a))
                    .EliminateVariable(x)
                    .AssertEqTo(
                        or(
                            and(y == z, y == a),
                            and(-y == z, -y == a)
                        )
                    )
                    .EliminateVariable(y)
                    .AssertEqTo(or(z == a, z == a));
            }
            
            {
                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                and(y != z, y == x, y == 10)
                    .EliminateVariable(y)
                    .AssertEqTo(and(x != z, x == 10));
            }

            #endregion

            #region PSE Example 2.6

            {
                var sAC = new Symbol("sAC");
                var sAB = new Symbol("sAB");

                var vA = new Symbol("vA");
                var vB = new Symbol("vB");
                var vC = new Symbol("vC");

                var a = new Symbol("a");

                var tAC = new Symbol("tAC");
                var tAB = new Symbol("tAB");
                
                var eqs = and(
                    tAB == tAC / 2,
                    Kinematic(sAC, vA, vC, a, tAC),
                    Kinematic(sAB, vA, vB, a, tAB)
                    );
                
                var vals = new List<Equation>() { vA == 10, vC == 30, tAC == 10 };

                eqs
                    .EliminateVariables(tAB, sAC, vB, sAB)
                    .IsolateVariable(a)
                    .AssertEqTo(a == (vC - vA) / tAC)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(a == 2);

                eqs
                    .EliminateVariables(vB, a, tAB, sAC)
                    .AssertEqTo(sAB == tAC / 4 * (2 * vA + (vC - vA) / 2))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(sAB == 75);
            }

            #endregion

            #region PSE Example 2.7
            {
                // s = 
                // u = 63
                // v =  0
                // a =
                // t =  2

                var s = new Symbol("s");
                var u = new Symbol("u");
                var v = new Symbol("v");
                var a = new Symbol("a");
                var t = new Symbol("t");
                
                var eqs = Kinematic(s, u, v, a, t);
                
                var vals = new List<Equation>() { u == 63, v == 0, t == 2.0 };

                eqs
                    .EliminateVariable(s)
                    .AssertEqTo(v == a * t + u)
                    .IsolateVariable(a)
                    .AssertEqTo(a == (v - u) / t)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(a == -31.5);

                eqs
                    .EliminateVariable(a)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(s == 63.0);
            }
            #endregion

            #region PSE Example 2.8
            {
                // car
                //
                // s1 =  
                // u1 = 45
                // v1 = 45
                // a1 =  0
                // t1 = 

                // officer
                //
                // s2 =  
                // u2 =  0
                // v2 = 
                // a2 =  3
                // t2

                var s1 = new Symbol("s1");
                var u1 = new Symbol("u1");
                var v1 = new Symbol("v1");
                var a1 = new Symbol("a1");
                var t1 = new Symbol("t1");

                var s2 = new Symbol("s2");
                var u2 = new Symbol("u2");
                var v2 = new Symbol("v2");
                var a2 = new Symbol("a2");
                var t2 = new Symbol("t2");
                                                
                var eqs = and(
                    u1 == v1,
                    s1 == s2,
                    t2 == t1 - 1,
                    Kinematic(s1, u1, v1, a1, t1),
                    Kinematic(s2, u2, v2, a2, t2));
                
                var vals = new List<Equation>() 
                {
                    v1 == 45.0,
                    u2 == 0,
                    a2 == 3
                };

                eqs
                    .EliminateVariables(s2, t1, a1, s1, v2, u1)
                    .IsolateVariable(t2)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(t2 == -0.96871942267131317, t2 == 30.968719422671313));
            }
            #endregion

            #region PSE Example 2.12

            {
                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");
                var yD = new Symbol("yD");

                var tA = new Symbol("tA");
                var tB = new Symbol("tB");
                var tC = new Symbol("tC");
                var tD = new Symbol("tD");

                var vA = new Symbol("vA");
                var vB = new Symbol("vB");
                var vC = new Symbol("vC");
                var vD = new Symbol("vD");

                var a = new Symbol("a");
                                                
                var eqs = and(
                    Kinematic(yA, yB, vA, vB, a, tA, tB),
                    Kinematic(yB, yC, vB, vC, a, tB, tC),
                    Kinematic(yC, yD, vC, vD, a, tC, tD));
                
                var vals = new List<Equation>()
                {
                    yA == 50,
                    yC == 50,
                    vA == 20,
                    vB == 0,
                    a == -9.8,
                    tA == 0,
                    tD == 5
                };

                // velocity and position at t = 5.00 s

                DoubleFloat.tolerance = 0.000000001;

                eqs
                    .EliminateVariables(tB, tC, vC, yB, yD)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(vD == -29.000000000000004, vD == -29.000000000000007));

                eqs
                    .EliminateVariables(tB, tC, vC, yB, vD)
                    .IsolateVariable(yD)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(yD == 27.499999999, yD == 27.499999999));

                DoubleFloat.tolerance = null;
            }

            #endregion
            
            #region PSE Example 4.3
            {
                // A long-jumper leaves the ground at an angle of 20.0° above
                // the horizontal and at a speed of 11.0 m/s.

                // (a) How far does he jump in the horizontal direction?
                // (Assume his motion is equivalent to that of a particle.)

                // (b) What is the maximum height reached?

                var xA = new Symbol("xA");
                var xB = new Symbol("xB");
                var xC = new Symbol("xC");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");
                var vxC = new Symbol("vxC");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    tAC == 2 * tAB,


                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,


                    vxC == vxA + ax * tAB,
                    vyC == vyA + ay * tAB,

                    xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
                    yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2

                    );

                var zeros = new List<Equation>() { xA == 0, yA == 0, ax == 0, vyB == 0 };

                var vals = new List<Equation>() { thA == (20).ToRadians(), vA == 11.0, ay == -9.8, Pi == Math.PI };

                eqs
                    .EliminateVariables(xB, yC, vxB, vxC, vyC, yB, tAC, vxA, vyA, tAB)
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(xC == -2 * cos(thA) * sin(thA) * (vA ^ 2) / ay)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(xC == 7.9364592624562507);

                eqs
                    .EliminateVariables(xB, yC, vxB, vxC, vyC, xC, vxA, tAC, vyA, tAB)
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(yB == -(sin(thA) ^ 2) * (vA ^ 2) / (2 * ay))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(yB == 0.72215873425009314);
            }

            #endregion
            
            #region PSE Example 4.3 KinematicObjectABC
            {
                // A long-jumper leaves the ground at an angle of 20.0° above
                // the horizontal and at a speed of 11.0 m/s.

                // (a) How far does he jump in the horizontal direction?
                // (Assume his motion is equivalent to that of a particle.)

                // (b) What is the maximum height reached?

                var obj = new KinematicObjectABC("obj");

                var yB = new Symbol("yB");
                var xC = new Symbol("xC");
                var ay = new Symbol("ay");
                var thA = new Symbol("thA");
                var vA = new Symbol("vA");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    obj.TrigEquationsA(),

                    obj.tAC == 2 * obj.tAB,

                    obj.EquationsAB(),
                    obj.EquationsAC()
                    
                    );

                var vals = new List<Equation>()
                {
                    obj.xA == 0,
                    obj.yA == 0,

                    obj.vA == vA,
                    obj.thA == thA,

                    obj.yB == yB,
                    obj.vyB == 0,

                    obj.xC == xC,

                    obj.ax == 0,
                    obj.ay == ay
                };

                var numerical_vals = new List<Equation>()
                {
                    thA == (20).ToRadians(),
                    vA == 11,
                    ay == -9.8,
                    Pi == Math.PI
                    
                };

                // xC
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(
                        obj.vxA, obj.vyA, obj.vyC, obj.vxC, obj.vxB,
                        obj.xB, yB, obj.yC,
                        obj.tAC, obj.tAB
                    )
                    
                    .AssertEqTo(xC == -2 * cos(thA) * sin(thA) * (vA ^ 2) / ay)

                    .SubstituteEqLs(numerical_vals)

                    .AssertEqTo(xC == 7.9364592624562507);

                // yB
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(
                        obj.tAB, obj.tAC,
                        obj.vxA, obj.vxB, obj.vxC, obj.vyC, obj.vyA,
                        obj.xB, xC, obj.yC
                    )
                    
                    .AssertEqTo(yB == -(sin(thA) ^ 2) * (vA ^ 2) / (2 * ay))

                    .SubstituteEqLs(numerical_vals)

                    .AssertEqTo(yB == 0.72215873425009314);

            }
            #endregion
            
            #region PSE 5E Example 4.5

            {
                var xA = new Symbol("xA");
                var xB = new Symbol("xB");
                var xC = new Symbol("xC");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");
                var vxC = new Symbol("vxC");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var vC = new Symbol("vC");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    // tAC == 2 * tAB,

                    // vxB == vxA + ax * tAB,
                    // vyB == vyA + ay * tAB,

                    // xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    // yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxC == vxA + ax * tAC,
                    vyC == vyA + ay * tAC,

                    // xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
                    yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2,

                    vC == sqrt((vxC ^ 2) + (vyC ^ 2)),

                    ay != 0
                );

                var zeros = new List<Equation>() { ax == 0, yC == 0 };
                var vals = new List<Equation>() { yA == 45, vA == 20, thA == (30).ToRadians(), ay == -9.8, Pi == Math.PI };

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .EliminateVariables(vC, vxA, vxC, vyC, vyA)
                    .IsolateVariable(tAC)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        or(
                            and(
                                tAC == -(sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
                                ay != 0),
                            and(
                                tAC == -(sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(tAC == 4.2180489012229376, tAC == -2.1772325746923267));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxC, vxA, vyA, vyC, tAC)
                    .SimplifyEquation().SimplifyLogical()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        or(
                            and(
                                ay != 0,
                                vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2))),
                            and(
                                ay != 0,
                                vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2)))))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(vC == 35.805027579936315, vC == 35.805027579936322));

                DoubleFloat.tolerance = null;
            }

            #endregion
            
            #region PSE 5E Example 4.6
            {
                // An Alaskan rescue plane drops a package of emergency rations to 
                // a stranded party of explorers, as shown in Figure 4.13.
                // If the plane is traveling horizontally at 40.0 m/s and is
                // 100 m above the ground, where does the package strike the
                // ground relative to the point at which it was released?

                // What are the horizontal and vertical components
                // of the velocity of the package just before it hits the ground?
                
                var xA = new Symbol("xA");
                var xB = new Symbol("xB");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxA != 0,

                    ay != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 100, vxA == 40, vyA == 0, yB == 0, ax == 0, ay == -9.8, Pi == Math.PI };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .EliminateVariables(vxB, vyB, tAB)
                    .IsolateVariable(xB)
                    .LogicalExpand().SimplifyEquation()
                    .CheckVariable(ay)
                    .CheckVariable(vxA).SimplifyLogical()
                    .SubstituteEq(ax == 0)        
                    .AssertEqTo(
                        or(
                            and(
                                vxA != 0,
                                xB == -(vxA ^ 2) * (-(- vyA / vxA + ay / (vxA ^ 2) * xA) + sqrt(((- vyA / vxA + ay * xA / (vxA ^ 2)) ^ 2) + 2 * ay * (vyA * xA / vxA - ay / 2 / (vxA ^ 2) * (xA ^ 2) - yA + yB) / (vxA ^ 2))) / ay,
                                ay / (vxA ^ 2) != 0,
                                ay != 0),
                            and(
                                vxA != 0,
                                xB == -(vxA ^ 2) * (-(-vyA / vxA + ay / (vxA ^ 2) * xA) - sqrt(((-vyA / vxA + ay * xA / (vxA ^ 2)) ^ 2) + 2 * ay * (vyA * xA / vxA - ay / 2 / (vxA ^ 2) * (xA ^ 2) - yA + yB) / (vxA ^ 2))) / ay,
                                ay / (vxA ^ 2) != 0,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(
                        or(
                            and(
                                vxA != 0,
                                xB == -1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
                                ay / (vxA ^ 2) != 0,
                                ay != 0),
                            and(
                                vxA != 0,
                                xB == 1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
                                ay / (vxA ^ 2) != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(xB == 180.70158058105022, xB == -180.70158058105022));

                eqs
                    .EliminateVariables(vxB, xB, tAB)
                    .IsolateVariable(vyB)
                    .LogicalExpand().SimplifyEquation()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        or(
                            and(
                                vyB == -1 * ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
                                vxA != 0,
                                ay != 0),
                            and(
                                vyB == ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
                                vxA != 0,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(
                        or(
                          and(
                              vyB == -ay * sqrt(-2 / ay * yA),
                              vxA != 0,
                              ay != 0),
                          and(
                              vyB == ay * sqrt(-2 / ay * yA),
                              vxA != 0,
                              ay != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(vyB == 44.271887242357309, vyB == -44.271887242357309));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E Example 4.7

            {
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var th = new Symbol("th");
                var d = new Symbol("d");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    cos(th) == (xB - xA) / d,
                    sin(th) == (yA - yB) / d,

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    yB != 0,

                    ay != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 0, vxA == 25, vyA == 0, ax == 0, ay == -9.8, th == (35).ToRadians(), Pi == Math.PI };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, yB, tAB)
                    .IsolateVariable(xB)
                    .LogicalExpand()
                    .CheckVariable(ay)
                    .SimplifyEquation()
                    .AssertEqTo(
                        or(
                            and(
                                xB == -(sin(th) / cos(th) + sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
                                ay / (vxA ^ 2) != 0,
                                sin(th) / cos(th) * xB != 0,
                                ay != 0),
                            and(
                                xB == -(sin(th) / cos(th) - sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
                                ay / (vxA ^ 2) != 0,
                                sin(th) / cos(th) * xB != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .SimplifyEquation()
                    .AssertEqTo(
                        or(
                            and(
                                xB == 89.312185996136435,
                                xB != 0),
                            and(
                                xB == 7.0805039835788038E-15,
                                xB != 0)));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, xB, tAB)
                    .IsolateVariable(yB)
                    .LogicalExpand()
                    .CheckVariable(yB)
                    .AssertEqTo(
                        and(
                            yB == 2 * (sin(th) ^ 2) * (vxA ^ 2) / ay / (cos(th) ^ 2),
                            -ay * (cos(th) ^ 2) / (sin(th) ^ 2) / (vxA ^ 2) / 2 != 0,
                            yB != 0,
                            ay != 0))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(
                        and(
                            yB == -62.537065888482395,
                            yB != 0));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, xB, yB)
                    .IsolateVariable(tAB)
                    .LogicalExpand().CheckVariable(ay).SimplifyEquation().SimplifyLogical()
                    .AssertEqTo(
                        or(
                            and(
                                tAB == -(sin(th) * vxA / cos(th) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
                                ay != 0,
                                sin(th) * tAB * vxA / cos(th) != 0),
                            and(
                                tAB == -(sin(th) * vxA / cos(th) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
                                ay != 0,
                                sin(th) * tAB * vxA / cos(th) != 0)))
                    .SubstituteEqLs(vals)
                    .CheckVariable(tAB).SimplifyEquation()
                    .AssertEqTo(
                        and(
                            tAB == 3.5724874398454571,
                            tAB != 0));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, d, tAB, xB, yB)
                    .IsolateVariable(vyB)
                    .LogicalExpand()
                    .CheckVariable(ay)
                    .SimplifyEquation()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        or(
                            and(
                                vyB == -ay * (sin(th) * vxA / (ay * cos(th)) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
                                sin(th) * vxA * vyB / (ay * cos(th)) != 0,
                                ay != 0),
                            and(
                                vyB == -ay * (sin(th) * vxA / (ay * cos(th)) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
                                sin(th) * vxA * vyB / (ay * cos(th)) != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .CheckVariable(vyB)
                    .SimplifyEquation()
                    .CheckVariable(vyB)
                    .AssertEqTo(
                        and(
                            vyB == -35.010376910485483,
                            vyB != 0));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.9

            {
                // In a local bar, a customer slides an empty beer mug
                // down the counter for a refill. The bartender is momentarily 
                // distracted and does not see the mug, which slides
                // off the counter and strikes the floor 1.40 m from the
                // base of the counter. If the height of the counter is 
                // 0.860 m, (a) with what velocity did the mug leave the
                // counter and (b) what was the direction of the mug’s 
                // velocity just before it hit the floor?
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var thB = new Symbol("thB");
                var vB = new Symbol("vB");

                var eqs = and(

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    tan(thB) == vyB / vxB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    xB != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 0.86, /* vxA */ vyA == 0, xB == 1.4, yB == 0, /* vxB vyB vB thB */ /* tAB */ ax == 0, ay == -9.8 };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(thB, vxB, vyB, tAB)
                    .IsolateVariable(vxA)
                    .LogicalExpand()
                    .AssertEqTo(
                        or(
                            and(
                                vxA == ay * (xB ^ 2) / yA / 4 * sqrt(-8 / ay * (xB ^ -2) * yA),
                                2 / ay * (xB ^ -2) * yA != 0,
                                xB != 0),
                            and(
                                vxA == -ay * (xB ^ 2) / yA / 4 * sqrt(-8 / ay * (xB ^ -2) * yA),
                                2 / ay * (xB ^ -2) * yA != 0,
                                xB != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(or(vxA == -3.3417722634053204, vxA == 3.3417722634053204));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, tAB, vxA)
                    .LogicalExpand()
                    .CheckVariable(xB)
                    .SimplifyLogical()
                    .IsolateVariable(thB)
                    .AssertEqTo(
                        and(
                            -tan(thB) / ay != 0,
                            thB == new Atan(-2 * yA / xB),
                            xB != 0))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(
                        and(
                            0.1020408163265306 * tan(thB) != 0,
                            thB == -0.88760488150470185));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region SumDifferenceFormulaFunc

            // sin(u) cos(v) - cos(u) sin(v) -> sin(u - v)

            Func<MathObject, MathObject> SumDifferenceFormulaFunc = elt =>
            {
                if (elt is Sum)
                {
                    var items = new List<MathObject>();

                    foreach (var item in (elt as Sum).elts)
                    {
                        if (
                            item is Product &&
                            (item as Product).elts[0] == -1 &&
                            (item as Product).elts[1] is Cos &&
                            (item as Product).elts[2] is Sin
                            )
                        {
                            var u_ = ((item as Product).elts[1] as Cos).args[0];
                            var v_ = ((item as Product).elts[2] as Sin).args[0];

                            Func<MathObject, bool> match = obj =>
                                obj is Product &&
                                (obj as Product).elts[0] is Cos &&
                                (obj as Product).elts[1] is Sin &&

                                ((obj as Product).elts[1] as Sin).args[0] == u_ &&
                                ((obj as Product).elts[0] as Cos).args[0] == v_;

                            if (items.Any(obj => match(obj)))
                            {
                                items = items.Where(obj => match(obj) == false).ToList();

                                items.Add(sin(u_ - v_));
                            }
                            else items.Add(item);
                        }
                        else items.Add(item);
                    }

                    return new Sum() { elts = items }.Simplify();
                }

                return elt;
            };

            {
                var u = new Symbol("u");
                var v = new Symbol("v");

                (sin(u) * cos(v) - cos(u) * sin(v))
                    .DeepSelect(SumDifferenceFormulaFunc)
                    .AssertEqTo(sin(u - v));
            }

            #endregion
            
            #region SumDifferenceFormulaFunc 

            // sin(u) cos(v) + cos(u) sin(v) -> sin(u + v)

            Func<MathObject, MathObject> SumDifferenceFormulaAFunc = elt =>
            {
                if (elt is Sum)
                {
                    var items = new List<MathObject>();

                    foreach (var item in (elt as Sum).elts)
                    {
                        if (
                            item is Product &&
                            (item as Product).elts[0] is Cos &&
                            (item as Product).elts[1] is Sin
                            )
                        {
                            var u_ = ((item as Product).elts[0] as Cos).args[0];
                            var v_ = ((item as Product).elts[1] as Sin).args[0];

                            Func<MathObject, bool> match = obj =>
                                obj is Product &&
                                (obj as Product).elts[0] is Cos &&
                                (obj as Product).elts[1] is Sin &&

                                ((obj as Product).elts[1] as Sin).args[0] == u_ &&
                                ((obj as Product).elts[0] as Cos).args[0] == v_;

                            if (items.Any(obj => match(obj)))
                            {
                                items = items.Where(obj => match(obj) == false).ToList();

                                items.Add(sin(u_ + v_));
                            }
                            else items.Add(item);
                        }
                        else items.Add(item);
                    }

                    return new Sum() { elts = items }.Simplify();
                }

                return elt;
            };

            {
                var u = new Symbol("u");
                var v = new Symbol("v");

                (sin(u) * cos(v) + cos(u) * sin(v))
                    .DeepSelect(SumDifferenceFormulaAFunc)
                    .AssertEqTo(sin(u + v));
            }

            #endregion
            
            #region DoubleAngleFormulaFunc

            // sin(u) cos(u) -> sin(2 u) / 2

            Func<MathObject, MathObject> DoubleAngleFormulaFunc =
                    elt =>
                    {
                        if (elt is Product)
                        {
                            var items = new List<MathObject>();

                            foreach (var item in (elt as Product).elts)
                            {
                                if (item is Sin)
                                {
                                    var sym = (item as Sin).args.First();

                                    if (items.Any(obj => (obj is Cos) && (obj as Cos).args.First() == sym))
                                    {
                                        items = items.Where(obj => ((obj is Cos) && (obj as Cos).args.First() == sym) == false).ToList();

                                        items.Add(sin(2 * sym) / 2);
                                    }
                                    else items.Add(item);
                                }

                                else if (item is Cos)
                                {
                                    var sym = (item as Cos).args.First();

                                    if (items.Any(obj => (obj is Sin) && (obj as Sin).args.First() == sym))
                                    {
                                        items = items.Where(obj => ((obj is Sin) && (obj as Sin).args.First() == sym) == false).ToList();

                                        items.Add(sin(2 * sym) / 2);
                                    }
                                    else items.Add(item);
                                }

                                else items.Add(item);

                            }
                            return new Product() { elts = items }.Simplify();
                        }
                        return elt;
                    };

            #endregion

            #region SinCosToTanFunc


            // sin(x) / cos(x) -> tan(x)

            Func<MathObject, MathObject> SinCosToTanFunc = elt =>
            {
                if (elt is Product)
                {
                    if ((elt as Product).elts.Any(obj1 =>
                            obj1 is Sin &&
                            (elt as Product).elts.Any(obj2 => obj2 == 1 / cos((obj1 as Sin).args[0]))))
                    {
                        var sin_ = (elt as Product).elts.First(obj1 =>
                            obj1 is Sin &&
                            (elt as Product).elts.Any(obj2 => obj2 == 1 / cos((obj1 as Sin).args[0])));

                        var arg = (sin_ as Sin).args[0];

                        return elt * cos(arg) / sin(arg) * tan(arg);
                    }

                    return elt;
                }

                return elt;
            };

            #endregion

            {
                var x = new Symbol("x");
                var y = new Symbol("y");

                (sin(x) / cos(x)).DeepSelect(SinCosToTanFunc)

                    .AssertEqTo(tan(x));

                (y * sin(x) / cos(x)).DeepSelect(SinCosToTanFunc)

                    .AssertEqTo(tan(x) * y);

                (sin(x) * sin(y) / cos(x) / cos(y))
                    .DeepSelect(SinCosToTanFunc)
                    .DeepSelect(SinCosToTanFunc)

                    .AssertEqTo(tan(x) * tan(y));
            }
            
            #region PSE 5E P4.11

            {
                // One strategy in a snowball fight is to throw a first snowball
                // at a high angle over level ground. While your opponent is watching
                // the first one, you throw a second one at a low angle and timed
                // to arrive at your opponent before or at the same time as the first one.

                // Assume both snowballs are thrown with a speed of 25.0 m/s.

                // The first one is thrown at an angle of 70.0° with respect to the horizontal. 

                // (a) At what angle should the second (lowangle) 
                // snowball be thrown if it is to land at the same
                // point as the first?

                // (b) How many seconds later should the second snowball 
                // be thrown if it is to land at the same time as the first?
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");

                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = new And(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() { xA == 0, yA == 0, /* vxA vyA */ vA == 25.0, /* thA == 70.0, */ /* xB == 20.497, */ /* yB */ /* vxB */ vyB == 0, /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        // thA = ... || thA = ...

                        var expr = eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(yB, vxA, vyA, vxB, tAB)
                            .DeepSelect(DoubleAngleFormulaFunc)
                            .IsolateVariable(thA);

                        // th_delta = ...

                        var th1 = ((expr as Or).args[0] as Equation).b;
                        var th2 = ((expr as Or).args[1] as Equation).b;

                        var th_delta = new Symbol("th_delta");

                        eqs
                            .Add(th_delta == (th1 - th2).AlgebraicExpand())
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(yB, vxA, vyA, vxB, tAB)

                            .DeepSelect(DoubleAngleFormulaFunc)
                            .EliminateVariable(xB)

                            .AssertEqTo(th_delta == asin(sin(2 * thA)) - Pi / 2)

                            .SubstituteEq(thA == (70).ToRadians())
                            .SubstituteEq(Pi == Math.PI)

                            .AssertEqTo(th_delta == -0.87266462599716454)
                            ;
                    }

                    {
                        // tAB = ...

                        var tAB_eq = eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(yB, vxA, vyA, vxB, xB)
                            .IsolateVariable(tAB);

                        and(
                            or(thA == (20).ToRadians(), thA == (70).ToRadians()),
                            tAB_eq,
                            tAC == tAB * 2)
                            .LogicalExpand()
                            .EliminateVariables(thA, tAB)

                            .AssertEqTo(or(
                                tAC == -2 * sin(Pi / 9) * vA / ay,
                                tAC == -2 * sin(7 * Pi / 18) * vA / ay))

                            .SubstituteEqLs(vals)
                            .AssertEqTo(
                                or(
                                    tAC == 1.7450007312534115,
                                    tAC == 4.794350106050552));
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion


            #region PSE 5E P4.13

            {
                // An artillery shell is fired with an initial velocity of 
                // 300 m/s at 55.0° above the horizontal. It explodes on a
                // mountainside 42.0 s after firing. What are the x and y
                // coordinates of the shell where it explodes, relative to its
                // firing point?
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = and(
                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() { xA == 0, yA == 0, /* vxA vyA */ vA == 300.0, thA == (55).ToRadians(), /* xB yB vxB vyB */ tAB == 42, ax == 0, ay == -9.8, Pi == Math.PI };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariable(vxA)
                            .EliminateVariable(vyA)

                            .AssertEqTo(
                                and(
                                    vxB == cos(thA) * vA,
                                    vyB == ay * tAB + sin(thA) * vA,
                                    xB == cos(thA) * tAB * vA,
                                    yB == ay * (tAB ^ 2) / 2 + sin(thA) * tAB * vA))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                and(
                                    vxB == 172.07293090531385,
                                    vyB == -165.85438671330249,
                                    xB == 7227.0630980231817,
                                    yB == 1677.7157580412968))

                            ;
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.15

            {
                // A projectile is fired in such a way that its horizontal
                // range is equal to three times its maximum height.
                //
                // What is the angle of projection? 
                // Give your answer to three significant figures.
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");


                var xC = new Symbol("xC");
                var yC = new Symbol("yC");

                var vxC = new Symbol("vxC");
                var vyC = new Symbol("vyC");


                var tAB = new Symbol("tAB");
                var tBC = new Symbol("tBC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    xC - xA == 3 * yB,

                    tAB == tBC,


                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,


                    vxC == vxB + ax * tBC,
                    vyC == vyB + ay * tBC,

                    xC == xB + vxB * tBC + ax * (tBC ^ 2) / 2,
                    yC == yB + vyB * tBC + ay * (tBC ^ 2) / 2

                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() 
                    { 
                        xA == 0, yA == 0, /* vxA vyA vA thA */ /* xB yB vxB */ vyB == 0, /* tAB tBC */ 
                        /* xC */ yC == 0,

                        ax == 0, ay == -9.8, Pi == Math.PI 
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    eqs
                        .SubstituteEqLs(zeros)
                        .EliminateVariables(xC, tAB, vxA, vyA, vxB, xB, yB, vxC, vyC, tBC)
                        .IsolateVariable(thA)
                        .AssertEqTo(thA == new Atan(new Integer(4) / 3));
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.17

            {
                // A cannon with a muzzle speed of 1000 m/s is used to
                // start an avalanche on a mountain slope. The target is 
                // 2000 m from the cannon horizontally and 800 m above
                // the cannon.
                //
                // At what angle, above the horizontal, should the cannon be fired?

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");


                var xC = new Symbol("xC");
                var yC = new Symbol("yC");

                var vxC = new Symbol("vxC");
                var vyC = new Symbol("vyC");


                var tAB = new Symbol("tAB");
                var tBC = new Symbol("tBC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var phi = new Symbol("phi");

                var eqs = and(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() 
                    { 
                        xA ==    0, yA ==   0, /* vxA vyA */ vA == 1000, /* thA */ 
                        xB == 2000, yB == 800.0, /* vxB vyB */ 
                        /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI 
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(vxA, vyA, vxB, vyB, tAB)

                            .MultiplyBothSidesBy(cos(thA) ^ 2).AlgebraicExpand()
                            .Substitute(cos(thA) ^ 2, (1 + cos(2 * thA)) / 2)
                            .DeepSelect(DoubleAngleFormulaFunc).AlgebraicExpand()
                            .AddToBothSides(-sin(2 * thA) * xB / 2)
                            .AddToBothSides(-yB / 2)
                            .MultiplyBothSidesBy(2 / xB).AlgebraicExpand()

                            // yB / xB = tan(phi)
                            // yB / xB = sin(phi) / cos(phi)

                            // phi = atan(yB / xB)

                            .Substitute(cos(2 * thA) * yB / xB, cos(2 * thA) * sin(phi) / cos(phi))
                            .MultiplyBothSidesBy(cos(phi)).AlgebraicExpand()
                            .DeepSelect(SumDifferenceFormulaFunc)
                            .IsolateVariable(thA)

                            .Substitute(phi, new Atan(yB / xB).Simplify())

                            .AssertEqTo(
                                or(
                                    thA == -(asin(ay * cos(atan(yB / xB)) * (vA ^ -2) * xB + -1 * cos(atan(yB / xB)) * yB / xB) - atan(yB / xB)) / 2,
                                    thA == -(-asin(ay * cos(atan(yB / xB)) * (vA ^ -2) * xB - cos(atan(yB / xB)) * yB / xB) - atan(yB / xB) + Pi) / 2))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                or(
                                    thA == 0.39034573609628065,
                                    thA == -1.5806356857788124))
                            ;
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion
            
            #region PSE 5E P4.19

            {
                // A placekicker must kick a football from a point 36.0 m
                // (about 40 yards) from the goal, and half the crowd
                // hopes the ball will clear the crossbar, which is 3.05 m
                // high. When kicked, the ball leaves the ground with a
                // speed of 20.0 m/s at an angle of 53.0° to the horizontal.
                //
                // (a) By how much does the ball clear or fall short of
                //     clearing the crossbar ?
                //
                // (b) Does the ball approach the crossbar while still 
                //     rising or while falling ?
                
                Func <MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");
                
                var tAB = new Symbol("tAB");
                
                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var cleared_by = new Symbol("cleared_by");

                var goal_height = new Symbol("goal_height");
                
                var eqs = and(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    cleared_by == yB - goal_height
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        xA == 0, yA == 0, /* vxA vyA */ vA == 20, thA == (53).ToRadians(),
                        xB == 36, /* yB */ /* vxB vyB */ 
                        /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI,

                        goal_height == 3.05
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(vxA, vyA, vxB, vyB, tAB, yB)

                            .AssertEqTo(
                                cleared_by == -goal_height + sin(thA) / cos(thA) * xB + ay / 2 * (cos(thA) ^ -2) * (vA ^ -2) * (xB ^ 2)
                                )

                            .SubstituteEqLs(vals)

                            .AssertEqTo(cleared_by == 0.88921618776713007);
                    }

                    {
                        eqs
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(cleared_by, vxA, vyA, vxB, tAB, yB)
                            .IsolateVariable(vyB)

                            .AssertEqTo(vyB == sin(thA) * vA + ay / cos(thA) / vA * xB)
                            
                            .SubstituteEqLs(vals)

                            .AssertEqTo(vyB == -13.338621888454744);
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion
            
            #region PSE 5E P4.21

            {
                // A firefighter a distance d from a burning building directs 
                // a stream of water from a fire hose at angle θi above
                // the horizontal as in Figure P4.20.If the initial speed of
                // the stream is vi, at what height h does the water strike
                // the building?
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var d = new Symbol("d");
                var thi = new Symbol("thi");
                var vi = new Symbol("vi");
                var h = new Symbol("h");
                
                var eqs = and(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                    
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        xA == 0, yA == 0, /* vxA vyA */ vA == vi, thA == thi,
                        xB == d, yB == h, /* vxB vyB */ 
                        /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();
                    
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(vxA, vyA, vxB, vyB, tAB)
                            
                            .SubstituteEqLs(vals.Where(eq => eq.b is Symbol).ToList())

                            .AssertEqTo(

                                h == d * sin(thi) / cos(thi) + ay * (d ^ 2) / (cos(thi) ^ 2) / (vi ^ 2) / 2
                                
                                );
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion
            
            #region PSE 5E P4.23

            {
                // A basketball star covers 2.80 m horizontally in a jump to
                // dunk the ball. His motion through space can be modeled as 
                // that of a particle at a point called his center of mass. 
                // His center of mass is at elevation 1.02 m when he leaves 
                // the floor. It reaches a maximum height of 1.85 m above 
                // the floor and is at elevation 0.900 m when he touches down
                // again.

                // Determine:

                // (a) his time of flight (his “hang time”)

                // (b) his horizontal and (c) vertical velocity components at the instant of takeoff

                // (d) his takeoff angle. 

                // (e) For comparison, determine the hang time of a
                // whitetail deer making a jump with center-of-mass elevations
                // y_i = 1.20 m
                // y_max = 2.50 m
                // y_f = 0.700 m
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");


                var tAB = new Symbol("tAB");


                var xC = new Symbol("xC");
                var yC = new Symbol("yC");

                var vxC = new Symbol("vxC");
                var vyC = new Symbol("vyC");


                var tBC = new Symbol("tBC");

                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    //vxA == vA * cos(thA),
                    //vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,


                    vxC == vxB + ax * tBC,
                    vyC == vyB + ay * tBC,

                    xC == xB + vxB * tBC + ax * (tBC ^ 2) / 2,
                    yC == yB + vyB * tBC + ay * (tBC ^ 2) / 2,

                    tAC == tAB + tBC,

                    // vyA / vxA == tan(thA),

                    tan(thA) == vyA / vxA,

                    ay != 0

                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        xA == 0,    yA == 1.02, /* vxA vyA vA thA */
                        /* xB */    yB == 1.85, /* vxB            */ vyB == 0,
                        xC == 2.80, yC == 0.9,  /* vxC vyC        */

                        /* tAB tBC */ ax == 0, ay == -9.8, Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(thA, vxB, xB, vxC, vyC, vxA, vyA, tAB)

                            .CheckVariable(ay).SimplifyEquation().SimplifyLogical()

                            .EliminateVariable(tBC)

                            .LogicalExpand().SimplifyEquation().CheckVariable(ay).SimplifyLogical()

                            .AssertEqTo(

                                or(
                                    and(ay != 0, tAC == (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + -1 * (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))),
                                    and(ay != 0, tAC == (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))),
                                    and(ay != 0, tAC == -1 * (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + -1 * (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))),
                                    and(ay != 0, tAC == -1 * (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC)))))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(

                                or(
                                    tAC == 0.028747849043843032,
                                    tAC == -0.85188272280886768,
                                    tAC == 0.85188272280886768,
                                    tAC == -0.028747849043843032));
                    }

                    {
                        eqs
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(thA, vxB, vxC, xB)

                            .IsolateVariable(vxA)

                            .EliminateVariables(tAC, vyC, tAB, vyA)

                            .SimplifyEquation().CheckVariable(ay)

                            .EliminateVariable(tBC)

                            .LogicalExpand().SimplifyEquation().CheckVariable(ay).SimplifyLogical()

                            .AssertEqTo(

                                or(
                                    and(ay != 0, vxA == xC * ((-1 * sqrt(-2 * (ay ^ -1) * (-1 * yA + yB)) + -1 * (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))) ^ -1)),
                                    and(ay != 0, vxA == xC * ((-1 * sqrt(-2 * (ay ^ -1) * (-1 * yA + yB)) + (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))) ^ -1)),
                                    and(ay != 0, vxA == xC * ((sqrt(-2 * (ay ^ -1) * (-1 * yA + yB)) + -1 * (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))) ^ -1)),
                                    and(ay != 0, vxA == xC * ((sqrt(-2 * (ay ^ -1) * (-1 * yA + yB)) + (ay ^ -1) * sqrt(2 * ay * (-1 * yB + yC))) ^ -1))))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(

                                or(
                                    vxA == 97.398591307814215,
                                    vxA == -3.286837407346058,
                                    vxA == 3.286837407346058,
                                    vxA == -97.398591307814215));
                    }

                    {
                        eqs
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(thA, vxA, vxC, vyC, vxB, xB, tAB, tAC, tBC)

                            .SimplifyEquation().CheckVariable(ay).SimplifyLogical()

                            .IsolateVariable(vyA)

                            .LogicalExpand().SimplifyEquation().CheckVariable(ay)

                            .AssertEqTo(
                                or(
                                    and(ay != 0, vyA == ay * sqrt(-2 * (ay ^ -1) * (-1 * yA + yB))),
                                    and(ay != 0, vyA == -1 * ay * sqrt(-2 * (ay ^ -1) * (-1 * yA + yB)))))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                or(
                                    vyA == -4.0333608814486217,
                                    vyA == 4.0333608814486217));
                    }

                    {
                        eqs
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(vxA, vyA, vxB, xB, vxC, tBC, tAB, vyC, tAC)

                            .LogicalExpand()
                            .SimplifyEquation()
                            .SimplifyLogical()
                            .CheckVariable(ay)

                            .AssertEqTo(

                                or(
                                    and(ay != 0, tan(thA) == -1 * (xC ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) * ((ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + -1 * sqrt(2 * (ay ^ -1) * (-1 * yB + yC)))),
                                    and(ay != 0, tan(thA) == -1 * (xC ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) * ((ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + sqrt(2 * (ay ^ -1) * (-1 * yB + yC)))),
                                    and(ay != 0, tan(thA) == (xC ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) * (-1 * (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + -1 * sqrt(2 * (ay ^ -1) * (-1 * yB + yC)))),
                                    and(ay != 0, tan(thA) == (xC ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) * (-1 * (ay ^ -1) * sqrt(-2 * ay * (-1 * yA + yB)) + sqrt(2 * (ay ^ -1) * (-1 * yB + yC))))

                                    ))

                            .IsolateVariable(thA)

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                or(
                                    thA == 0.88702813023277882,
                                    thA == -0.041387227947930878,
                                    thA == -0.041387227947930878,
                                    thA == 0.88702813023277882));

                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E E5.1

            {
                // A hockey puck having a mass of 0.30 kg slides on the horizontal, 
                // frictionless surface of an ice rink. Two forces act on
                // the puck, as shown in Figure 5.5.The force F1 has a magnitude 
                // of 5.0 N, and the force F2 has a magnitude of 8.0 N.

                // Determine both the magnitude and the direction of the puck’s acceleration.

                // Determine the components of a third force that,
                // when applied to the puck, causes it to have zero acceleration.
                
                var F = new Symbol("F");
                var th = new Symbol("th");

                var Fx = new Symbol("Fx");
                var Fy = new Symbol("Fy");


                var F1 = new Symbol("F1");
                var th1 = new Symbol("th1");

                var F1x = new Symbol("F1x");
                var F1y = new Symbol("F1y");
                

                var F2 = new Symbol("F2");
                var th2 = new Symbol("th2");

                var F2x = new Symbol("F2x");
                var F2y = new Symbol("F2y");


                var F3 = new Symbol("F3");
                var th3 = new Symbol("th3");

                var F3x = new Symbol("F3x");
                var F3y = new Symbol("F3y");


                var a = new Symbol("a");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var m = new Symbol("m");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    Fx == F * cos(th),
                    Fy == F * sin(th),

                    Fx == ax * m,
                    Fy == ay * m,

                    Fx == F1x + F2x + F3x,
                    Fy == F1y + F2y + F3y,

                    F1x == F1 * cos(th1), F1y == F1 * sin(th1),

                    F2x == F2 * cos(th2), F2y == F2 * sin(th2),

                    F3x == F3 * cos(th3), F3y == F3 * sin(th3),

                    a == sqrt((ax ^ 2) + (ay ^ 2))

                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {

                        m == 0.3,

                        F1 == 5.0, th1 == (-20).ToRadians(),
                        F2 == 8.0, th2 == (60).ToRadians(),

                        F3 == 0,

                        Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // a 
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(ax, ay, Fx, Fy, F, F1x, F1y, F2x, F2y, F3x, F3y)
                            .DeepSelect(SinCosToTanFunc)
                            .EliminateVariable(th)
                            
                            .AssertEqTo(

                                a ==
                                    sqrt(
                                        ((cos(th1) * F1 + cos(th2) * F2) ^ 2) * (m ^ -2) +
                                        (cos(atan(((cos(th1) * F1 + cos(th2) * F2) ^ -1) * (F1 * sin(th1) + F2 * sin(th2)))) ^ -2) *
                                        ((cos(th1) * F1 + cos(th2) * F2) ^ 2) *
                                        (m ^ -2) *
                                        (sin(atan(((cos(th1) * F1 + cos(th2) * F2) ^ -1) * (F1 * sin(th1) + F2 * sin(th2)))) ^ 2))

                            )

                            .SubstituteEqLs(vals)

                            .Substitute(3, 3.0)

                            //.DispLong()

                            .AssertEqTo(a == 33.811874017759315);
                    }

                    // th
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(a, F, Fx, Fy, ax, ay, F1x, F1y, F2x, F2y, F3x, F3y)
                            .DeepSelect(SinCosToTanFunc)
                            .IsolateVariable(th)

                            .AssertEqTo(

                                th == atan((F1 * sin(th1) + F2 * sin(th2)) / (cos(th1) * F1 + cos(th2) * F2))

                                )

                            .SubstituteEqLs(vals)

                            .Substitute(3, 3.0)

                            .AssertEqTo(th == 0.54033704850428876);
                    }
                }

                {
                    var vals = new List<Equation>()
                    {

                        m == 0.3,

                        F1 == 5.0, th1 == (-20).ToRadians(),
                        F2 == 8.0, th2 == (60).ToRadians(),

                        ax == 0, ay == 0,

                        Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();
                    
                    // F3x
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(F3, th3, F3y, F1x, F2x, Fx, F, Fy, F1y, F2y, a)
                            .IsolateVariable(F3x)
                            
                            .AssertEqTo(F3x == -1 * cos(th1) * F1 + -1 * cos(th2) * F2)

                            .SubstituteEqLs(vals)
                            
                            .AssertEqTo(F3x == -8.6984631039295444);
                    }


                    // F3y
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(F3, th3, F3x, F1x, F2x, Fx, F, Fy, F1y, F2y, a)
                            .IsolateVariable(F3y)

                            .AssertEqTo(F3y == -1 * F1 * sin(th1) + -1 * F2 * sin(th2))
                            
                            .SubstituteEqLs(vals)

                            // .DispLong()

                            .Substitute(3, 3.0)

                            .AssertEqTo(F3y == -5.2181025136471657);
                    }   
                }
            }

            #endregion
            
            #region PSE 5E E5.4

            {
                // A traffic light weighing 125 N hangs from a cable tied to two
                // other cables fastened to a support. The upper cables make
                // angles of 37.0° and 53.0° with the horizontal. Find the tension
                // in the three cables.
                
                var F = new Symbol("F");    // total force magnitude
                var th = new Symbol("th");  // total force direction

                var Fx = new Symbol("Fx");  // total force x-component
                var Fy = new Symbol("Fy");  // total force y-component


                var F1 = new Symbol("F1");
                var th1 = new Symbol("th1");

                var F1x = new Symbol("F1x");
                var F1y = new Symbol("F1y");


                var F2 = new Symbol("F2");
                var th2 = new Symbol("th2");

                var F2x = new Symbol("F2x");
                var F2y = new Symbol("F2y");


                var F3 = new Symbol("F3");
                var th3 = new Symbol("th3");

                var F3x = new Symbol("F3x");
                var F3y = new Symbol("F3y");


                var a = new Symbol("a");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var m = new Symbol("m");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    Fx == F * cos(th),
                    Fy == F * sin(th),

                    Fx == ax * m,
                    Fy == ay * m,

                    Fx == F1x + F2x + F3x,
                    Fy == F1y + F2y + F3y,

                    F1x == F1 * cos(th1), F1y == F1 * sin(th1),
                    F2x == F2 * cos(th2), F2y == F2 * sin(th2),
                    F3x == F3 * cos(th3), F3y == F3 * sin(th3),

                    a == sqrt((ax ^ 2) + (ay ^ 2))

                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {

                        // m 

                        /* F1 */    th1 == (180 - 37).ToRadians(),  // F1x F1y
                        /* F2 */    th2 == (53).ToRadians(),        // F2x F2y
                        F3 == 125,  th3 == (270).ToRadians(),       // F3x F3y
                        
                        ax == 0,    ay == 0,

                        Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // F1
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(Fx, Fy, F, F1x, F1y, F2x, F2y, F2, F3x, F3y, a)
                            .IsolateVariable(F1)
                            
                            .AssertEqTo(F1 == (F3 * sin(th3) - cos(th3) * F3 * sin(th2) / cos(th2)) / (cos(th1) * sin(th2) / cos(th2) - sin(th1)))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(F1 == 75.226877894006023);
                    }

                    // F2
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(Fx, Fy, F, F1x, F1y, F2x, F2y, F1, F3x, F3y, a)
                            .IsolateVariable(F2)

                            .AssertEqTo(F2 == (cos(th3) * F3 * sin(th1) / cos(th1) - F3 * sin(th3)) / (sin(th2) - cos(th2) * sin(th1) / cos(th1)))
                            
                            .SubstituteEqLs(vals)

                            .AssertEqTo(F2 == 99.829438755911582);
                    }

                }
            }

            #endregion
            
            #region PSE 5E E5.6

            {
                // A crate of mass m is placed on a frictionless inclined plane of
                // angle θ. (a) Determine the acceleration of the crate after it is
                // released.

                // (b) Suppose the crate is released from rest at the top of
                // the incline, and the distance from the front edge of the crate
                // to the bottom is d. How long does it take the front edge to
                // reach the bottom, and what is its speed just as it gets there?
                
                var F = new Symbol("F");    // total force magnitude
                var th = new Symbol("th");  // total force direction

                var Fx = new Symbol("Fx");  // total force x-component
                var Fy = new Symbol("Fy");  // total force y-component


                var F1 = new Symbol("F1");
                var th1 = new Symbol("th1");

                var F1x = new Symbol("F1x");
                var F1y = new Symbol("F1y");


                var F2 = new Symbol("F2");
                var th2 = new Symbol("th2");

                var F2x = new Symbol("F2x");
                var F2y = new Symbol("F2y");


                //var F3 = new Symbol("F3");
                //var th3 = new Symbol("th3");

                //var F3x = new Symbol("F3x");
                //var F3y = new Symbol("F3y");


                var a = new Symbol("a");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var m = new Symbol("m");

                var n = new Symbol("n");
                var g = new Symbol("g");

                var incline = new Symbol("incline");

                var Pi = new Symbol("Pi");
                
                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");


                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");


                var tAB = new Symbol("tAB");
                
                var d = new Symbol("d");
                
                var eqs = and(

                    Fx == F * cos(th),
                    Fy == F * sin(th),

                    Fx == ax * m,
                    Fy == ay * m,

                    Fx == F1x + F2x, //+ F3x,
                    Fy == F1y + F2y, //+ F3y,

                    F1x == F1 * cos(th1), F1y == F1 * sin(th1),
                    F2x == F2 * cos(th2), F2y == F2 * sin(th2),
                    //F3x == F3 * cos(th3), F3y == F3 * sin(th3),

                    a == sqrt((ax ^ 2) + (ay ^ 2)),

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,

                    vxB == vxA + ax * tAB,

                    d != 0

                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {

                        // m 
                        
                        F1 == n,        th1 == 90 * Pi / 180,            // F1x F1y
                        F2 == m * g,    th2 == 270 * Pi / 180 + incline, // F2x F2y
                        //F3 == 125,    th3 == (270).ToRadians(),        // F3x F3y
                        
                        /* ax */  ay == 0,

                        // Pi == Math.PI

                        xA == 0, xB == d, vxA == 0
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // ax
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(a, F)
                            .DeepSelect(SinCosToTanFunc)
                            .EliminateVariables(th, Fx, F1x, F2x, Fy, F1y, F2y, vxB, xB)
                            .SubstituteEqLs(vals)
                            .EliminateVariable(n)
                            .IsolateVariable(ax)

                            .AssertEqTo(
                                and(
                                    ax == g * sin(incline),
                                    d != 0));
                    }

                    // tAB
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(a, F)
                            .DeepSelect(SinCosToTanFunc)
                            .EliminateVariables(th, Fx, F1x, F2x, Fy, F1y, F2y, ax, vxB)
                            .SubstituteEqLs(vals)
                            .EliminateVariable(n)
                            .IsolateVariable(tAB).LogicalExpand().CheckVariable(d)
                            
                            .AssertEqTo(
                                or(
                                    and(
                                        tAB == - sqrt(2 * d * g * sin(incline)) / sin(incline) / g,
                                        - g * sin(incline) / 2 != 0,
                                        d != 0),
                                    and(
                                        tAB == sqrt(2 * d * g * sin(incline)) / sin(incline) / g,
                                        -g * sin(incline) / 2 != 0,
                                        d != 0))
                            );
                    }

                    // vxB
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(a, F)
                            .DeepSelect(SinCosToTanFunc)
                            .EliminateVariables(th, Fx, F1x, F2x, Fy, F1y, F2y, ax, tAB)
                            .SubstituteEqLs(vals)
                            .CheckVariable(d)
                            .EliminateVariable(n)

                            .AssertEqTo(
                                or(
                                    and(
                                        -g * sin(incline) / 2 != 0,
                                        vxB == -sqrt(2 * d * g * sin(incline)),
                                        d != 0
                                    ),
                                    and(
                                        -g * sin(incline) / 2 != 0,
                                        vxB == sqrt(2 * d * g * sin(incline)),
                                        d != 0))
                            );
                    }
                }
            }

            #endregion
            
            #region PSE 5E E5.9

            {
                // When two objects of unequal mass are hung vertically over a
                // frictionless pulley of negligible mass, as shown in Figure
                // 5.15a, the arrangement is called an Atwood machine. The device 
                // is sometimes used in the laboratory to measure the freefall
                // acceleration.
                //
                // Determine the magnitude of the acceleration of the two 
                // objects and the tension in the lightweight cord.
                
                var F_m1 = new Symbol("F_m1");      // total force on mass 1
                var F_m2 = new Symbol("F_m2");      // total force on mass 2

                var F1_m1 = new Symbol("F1_m1");    // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");    // force 2 on mass 1

                var F1_m2 = new Symbol("F1_m2");    // force 1 on mass 2
                var F2_m2 = new Symbol("F2_m2");    // force 2 on mass 2

                var m1 = new Symbol("m1");
                var m2 = new Symbol("m2");

                var a = new Symbol("a");

                var T = new Symbol("T");

                var g = new Symbol("g");


                var eqs = and(

                    F_m1 == F1_m1 - F2_m1,
                    F_m2 == F2_m2 - F1_m2,

                    F_m1 == m1 * a,
                    F_m2 == m2 * a,

                    F1_m1 == T,
                    F2_m1 == m1 * g,

                    F1_m2 == T,
                    F2_m2 == m2 * g
                    
                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        m1 == 2.0, m2 == 4.0, g == 9.8
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // a
                    {
                        eqs
                            .EliminateVariables(F_m1, F_m2, F2_m1, F2_m2, F1_m1, F1_m2, T)
                            .IsolateVariable(a)
                            
                            .AssertEqTo(
                                a == (-1 * g * m1 + g * m2) / (m1 + m2)
                            )

                            .SubstituteEqLs(vals)
                            
                            .AssertEqTo(a == 3.2666666666666666);
                    }

                    // T
                    {
                        eqs
                            .EliminateVariables(F_m1, F_m2, F2_m1, F2_m2, F1_m1, F1_m2, a)
                            .IsolateVariable(T)
                            
                            .AssertEqTo(
                                T == 2 * g * m2 / (1 + m2 / m1)
                            )

                            .SubstituteEqLs(vals)
                            
                            .AssertEqTo(
                                T == 26.133333333333333
                            );
                    }
                    
                }
            }

            #endregion
            
            #region PSE 5E E5.10 - Acceleration of Two Objects Connected by a Cord

            {
                // A ball of mass m1 and a block of mass m2 are attached by a
                // lightweight cord that passes over a frictionless pulley of 
                // negligible mass, as shown in Figure 5.16a. The block lies 
                // on a frictionless incline of angle th. Find the magnitude 
                // of the acceleration of the two objects and the tension in the cord.

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                var F3_m1 = new Symbol("F3_m1");        // force 3 on mass 1

                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                var th3_m1 = new Symbol("th3_m1");      // direction of force 3 on mass 1

                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                var F3x_m1 = new Symbol("F3x_m1");      // x-component of force 3 on mass 1

                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                var F3y_m1 = new Symbol("F3y_m1");      // y-component of force 3 on mass 1

                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m2 = new Symbol("F1_m2");        // force 1 on mass 2
                var F2_m2 = new Symbol("F2_m2");        // force 2 on mass 2
                var F3_m2 = new Symbol("F3_m2");        // force 3 on mass 2

                var th1_m2 = new Symbol("th1_m2");      // direction of force 1 on mass 2
                var th2_m2 = new Symbol("th2_m2");      // direction of force 2 on mass 2
                var th3_m2 = new Symbol("th3_m2");      // direction of force 3 on mass 2

                var F1x_m2 = new Symbol("F1x_m2");      // x-component of force 1 on mass 2
                var F2x_m2 = new Symbol("F2x_m2");      // x-component of force 2 on mass 2
                var F3x_m2 = new Symbol("F3x_m2");      // x-component of force 3 on mass 2

                var F1y_m2 = new Symbol("F1y_m2");      // y-component of force 1 on mass 2
                var F2y_m2 = new Symbol("F2y_m2");      // y-component of force 2 on mass 2
                var F3y_m2 = new Symbol("F3y_m2");      // y-component of force 3 on mass 2

                var Fx_m2 = new Symbol("Fx_m2");        // x-component of total force on mass 2
                var Fy_m2 = new Symbol("Fy_m2");        // y-component of total force on mass 2

                var ax_m2 = new Symbol("ax_m2");        // x-component of acceleration of mass 2
                var ay_m2 = new Symbol("ay_m2");        // y-component of acceleration of mass 2

                var m2 = new Symbol("m2");

                ////////////////////////////////////////////////////////////////////////////////

                var incline = new Symbol("incline");

                var T = new Symbol("T");                // tension in cable

                var g = new Symbol("g");                // gravity

                var n = new Symbol("n");                // normal force on block

                var a = new Symbol("a");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    ax_m2 == ay_m1,                     // the block moves right as the ball moves up

                    ////////////////////////////////////////////////////////////////////////////////

                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    F3x_m1 == F3_m1 * cos(th3_m1),

                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    F3y_m1 == F3_m1 * sin(th3_m1),

                    Fx_m1 == F1x_m1 + F2x_m1 + F3x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1 + F3y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1,

                    ////////////////////////////////////////////////////////////////////////////////

                    F1x_m2 == F1_m2 * cos(th1_m2),
                    F2x_m2 == F2_m2 * cos(th2_m2),
                    F3x_m2 == F3_m2 * cos(th3_m2),

                    F1y_m2 == F1_m2 * sin(th1_m2),
                    F2y_m2 == F2_m2 * sin(th2_m2),
                    F3y_m2 == F3_m2 * sin(th3_m2),

                    Fx_m2 == F1x_m2 + F2x_m2 + F3x_m2,
                    Fy_m2 == F1y_m2 + F2y_m2 + F3y_m2,

                    Fx_m2 == m2 * ax_m2,
                    Fy_m2 == m2 * ay_m2,

                    ////////////////////////////////////////////////////////////////////////////////
                    
                    a == ax_m2
                    
                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        ax_m1 == 0,                         // ball  moves vertically
                        ay_m2 == 0,                         // block moves horizontally

                        F1_m1 == T,
                        F2_m1 == m1 * g,
                        F3_m1 == 0,

                        th1_m1 == 90 * Pi / 180,            // force 1 is straight up
                        th2_m1 == 270 * Pi / 180,           // force 2 is straight down

                        F1_m2 == n,
                        F2_m2 == T,
                        F3_m2 == m2 * g,

                        th1_m2 == 90 * Pi / 180,            // force 1 is straight up
                        th2_m2 == 180 * Pi / 180,           // force 2 is straight down
                        th3_m2 == 270 * Pi / 180 + incline  // force 3 direction

                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();
                    
                    // a
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                                F1x_m1, F2x_m1, F3x_m1,
                                F1y_m1, F2y_m1, F3y_m1,
                                
                                Fx_m1, Fy_m1,

                                F1x_m2, F2x_m2, F3x_m2,
                                F1y_m2, F2y_m2, F3y_m2,

                                Fx_m2, Fy_m2,                                
                                
                                ax_m2, n, T, ay_m1
                            )
                            
                            .AssertEqTo(
                            
                                a == (g * m1 - g * m2 * sin(incline)) / (-m1 - m2)

                            )

                            .SubstituteEq(m1 == 10.0)
                            .SubstituteEq(m2 == 5.0)
                            .SubstituteEq(incline == 45 * Math.PI / 180)
                            .SubstituteEq(g == 9.8)

                            .AssertEqTo(a == -4.2234511814572784);
                    }
                    
                    // T
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                                F1x_m1, F2x_m1, F3x_m1,
                                F1y_m1, F2y_m1, F3y_m1,

                                Fx_m1, Fy_m1,

                                F1x_m2, F2x_m2, F3x_m2,
                                F1y_m2, F2y_m2, F3y_m2,

                                Fx_m2, Fy_m2,

                                ax_m2, n, a, ay_m1
                            )
                            
                            .IsolateVariable(T)
                            .RationalizeExpression()
                            
                            .AssertEqTo(

                                T == m1 * (-g * m2 - g * m2 * sin(incline)) / (-m1 - m2)

                            );
                    }
                }
            }

            #endregion

            #region PSE 5E E5.10 - Acceleration of Two Objects Connected by a Cord - Obj3

            {
                // A ball of mass m1 and a block of mass m2 are attached by a
                // lightweight cord that passes over a frictionless pulley of 
                // negligible mass, as shown in: 
                //
                //      http://i.imgur.com/XMHM6On.png
                //
                // The block lies on a frictionless incline of angle th.
                //
                // Find the magnitude of the acceleration of the two objects
                // and the tension in the cord.

                var bal = new Obj2("bal");
                var blk = new Obj3("blk");

                var th = new Symbol("th");

                var T = new Symbol("T");                // tension in cable
                var g = new Symbol("g");                // gravity
                var n = new Symbol("n");                // normal force on block
                var a = new Symbol("a");

                var m1 = new Symbol("m1");
                var m2 = new Symbol("m2");

                var Pi = new Symbol("Pi");

                var eqs = and(

                    blk.ax == bal.ay,                   // the block moves right as the ball moves up

                    a == blk.ax,

                    bal.Equations(),
                    blk.Equations()

                    );

                DoubleFloat.tolerance = 0.00001;

                var vals = new List<Equation>
                {
                    bal.ax == 0,

                    bal.m == m1,

                    bal.F1 == T,            bal.th1 == (90).ToRadians(),                // force 1 is straight up
                    bal.F2 == m1 * g,       bal.th2 == (270).ToRadians(),               // force 2 is straight down

                    blk.ay == 0,

                    blk.m == m2,

                    blk.F1 == n,            blk.th1 == (90).ToRadians(),                // force 1 is straight up
                    blk.F2 == T,            blk.th2 == (180).ToRadians(),               // force 2 is straight down
                    blk.F3 == m2 * g,       blk.th3 == (270).ToRadians() + th           // force 3 direction
                };

                // a
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        bal.ΣFx, bal.F1x, bal.F2x,
                        bal.ΣFy, bal.F1y, bal.F2y,

                        blk.ΣFx, blk.F1x, blk.F2x, blk.F3x,
                        blk.ΣFy, blk.F1y, blk.F2y, blk.F3y,

                        blk.ax, bal.ay,

                        T, n
                    )

                    .IsolateVariable(a)

                    .AssertEqTo(

                        a == (g * m1 - g * m2 * sin(th)) / (-m1 - m2)

                    );

                // T
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        bal.ΣFx, bal.F1x, bal.F2x,
                        bal.ΣFy, bal.F1y, bal.F2y,

                        blk.ΣFx, blk.F1x, blk.F2x, blk.F3x,
                        blk.ΣFy, blk.F1y, blk.F2y, blk.F3y,

                        blk.ax, bal.ay,

                        a, n
                    )

                .IsolateVariable(T)

                .RationalizeExpression()

                .AssertEqTo(

                    T == m1 * (-g * m2 - g * m2 * sin(th)) / (-m1 - m2)

                );
            }

            #endregion

            #region PSE 5E E5.12 - Experimental Determination of μs and μk

            {
                // The following is a simple method of measuring coefficients of
                // friction: Suppose a block is placed on a rough surface
                // inclined relative to the horizontal, as shown in Figure 5.19. 
                // The incline angle is increased until the block starts to move. 
                // Let us show that by measuring the critical angle θ_c at which this
                // slipping just occurs, we can obtain μs.

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                var F3_m1 = new Symbol("F3_m1");        // force 3 on mass 1

                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                var th3_m1 = new Symbol("th3_m1");      // direction of force 3 on mass 1

                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                var F3x_m1 = new Symbol("F3x_m1");      // x-component of force 3 on mass 1

                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                var F3y_m1 = new Symbol("F3y_m1");      // y-component of force 3 on mass 1

                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////
                
                var incline = new Symbol("incline");
                
                var f_s = new Symbol("f_s");            // force due to static friction
                
                var g = new Symbol("g");                // gravity

                var n = new Symbol("n");                // normal force on block

                var a = new Symbol("a");

                var Pi = new Symbol("Pi");

                var mu_s = new Symbol("mu_s");          // coefficient of static friction

                var eqs = and(
                    
                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    F3x_m1 == F3_m1 * cos(th3_m1),

                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    F3y_m1 == F3_m1 * sin(th3_m1),

                    Fx_m1 == F1x_m1 + F2x_m1 + F3x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1 + F3y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1,

                    f_s == mu_s * n
                    
                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        ax_m1 == 0,                         
                        ay_m1 == 0,                         
                        
                        F1_m1 == n,                     
                        F2_m1 == f_s,
                        F3_m1 == m1 * g,

                        th1_m1 == 90 * Pi / 180,            // force 1 is straight up
                        th2_m1 == 180 * Pi / 180,           // force 2 is straight down
                        th3_m1 == 270 * Pi / 180 + incline  // force 3 direction 
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // mu_s
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                                F1x_m1, F2x_m1, F3x_m1,
                                F1y_m1, F2y_m1, F3y_m1,
                                Fx_m1, Fy_m1,
                                f_s, n
                            )
                            .IsolateVariable(mu_s)

                            .DeepSelect(SinCosToTanFunc)

                            .AssertEqTo(mu_s == tan(incline));
                    }
                }
            }

            #endregion
            
            #region PSE 5E E5.13 - The Sliding Hockey Puck

            {
                // A hockey puck on a frozen pond is given an initial speed of
                // 20.0  m/s. If the puck always remains on the ice and slides
                // 115 m before coming to rest, determine the coefficient of
                // kinetic friction between the puck and ice.
                
                ////////////////////////////////////////////////////////////////////////////////

                var s = new Symbol("s");                // displacement
                var u = new Symbol("u");                // initial velocity
                var v = new Symbol("v");                // final velocity
                var a = new Symbol("a");                // acceleration
                var t = new Symbol("t");                // time elapsed
                
                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                var F3_m1 = new Symbol("F3_m1");        // force 3 on mass 1

                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                var th3_m1 = new Symbol("th3_m1");      // direction of force 3 on mass 1

                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                var F3x_m1 = new Symbol("F3x_m1");      // x-component of force 3 on mass 1

                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                var F3y_m1 = new Symbol("F3y_m1");      // y-component of force 3 on mass 1

                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////

                // var incline = new Symbol("incline");
                
                var f_s = new Symbol("f_s");            // force due to static friction

                var f_k = new Symbol("f_k");            // force due to kinetic friction

                var g = new Symbol("g");                // gravity

                var n = new Symbol("n");                // normal force on block

                // var a = new Symbol("a");

                var Pi = new Symbol("Pi");

                var mu_s = new Symbol("mu_s");          // coefficient of static friction

                var mu_k = new Symbol("mu_k");          // coefficient of kinetic friction
                
                var eqs = and(

                    a == ax_m1,

                    v == u + a * t,
                    s == (u + v) * t / 2,
                    
                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    F3x_m1 == F3_m1 * cos(th3_m1),

                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    F3y_m1 == F3_m1 * sin(th3_m1),

                    Fx_m1 == F1x_m1 + F2x_m1 + F3x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1 + F3y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1,

                    f_s == mu_s * n,
                    f_k == mu_k * n
                    
                    );
                
                DoubleFloat.tolerance = 0.00001;

                {
                    var symbolic_vals = new List<Equation>()
                    {
                        F1_m1 == n,
                        F2_m1 == f_k,
                        F3_m1 == m1 * g,

                        th1_m1 == 90 * Pi / 180,            // force 1 is straight up
                        th2_m1 == 180 * Pi / 180,           // force 2 is left
                        th3_m1 == 270 * Pi / 180            // force 3 is straight down
                    };

                    var vals = new List<Equation>()
                    {
                        //ax_m1 == 0,
                        ay_m1 == 0,

                        s == 115,
                        u == 20,
                        v == 0,

                        g == 9.8
                    };
                    
                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // mu_k
                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .SubstituteEqLs(symbolic_vals)

                            .EliminateVariables(
                                t,
                                F1x_m1, F2x_m1, F3x_m1,
                                F1y_m1, F2y_m1, F3y_m1,

                                Fx_m1, Fy_m1,

                                f_s, f_k,

                                n,

                                ax_m1, a

                                )

                            .IsolateVariable(mu_k)
                            
                            .AssertEqTo(    mu_k == (u ^ 2) / s / g / 2    )

                            .SubstituteEqLs(vals)
                            
                            .AssertEqTo(    mu_k == 0.17746228926353147    );
                    }
                }
            }

            #endregion
            
            #region PSE 5E E5.14 - Acceleration of Two Connected Objects When Friction Is Present

            {
                // A block of mass m1 on a rough, horizontal surface is connected
                // to a ball of mass m2 by a lightweight cord over a lightweight,
                // frictionless pulley, as shown:
                //
                // http://i.imgur.com/0fHOmGJ.png
                //
                // A force of magnitude F at an angle th with the horizontal is
                // applied to the block as shown. The coefficient of kinetic
                // friction between the block and surface is mu_k.
                // 
                // Determine the magnitude of the acceleration of the two objects.
                
                ////////////////////////////////////////////////////////////////////////////////

                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                var F3_m1 = new Symbol("F3_m1");        // force 3 on mass 1
                var F4_m1 = new Symbol("F4_m1");        // force 4 on mass 1
                var F5_m1 = new Symbol("F5_m1");        // force 5 on mass 1

                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                var th3_m1 = new Symbol("th3_m1");      // direction of force 3 on mass 1
                var th4_m1 = new Symbol("th4_m1");      // direction of force 4 on mass 1
                var th5_m1 = new Symbol("th5_m1");      // direction of force 5 on mass 1

                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                var F3x_m1 = new Symbol("F3x_m1");      // x-component of force 3 on mass 1
                var F4x_m1 = new Symbol("F4x_m1");      // x-component of force 4 on mass 1
                var F5x_m1 = new Symbol("F5x_m1");      // x-component of force 5 on mass 1

                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                var F3y_m1 = new Symbol("F3y_m1");      // y-component of force 3 on mass 1
                var F4y_m1 = new Symbol("F4y_m1");      // y-component of force 4 on mass 1
                var F5y_m1 = new Symbol("F5y_m1");      // y-component of force 5 on mass 1

                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m2 = new Symbol("F1_m2");        // force 1 on mass 2
                var F2_m2 = new Symbol("F2_m2");        // force 2 on mass 2
                
                var th1_m2 = new Symbol("th1_m2");      // direction of force 1 on mass 2
                var th2_m2 = new Symbol("th2_m2");      // direction of force 2 on mass 2
                
                var F1x_m2 = new Symbol("F1x_m2");      // x-component of force 1 on mass 2
                var F2x_m2 = new Symbol("F2x_m2");      // x-component of force 2 on mass 2
                
                var F1y_m2 = new Symbol("F1y_m2");      // y-component of force 1 on mass 2
                var F2y_m2 = new Symbol("F2y_m2");      // y-component of force 2 on mass 2
                
                var Fx_m2 = new Symbol("Fx_m2");        // x-component of total force on mass 2
                var Fy_m2 = new Symbol("Fy_m2");        // y-component of total force on mass 2

                var ax_m2 = new Symbol("ax_m2");        // x-component of acceleration of mass 2
                var ay_m2 = new Symbol("ay_m2");        // y-component of acceleration of mass 2

                var m2 = new Symbol("m2");

                ////////////////////////////////////////////////////////////////////////////////
                
                var F = new Symbol("F");                // force applied at angle on block
                var th = new Symbol("th");              // angle of force applied on block
                var T = new Symbol("T");                // tension in cable
                var g = new Symbol("g");                // gravity
                var n = new Symbol("n");                // normal force on block

                var a = new Symbol("a");

                var Pi = new Symbol("Pi");
                                
                var f_k = new Symbol("f_k");            // force due to kinetic friction
                
                var mu_k = new Symbol("mu_k");          // coefficient of kinetic friction

                var eqs = and(
                    
                    ax_m1 == ay_m2,                     // the block moves right as the ball moves up

                    ////////////////////////////////////////////////////////////////////////////////

                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    F3x_m1 == F3_m1 * cos(th3_m1),
                    F4x_m1 == F4_m1 * cos(th4_m1),
                    F5x_m1 == F5_m1 * cos(th5_m1),

                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    F3y_m1 == F3_m1 * sin(th3_m1),
                    F4y_m1 == F4_m1 * sin(th4_m1),
                    F5y_m1 == F5_m1 * sin(th5_m1),

                    Fx_m1 == F1x_m1 + F2x_m1 + F3x_m1 + F4x_m1 + F5x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1 + F3y_m1 + F4y_m1 + F5y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1,

                    ////////////////////////////////////////////////////////////////////////////////

                    F1x_m2 == F1_m2 * cos(th1_m2),
                    F2x_m2 == F2_m2 * cos(th2_m2),

                    F1y_m2 == F1_m2 * sin(th1_m2),
                    F2y_m2 == F2_m2 * sin(th2_m2),

                    Fx_m2 == F1x_m2 + F2x_m2,
                    Fy_m2 == F1y_m2 + F2y_m2,

                    Fx_m2 == m2 * ax_m2,
                    Fy_m2 == m2 * ay_m2,

                    ////////////////////////////////////////////////////////////////////////////////

                    f_k == mu_k * n,

                    a == ax_m1

                    );
                
                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        ay_m1 == 0,                                     // block moves horizontally
                        ax_m2 == 0,                                     // ball moves vertically
                        
                        F1_m1 == F,         th1_m1 == th,               // force applied at angle
                        F2_m1 == n,         th2_m1 == 90 * Pi / 180,    // normal force is straight up
                        F3_m1 == T,         th3_m1 == 180 * Pi / 180,   // force due to cord is left
                        F4_m1 == f_k,       th4_m1 == 180 * Pi / 180,   // force due to friction is left
                        F5_m1 == m1 * g,    th5_m1 == 270 * Pi / 180,   // force due to gravity is down
                        
                        F1_m2 == T,         th1_m2 == 90 * Pi / 180,    // force due to cord is up
                        F2_m2 == m2 * g,    th2_m2 == 270 * Pi / 180    // force due to gravity is down                                
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // a
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                                ax_m1,

                                Fx_m1, Fy_m1,
                                Fx_m2, Fy_m2,

                                F1x_m1, F2x_m1, F3x_m1, F4x_m1, F5x_m1,
                                F1y_m1, F2y_m1, F3y_m1, F4y_m1, F5y_m1,

                                F1x_m2, F2x_m2,
                                F1y_m2, F2y_m2,

                                T, f_k, n,

                                ay_m2
                            )
                            
                            .AssertEqTo(

                                a == (g * m2 + g * m1 * mu_k - F * mu_k * sin(th) - cos(th) * F) / (-m1 - m2)

                            );
                    }
                }
            }

            #endregion
                                    
            #region PSE 5E E5.14 - Acceleration of Two Connected Objects When Friction Is Present - Obj5

            {
                // A block of mass m1 on a rough, horizontal surface is connected
                // to a ball of mass m2 by a lightweight cord over a lightweight,
                // frictionless pulley, as shown:
                //
                // http://i.imgur.com/0fHOmGJ.png
                //
                // A force of magnitude F at an angle th with the horizontal is
                // applied to the block as shown. The coefficient of kinetic
                // friction between the block and surface is mu_k.
                // 
                // Determine the magnitude of the acceleration of the two objects.

                var blk = new Obj5("blk");
                var bal = new Obj3("bal");
                
                var F = new Symbol("F");                // force applied at angle on block
                var th = new Symbol("th");              // angle of force applied on block
                var T = new Symbol("T");                // tension in cable
                var g = new Symbol("g");                // gravity
                var n = new Symbol("n");                // normal force on block

                var a = new Symbol("a");

                var Pi = new Symbol("Pi");

                var f_k = new Symbol("f_k");            // force due to kinetic friction

                var mu_k = new Symbol("mu_k");          // coefficient of kinetic friction

                var m1 = new Symbol("m1");
                var m2 = new Symbol("m2");

                var eqs = and(

                    blk.ax == bal.ay,                   // the block moves right as the ball moves up

                    blk.Equations(),
                    bal.Equations(),

                    f_k == mu_k * n,

                    a == blk.ax

                    );
                
                var vals = new List<Equation>()
                {
                    blk.ay == 0,                                        // block moves horizontally
                        
                    blk.F1 == F,            blk.th1 == th,              // block moves horizontally
                    blk.F2 == n,            blk.th2 == 90 * Pi / 180,   // normal force is straight up
                    blk.F3 == T,            blk.th3 == 180 * Pi / 180,  // force due to cord is left
                    blk.F4 == f_k,          blk.th4 == 180 * Pi / 180,  // force due to friction is left
                    blk.F5 == blk.m * g,    blk.th5 == 270 * Pi / 180,  // force due to gravity is down

                    bal.ax == 0,                                        // ball moves vertically

                    bal.F1 == T,            bal.th1 == 90 * Pi / 180,   // force due to cord is up
                    bal.F2 == bal.m * g,    bal.th2 == 270 * Pi / 180,  // force due to gravity is down
                    bal.F3 == 0,

                    blk.m == m1,
                    bal.m == m2
                };

                // a
                
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        blk.ax,

                        blk.ΣFx, blk.ΣFy,
                        bal.ΣFx, bal.ΣFy,

                        blk.F1x, blk.F2x, blk.F3x, blk.F4x, blk.F5x,
                        blk.F1y, blk.F2y, blk.F3y, blk.F4y, blk.F5y,

                        bal.F1x, bal.F2x, bal.F3x,
                        bal.F1y, bal.F2y, bal.F3y,

                        T, f_k, n,

                        bal.ay
                    )

                    .AssertEqTo(

                        a == (g * m2 + g * m1 * mu_k - F * mu_k * sin(th) - cos(th) * F) / (-m1 - m2)

                    );
                
            }

            #endregion
            
            #region PSE 5E P5.25

            {
                // A bag of cement of weight F_g hangs from three wires as
                // shown in http://i.imgur.com/f5JpLjY.png
                //  
                // Two of the wires make angles th1 and th2 with the horizontal.
                // If the system is in equilibrium, show that the tension in the
                // left -hand wire is:
                //
                //          T1 == F_g cos(th2) / sin(th1 + th2)
                
                ////////////////////////////////////////////////////////////////////////////////

                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                var F3_m1 = new Symbol("F3_m1");        // force 3 on mass 1

                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                var th3_m1 = new Symbol("th3_m1");      // direction of force 3 on mass 1

                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                var F3x_m1 = new Symbol("F3x_m1");      // x-component of force 3 on mass 1

                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                var F3y_m1 = new Symbol("F3y_m1");      // y-component of force 3 on mass 1

                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////
                
                var g = new Symbol("g");                // gravity
                
                var a = new Symbol("a");

                var Pi = new Symbol("Pi");

                var T1 = new Symbol("T1");
                var T2 = new Symbol("T2");
                var T3 = new Symbol("T3");

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2");
                
                var eqs = and(
                    
                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    F3x_m1 == F3_m1 * cos(th3_m1),

                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    F3y_m1 == F3_m1 * sin(th3_m1),

                    Fx_m1 == F1x_m1 + F2x_m1 + F3x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1 + F3y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1
                    
                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        ax_m1 == 0,
                        ay_m1 == 0,
                        
                        F1_m1 == T2,
                        F2_m1 == T1,
                        F3_m1 == m1 * g,

                        th1_m1 == th2,                              
                        th2_m1 == 180 * Pi / 180 - th1,             
                        th3_m1 == 270 * Pi / 180
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // T1
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                            
                                F1x_m1, F2x_m1, F3x_m1,
                                F1y_m1, F2y_m1, F3y_m1,

                                Fx_m1, Fy_m1,

                                T2
                            )

                            .IsolateVariable(T1)
                            
                            .RationalizeExpression()

                            .DeepSelect(SumDifferenceFormulaAFunc)

                            .AssertEqTo(
                                T1 == cos(th2) * g * m1 / sin(th1 + th2)
                            );
                    }
                }
            }

            #endregion
            
            #region PSE 5E P5.25 Obj

            {
                // A bag of cement of weight F_g hangs from three wires as
                // shown in http://i.imgur.com/f5JpLjY.png
                //  
                // Two of the wires make angles th1 and th2 with the horizontal.
                // If the system is in equilibrium, show that the tension in the
                // left -hand wire is:
                //
                //          T1 == F_g cos(th2) / sin(th1 + th2)
                
                var bag = new Obj3("bag");
                
                var T1 = new Symbol("T1");
                var T2 = new Symbol("T2");
                var T3 = new Symbol("T3");

                var F_g = new Symbol("F_g");

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2");

                var eqs = bag.Equations();

                var vals = new List<Equation>()
                {
                    bag.ax == 0,
                    bag.ay == 0,

                    bag.F1 == T1,       bag.th1 == (180).ToRadians() - th1,
                    bag.F2 == T2,       bag.th2 == th2,
                    bag.F3 == F_g,      bag.th3 == (270).ToRadians()
                };

                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        bag.ΣFx, bag.F1x, bag.F2x, bag.F3x,
                        bag.ΣFy, bag.F1y, bag.F2y, bag.F3y,

                        T2
                    
                    )

                    .IsolateVariable(T1)

                    .RationalizeExpression()

                    .DeepSelect(SumDifferenceFormulaAFunc)

                    .AssertEqTo(    T1 == cos(th2) * F_g / sin(th1 + th2)   );
                
            }

            #endregion
            
            #region PSE 5E P5.31

            {
                // Two people pull as hard as they can on ropes attached
                // to a boat that has a mass of 200 kg. If they pull in the
                // same direction, the boat has an acceleration of
                // 1.52 m/s^2 to the right. If they pull in opposite directions,
                // the boat has an acceleration of 0.518 m/s^2 to the
                // left.
                // 
                // What is the force exerted by each person on the
                // boat? (Disregard any other forces on the boat.)

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m1 = new Symbol("F1_m1");        // force 1 on mass 1
                var F2_m1 = new Symbol("F2_m1");        // force 2 on mass 1
                
                var th1_m1 = new Symbol("th1_m1");      // direction of force 1 on mass 1
                var th2_m1 = new Symbol("th2_m1");      // direction of force 2 on mass 1
                
                var F1x_m1 = new Symbol("F1x_m1");      // x-component of force 1 on mass 1
                var F2x_m1 = new Symbol("F2x_m1");      // x-component of force 2 on mass 1
                
                var F1y_m1 = new Symbol("F1y_m1");      // y-component of force 1 on mass 1
                var F2y_m1 = new Symbol("F2y_m1");      // y-component of force 2 on mass 1
                
                var Fx_m1 = new Symbol("Fx_m1");        // x-component of total force on mass 1
                var Fy_m1 = new Symbol("Fy_m1");        // y-component of total force on mass 1

                var ax_m1 = new Symbol("ax_m1");        // x-component of acceleration of mass 1
                var ay_m1 = new Symbol("ay_m1");        // y-component of acceleration of mass 1

                var m1 = new Symbol("m1");

                ////////////////////////////////////////////////////////////////////////////////

                var F1_m2 = new Symbol("F1_m2");        // force 1 on mass 2
                var F2_m2 = new Symbol("F2_m2");        // force 2 on mass 2

                var th1_m2 = new Symbol("th1_m2");      // direction of force 1 on mass 2
                var th2_m2 = new Symbol("th2_m2");      // direction of force 2 on mass 2

                var F1x_m2 = new Symbol("F1x_m2");      // x-component of force 1 on mass 2
                var F2x_m2 = new Symbol("F2x_m2");      // x-component of force 2 on mass 2

                var F1y_m2 = new Symbol("F1y_m2");      // y-component of force 1 on mass 2
                var F2y_m2 = new Symbol("F2y_m2");      // y-component of force 2 on mass 2

                var Fx_m2 = new Symbol("Fx_m2");        // x-component of total force on mass 2
                var Fy_m2 = new Symbol("Fy_m2");        // y-component of total force on mass 2

                var ax_m2 = new Symbol("ax_m2");        // x-component of acceleration of mass 2
                var ay_m2 = new Symbol("ay_m2");        // y-component of acceleration of mass 2

                var m2 = new Symbol("m2");

                ////////////////////////////////////////////////////////////////////////////////
                
                var Pi = new Symbol("Pi");
                
                var T1 = new Symbol("T1");
                var T2 = new Symbol("T2");

                var eqs = and(

                    m1 == m2,
                                        
                    F1x_m1 == F1_m1 * cos(th1_m1),
                    F2x_m1 == F2_m1 * cos(th2_m1),
                    
                    F1y_m1 == F1_m1 * sin(th1_m1),
                    F2y_m1 == F2_m1 * sin(th2_m1),
                    
                    Fx_m1 == F1x_m1 + F2x_m1,
                    Fy_m1 == F1y_m1 + F2y_m1,

                    Fx_m1 == m1 * ax_m1,
                    Fy_m1 == m1 * ay_m1,


                    F1x_m2 == F1_m2 * cos(th1_m2),
                    F2x_m2 == F2_m2 * cos(th2_m2),

                    F1y_m2 == F1_m2 * sin(th1_m2),
                    F2y_m2 == F2_m2 * sin(th2_m2),

                    Fx_m2 == F1x_m2 + F2x_m2,
                    Fy_m2 == F1y_m2 + F2y_m2,

                    Fx_m2 == m2 * ax_m2,
                    Fy_m2 == m2 * ay_m2
                    );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        ay_m1 == 0,

                        F1_m1 == T1,    th1_m1 == 0,
                        F2_m1 == T2,    th2_m1 == 0,

                        ay_m2 == 0,

                        F1_m2 == T1,    th1_m2 == 180 * Pi / 180,
                        F2_m2 == T2,    th2_m2 == 0
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    var numerical_vals = new List<Equation>()
                    {
                        m1 == 200,

                        ax_m1 == 1.52,
                        ax_m2 == -0.518
                    };
                    
                    // T1
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(
                            
                                m2,

                                F1x_m1, F2x_m1,
                                F1y_m1, F2y_m1,

                                F1x_m2, F2x_m2,
                                F1y_m2, F2y_m2,

                                Fx_m1, Fy_m1,
                                
                                Fx_m2, Fy_m2,

                                T2
                                
                                )

                            .IsolateVariable(T1)

                            .AssertEqTo(
                            
                                T1 == -(ax_m2 * m1 - ax_m1 * m1) / 2
                                
                            )
                            
                            .SubstituteEqLs(numerical_vals)

                            .AssertEqTo(T1 == 203.8);
                    }

                    // T2
                    {
                        eqs
                            .SubstituteEqLs(vals)

                            .EliminateVariables(

                                m2,

                                F1x_m1, F2x_m1,
                                F1y_m1, F2y_m1,

                                F1x_m2, F2x_m2,
                                F1y_m2, F2y_m2,

                                Fx_m1, Fy_m1,

                                Fx_m2, Fy_m2,

                                T1

                                )

                            .IsolateVariable(T2)

                            .AssertEqTo(
                            
                                T2 == (ax_m1 * m1 + ax_m2 * m1) / 2
                                
                            )
                            
                            .SubstituteEqLs(numerical_vals)

                            .AssertEqTo(T2 == 100.19999999999999);
                    }
                }
            }

            #endregion

            #region PSE 5E P5.31 Obj

            {
                // Two people pull as hard as they can on ropes attached
                // to a boat that has a mass of 200 kg. If they pull in the
                // same direction, the boat has an acceleration of
                // 1.52 m/s^2 to the right. If they pull in opposite directions,
                // the boat has an acceleration of 0.518 m/s^2 to the
                // left.
                // 
                // What is the force exerted by each person on the
                // boat? (Disregard any other forces on the boat.)

                ////////////////////////////////////////////////////////////////////////////////

                var b1 = new Obj2("b1");            // boat in scenario 1 (same direction)
                var b2 = new Obj2("b2");            // boat in scenario 2 (opposite directions)

                var m = new Symbol("m");

                ////////////////////////////////////////////////////////////////////////////////

                var Pi = new Symbol("Pi");

                var T1 = new Symbol("T1");
                var T2 = new Symbol("T2");

                var eqs = and(

                    b1.Equations(),
                    b2.Equations()

                    );

                DoubleFloat.tolerance = 0.00001;

                var vals = new List<Equation>()
                {
                    b1.m == m,

                    b1.ay == 0,

                    b1.F1 == T1, b1.th1 == 0,
                    b1.F2 == T2, b1.th2 == 0,

                    b2.m == m,

                    b2.ay == 0,

                    b2.F1 == T1, b2.th1 == (180).ToRadians(),
                    b2.F2 == T2, b2.th2 == 0

                };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                var numerical_vals = new List<Equation>()
                {
                    m == 200,

                    b1.ax == 1.52,
                    b2.ax == -0.518
                };

                // T1
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        b1.ΣFx, b1.F1x, b1.F2x,
                        b1.ΣFy, b1.F1y, b1.F2y,

                        b2.ΣFx, b2.F1x, b2.F2x,
                        b2.ΣFy, b2.F1y, b2.F2y,

                        T2
                    )

                    .IsolateVariable(T1)

                    .AssertEqTo(

                        T1 == -(b2.ax * m - b1.ax * m) / 2

                    )

                    .SubstituteEqLs(numerical_vals)

                    .AssertEqTo(T1 == 203.8);

                // T2
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        b1.ΣFx, b1.F1x, b1.F2x,
                        b1.ΣFy, b1.F1y, b1.F2y,

                        b2.ΣFx, b2.F1x, b2.F2x,
                        b2.ΣFy, b2.F1y, b2.F2y,

                        T1
                    )

                    .IsolateVariable(T2)

                    .AssertEqTo(

                        T2 == (b1.ax * m + b2.ax * m) / 2

                    )

                    .SubstituteEqLs(numerical_vals)

                    .AssertEqTo(T2 == 100.19999999999999);

            }

            #endregion
            
            #region PSE 5E P5.55 

            {
                // An inventive child named Pat wants to reach an apple
                // in a tree without climbing the tree. Sitting in a chair
                // connected to a rope that passes over a frictionless pulley
                // Pat pulls on the loose end of the rope with such a force
                // that the spring scale reads 250 N. Pat’s weight is 320 N,
                // and the chair weighs 160 N.
                //
                // http://i.imgur.com/wwlypzB.png
                //
                // (a) Draw free - body diagrams for Pat and the chair considered as
                // separate systems, and draw another diagram for Pat and
                // the chair considered as one system.
                //
                // (b) Show that the acceleration of the system is upward and
                // find its magnitude.
                //
                // (c) Find the force Pat exerts on the chair.

                var b = new Obj3("b");          // boy
                var c = new Obj3("c");          // chair
                var s = new Obj3("s");          // system

                var T = new Symbol("T");        // rope tension
                var n = new Symbol("n");        // normal force

                var Fg_b = new Symbol("Fg_b");  // force due to gravity of the boy
                var Fg_c = new Symbol("Fg_c");  // force due to gravity of the chair
                var Fg_s = new Symbol("Fg_s");  // force due to gravity of the system

                var a = new Symbol("a");        // acceleration

                var Pi = new Symbol("Pi");
                var g = new Symbol("g");

                var eqs = and(

                    Fg_b == b.m * g,
                    Fg_c == c.m * g,
                    Fg_s == s.m * g,

                    Fg_s == Fg_c + Fg_b,

                    s.Equations(),
                    c.Equations()

                    );

                var vals = new List<Equation>()
                {
                    //b.ax == 0,
                    c.ax == 0,
                    s.ax == 0,

                    //b.F1 == T,          b.th1 == 90 * Pi / 180,
                    //b.F2 == n,          b.th2 == 90 * Pi / 180,
                    //b.F3 == b.m * g,    b.th3 == 270 * Pi / 180,

                    c.F1 == T,          c.th1 == 90 * Pi / 180,
                    c.F2 == n,          c.th2 == 270 * Pi / 180,
                    c.F3 == Fg_c,       c.th3 == 270 * Pi / 180,

                    s.F1 == T,          s.th1 == 90 * Pi / 180,
                    s.F2 == T,          s.th2 == 90 * Pi / 180,
                    s.F3 == Fg_s,       s.th3 == 270 * Pi / 180,

                    //b.ay == a,
                    c.ay == a,
                    s.ay == a
                };

                var numerical_vals = new List<Equation>()
                {
                    T == 250.0,
                    Fg_b == 320,
                    Fg_c == 160,
                    g == 9.8
                };

                DoubleFloat.tolerance = 0.00001;

                // a
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        s.ΣFx, s.F1x, s.F2x, s.F3x,
                        s.ΣFy, s.F1y, s.F2y, s.F3y,

                        c.ΣFx, c.F1x, c.F2x, c.F3x,
                        c.ΣFy, c.F1y, c.F2y, c.F3y,

                        n,

                        s.m,

                        Fg_s,

                        b.m, c.m

                    )

                    .IsolateVariable(a)

                    .AssertEqTo(

                        a == -g * (Fg_b + Fg_c - 2 * T) / (Fg_b + Fg_c)

                    )

                    .SubstituteEqLs(numerical_vals)

                    .AssertEqTo(a == 0.40833333333333333);

                // n
                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        s.ΣFx, s.F1x, s.F2x, s.F3x,
                        s.ΣFy, s.F1y, s.F2y, s.F3y,

                        c.ΣFx, c.F1x, c.F2x, c.F3x,
                        c.ΣFy, c.F1y, c.F2y, c.F3y,

                        c.m, s.m,

                        Fg_s,

                        b.m,

                        a

                    )

                    .IsolateVariable(n)

                    .AssertEqTo(

                        n == -1 * (Fg_c - T - Fg_c * (Fg_b + Fg_c - 2 * T) / (Fg_b + Fg_c))

                    )

                    .SubstituteEqLs(numerical_vals);

                DoubleFloat.tolerance = null;

            }

            #endregion
            
            #region PSE 5E P5.59

            {
                // A mass M is held in place by an applied force F and a
                // pulley system: 
                //
                //                 http://i.imgur.com/TPAHTlW.png
                //
                // The pulleys are massless and frictionless. Find 
                //                     
                // (a) the tension in each section of rope, T1, T2, T3, T4, and T5
                //                     
                // (b) the magnitude of F. 
                //                     
                // (Hint: Draw a free - body diagram for each pulley.)

                var pul1_F = new Symbol("pul1_F");      // magnitude of total force on pully 1
                var pul1_m = new Symbol("pul1_m");      // mass of pully 1
                var pul1_a = new Symbol("pul1_a");      // acceleration of pully 1

                var pul2_F = new Symbol("pul2_F");      // magnitude of total force on pully 2
                var pul2_m = new Symbol("pul2_m");      // mass of pully 2
                var pul2_a = new Symbol("pul2_a");      // acceleration of pully 2
                
                var T1 = new Symbol("T1");
                var T2 = new Symbol("T2");
                var T3 = new Symbol("T3");
                var T4 = new Symbol("T4");
                var T5 = new Symbol("T5");

                var F = new Symbol("F");

                var M = new Symbol("M");

                var g = new Symbol("g");

                var eqs = and(

                     T1 == F,
                     T2 == T3,
                     T1 == T3,
                     T5 == M * g,
                     
                     pul1_a == 0,
                     pul1_m == 0,

                     pul1_F == T4 - T1 - T2 - T3,
                     pul1_F == pul1_m * pul1_a,

                     pul2_m == 0,

                     pul2_F == T2 + T3 - T5,
                     pul2_F == pul2_m * pul2_a

                    );

                DoubleFloat.tolerance = 0.00001;

                // T1
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T2, T3, T4, T5, F)
                        .IsolateVariable(T1)
                        .AssertEqTo(T1 == g * M / 2);
                }
                
                // T2
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T1, T3, T4, T5, F)
                        .IsolateVariable(T2)
                        .AssertEqTo(T2 == g * M / 2);
                }

                // T3
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T1, T2, T4, T5, F)
                        .IsolateVariable(T3)
                        .AssertEqTo(T3 == g * M / 2);
                }

                // T4
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T1, T2, T3, T5, F)
                        .IsolateVariable(T4)
                        .AssertEqTo(T4 == g * M * 3 / 2);
                }

                // T5
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T1, T2, T3, T4, F)
                        .AssertEqTo(T5 == g * M);
                }

                // F
                {
                    eqs
                        .EliminateVariables(pul1_F, pul2_F, pul1_m, pul2_m, pul1_a, T1, T2, T3, T4, T5)
                        .IsolateVariable(F)
                        .AssertEqTo(F == g * M / 2);
                }
            }

            #endregion
            
            #region PSE 5E P5.69
            {
                // What horizontal force must be applied to the cart shown:

                // http://i.imgur.com/fpkzsYI.png

                // so that the blocks remain stationary relative to the cart?
                // Assume all surfaces, wheels, and pulley are frictionless.
                // (Hint:Note that the force exerted by the string accelerates m1.)

                var blk1 = new Obj3("blk1");
                var blk2 = new Obj3("blk2");

                var sys = new Obj3("sys");
                
                var m1 = new Symbol("m1");
                var m2 = new Symbol("m2");
                
                var T = new Symbol("T");
                var F = new Symbol("F");
                var M = new Symbol("M");
                var g = new Symbol("g");
                var a = new Symbol("a");
                
                var eqs = and(

                    blk1.Equations(),
                    blk2.Equations(),

                    sys.Equations()
                    
                    );

                var vals = new List<Equation>()
                {
                    blk1.ax == a,
                    blk1.ay == 0,

                    blk1.m == m1,

                    blk1.F1 == T,   blk1.th1 == 0,

                    blk1.th2 == (90).ToRadians(),
                    blk1.th3 == (270).ToRadians(),


                    blk2.ax == a,
                    blk2.ay == 0,

                    blk2.m == m2,

                    blk2.th1 == 0,

                    blk2.F2 == T,       blk2.th2 == (90).ToRadians(),
                    blk2.F3 == m2 * g,  blk2.th3 == (270).ToRadians(),


                    sys.ax == a,
                    sys.ay == 0,

                    sys.m == M + m1 + m2,

                    sys.F1 == F,        sys.th1 == 0,

                    sys.th2 == (90).ToRadians(),
                    sys.th3 == (270).ToRadians()

                };

                eqs
                    .SubstituteEqLs(vals)

                    .EliminateVariables(

                        blk1.ΣFx, blk1.F1x, blk1.F2x, blk1.F3x,
                        blk1.ΣFy, blk1.F1y, blk1.F2y, blk1.F3y,

                        blk1.F2,

                        blk2.ΣFx, blk2.F1x, blk2.F2x, blk2.F3x,
                        blk2.ΣFy, blk2.F1y, blk2.F2y, blk2.F3y,

                        blk2.F1,

                        sys.ΣFx, sys.F1x, sys.F2x, sys.F3x,
                        sys.ΣFy, sys.F1y, sys.F2y, sys.F3y,

                        sys.F2,

                        T, a

                    )

                    .AssertEqTo(   F == g * m2 / m1 * (M + m1 + m2)   );
            }
            #endregion
                        
            #region PSE 5E E7.7
            {
                // A  6.0-kg block initially at rest is pulled to the right along a
                // horizontal, frictionless surface by a constant horizontal force
                // of 12 N. Find the speed of the block after it has moved 3.0 m.
                
                var W = new Symbol("W");
                var F = new Symbol("F");
                var d = new Symbol("d");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");

                var m = new Symbol("m");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var eqs = and(

                    W == F * d,

                    W == Kf - Ki,

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,

                    m != 0

                    );

                var vals = new List<Equation>() { m == 6.0, vi == 0, F == 12, d == 3 };

                // vf
                eqs
                    .EliminateVariables(Kf, Ki, W)
                    .IsolateVariable(vf)
                    .LogicalExpand().CheckVariable(m).SimplifyEquation().SimplifyLogical()

                    .AssertEqTo(

                        or(
                            and(
                                vf == sqrt(-2 * m * (-d * F - m * (vi ^ 2) / 2)) / m,
                                m != 0),
                            and(
                                vf == -sqrt(-2 * m * (-d * F - m * (vi ^ 2) / 2)) / m,
                                m != 0)))
                                
                    .SubstituteEq(vi == 0)
                                        
                    .AssertEqTo(

                        or(
                            and(
                                vf == sqrt(2 * d * F * m) / m,
                                m != 0),
                            and(
                                vf == -sqrt(2 * d * F * m) / m,
                                m != 0)))
                    
                    .SubstituteEqLs(vals)

                    .AssertEqTo(
                        or(
                            vf == 3.4641016151377544,
                            vf == -3.4641016151377544));

            }
            #endregion
                        
            #region PSE 5E E7.8
            {
                // Find the final speed of the block described in Example 7.7 if
                // the surface is not frictionless but instead has a coefficient of
                // kinetic friction of 0.15.

                var W = new Symbol("W");
                var F = new Symbol("F");
                var d = new Symbol("d");
                var n = new Symbol("n");

                var g = new Symbol("g");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");

                var m = new Symbol("m");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");
                                
                var μk = new Symbol("μk");

                var eqs = and(

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,

                    W == F * d,

                    n == m * g,

                    fk == n * μk,

                    W - fk * d == Kf - Ki,

                    m != 0

                    );

                var vals = new List<Equation>()
                {
                    vi == 0,
                    F == 12.0,
                    d == 3.0,

                    m == 6.0,
                    
                    μk == 0.15,

                    g == 9.8,
                };

                // vf
                eqs
                    .EliminateVariables(Kf, Ki, W, n, fk)
                    .IsolateVariable(vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                    .SubstituteEq(vi == 0)
                    .AssertEqTo(
                        or(
                            and(
                                vf == -sqrt(2 * m * (d * F - d * g * m * μk)) / m,
                                m != 0),
                            and(
                                vf == sqrt(2 * m * (d * F - d * g * m * μk)) / m,
                                m != 0)))

                    .SubstituteEqLs(vals)

                    .AssertEqTo(or(vf == -1.7832554500127007, vf == 1.7832554500127007));

            }
            #endregion
            
            #region PSE 5E E7.11
            {
                // A block of mass 1.6 kg is attached to a horizontal spring that
                // has a force constant of 1.0 x 10^3 N/m, as shown in Figure
                // 7.10. The spring is compressed 2.0 cm and is then released
                // from  rest.
                
                // (a) Calculate the  speed of  the block  as it  passes
                // through the equilibrium position x = 0 if the surface is frictionless.

                // (b) Calculate the speed of the block as it passes through
                // the equilibrium position if a constant frictional force of 4.0 N
                // retards its motion from the moment it is released.

                var ΣW = new Symbol("ΣW");
                                
                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");

                var m = new Symbol("m");
                var d = new Symbol("d");
                var k = new Symbol("k");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");
                
                var W_s = new Symbol("W_s");
                var W_f = new Symbol("W_f");
                
                var x_max = new Symbol("x_max");

                var eqs = and(

                    W_s == k * (x_max ^ 2) / 2,

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,
                    
                    W_f == -fk * d,

                    ΣW == Kf - Ki,

                    ΣW == W_s + W_f,

                    m != 0

                    );

                // vf
                {
                    var vals = new List<Equation>() { m == 1.6, vi == 0, fk == 0, k == 1000, x_max == -0.02 };

                    eqs
                        .EliminateVariables(ΣW, Kf, Ki, W_f, W_s)
                        .IsolateVariable(vf)
                        .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                        
                        .AssertEqTo(
                            or(
                                and(
                                    vf == sqrt(-2 * m * (d * fk - m * (vi ^ 2) / 2 - k * (x_max ^ 2) / 2)) / m,
                                    m != 0),
                                and(
                                    vf == -sqrt(-2 * m * (d * fk - m * (vi ^ 2) / 2 - k * (x_max ^ 2) / 2)) / m,
                                    m != 0)))
                                              
                        .SubstituteEqLs(vals)
                        
                        .AssertEqTo(or(vf == 0.5, vf == -0.5));
                }

                // vf
                {
                    var vals = new List<Equation>() { m == 1.6, vi == 0, fk == 4, k == 1000, x_max == -0.02, d == 0.02 };

                    eqs
                        .EliminateVariables(ΣW, Kf, Ki, W_f, W_s)
                        .IsolateVariable(vf)
                        .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                        
                        .SubstituteEqLs(vals)
                        
                        .AssertEqTo(or(vf == 0.3872983346207417, vf == -0.3872983346207417));
                }
                
            }
            #endregion
                        
            #region PSE 6E P7.3
            {
                // Batman, whose mass is 80.0kg, is dangling on the free end
                // of a 12.0m rope, the other end of which is fixed to a tree
                // limb above. He is able to get the rope in motion as only
                // Batman knows how, eventually getting it to swing enough
                // that he can reach a ledge when the rope makes a 60.0°
                // angle with the vertical. How much work was done by the
                // gravitational force on Batman in this maneuver?

                var m = new Symbol("m");
                var a = new Symbol("a");

                var W = new Symbol("W");
                var F = new Symbol("F");
                var d = new Symbol("d");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");

                var th = new Symbol("th");

                var len = new Symbol("len");
                
                var eqs = and(

                    yA == -len,

                    yB == -len * cos(th),

                    d == yB - yA,

                    F == m * a,

                    W == F * d
                              
                    );

                var vals = new List<Equation>()
                { m == 80, len == 12, th == (60).ToRadians(), a == -9.8 };

                eqs
                    .EliminateVariables(F, d, yA, yB)

                    .AssertEqTo(W == a * (len - cos(th) * len) * m)

                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(W == -4704.0);
            }
            #endregion
                        
            #region PSE 5E P7.23
            {
                // If it takes 4.00J of work to stretch a Hooke’s-law spring
                // 10.0cm from its unstressed length, determine the extra
                // work required to stretch it an additional 10.0cm.

                var WsAB = new Symbol("WsAB");
                
                var WsA = new Symbol("WsA");
                var WsB = new Symbol("WsB");

                var k = new Symbol("k");

                var xA = new Symbol("xA");
                var xB = new Symbol("xB");
                                
                var eqs = and(
                    
                    WsA == k * (xA ^ 2) / 2,
                    WsB == k * (xB ^ 2) / 2,

                    WsAB == WsB - WsA
                                        
                    );

                var vals = new List<Equation>() { xA == 0.1, xB == 0.2, WsA == 4 };

                eqs

                    .EliminateVariables(WsB, k)

                    .AssertEqTo(
                    
                        WsAB == WsA * (xB ^ 2) / (xA ^ 2) - WsA     
                        
                        )
                        
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(WsAB == 12.0);
                
            }
            #endregion
            
            #region PSE 5E 7.33
            {
                // A 40.0-kg box initially at rest is pushed 5.00m along a
                // rough, horizontal floor with a constant applied horizontal
                // force of 130 N. If the coefficient of friction between
                // the box and the floor is 0.300, find

                // (a) the work done by the applied force
                // (b) the energy loss due to friction
                // (c) the work done by the normal force
                // (d) the work done by gravity
                // (e) the change in kinetic energy of the box
                // (f) the final speed of the box

                var ΣW = new Symbol("ΣW");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");

                var F = new Symbol("F");

                var m = new Symbol("m");
                var d = new Symbol("d");

                var n = new Symbol("n");
                var g = new Symbol("g");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");

                var W_F = new Symbol("W_F"); 
                var W_f = new Symbol("W_f");

                var μk = new Symbol("μk");

                var eqs = and(

                    n == m * g,

                    fk == μk * n,

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,
                    
                    W_F == F * d,

                    W_f == -fk * d,

                    ΣW == Kf - Ki,
                                        
                    ΣW == W_F + W_f,

                    m != 0

                    );

                var vals = new List<Equation>()
                { m == 40, vi == 0, d == 5, F == 130, μk == 0.3, g == 9.8 };
                
                // W_F, W_f
                eqs
                    .EliminateVariables(fk, n, Kf, Ki, ΣW, vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                    
                    .AssertEqTo(
                        and(
                            m != 0,
                            W_F == d * F,
                            W_f == -d * g * m * μk))
                            
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(and(W_F == 650, W_f == -588.0));

                // ΣW
                eqs
                    .EliminateVariables(W_F, W_f, fk, n, Ki, Kf)

                    .AssertEqTo(
                        and(
                            ΣW == m * (vf ^ 2) / 2 - m * (vi ^ 2) / 2,
                            ΣW == d * F - d * g * m * μk,
                            m != 0))
                                                
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(and(ΣW == 20 * (vf ^ 2), ΣW == 62.0));
                
                // vf
                eqs
                    .EliminateVariables(Kf, Ki, ΣW, W_F, W_f, fk, n)
                    .IsolateVariable(vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)

                    .AssertEqTo(
                        or(
                            and(
                                vf == sqrt(-2 * m * (-d * F - m * (vi ^ 2) / 2 + d * g * m * μk)) / m,
                                m != 0),
                            and(
                                vf == -sqrt(-2 * m * (-d * F - m * (vi ^ 2) / 2 + d * g * m * μk)) / m,
                                m != 0)))
                                
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(or(vf == 1.7606816861659009, vf == -1.7606816861659009));
            }
            #endregion
            
            #region PSE 5E P7.35
            {
                // A crate of mass 10.0kg is pulled up a rough incline with
                // an initial speed of 1.50 m/s.The pulling force is 100 N
                // parallel to the incline, which makes an angle of 20.0°
                // with the horizontal. The coefficient of kinetic friction is
                // 0.400, and the crate is pulled 5.00 m.

                // (a) How much work is done by gravity?
                // (b) How much energy is lost because of friction?
                // (c) How much work is done by the 100-N force?
                // (d) What is the change in kinetic energy of the crate?
                // (e) What is the speed of the crate after it has been pulled 5.00 m?

                var ΣW = new Symbol("ΣW");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");

                var F = new Symbol("F");

                var m = new Symbol("m");
                var d = new Symbol("d");

                var n = new Symbol("n");
                var g = new Symbol("g");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");

                var W_F = new Symbol("W_F");
                var W_f = new Symbol("W_f");
                var W_g = new Symbol("W_g");

                var μk = new Symbol("μk");
                                
                var th = new Symbol("th");

                var F_g = new Symbol("F_g");

                var Pi = new Symbol("Pi");
                
                var eqs = and(

                    F_g == m * g,

                    n == F_g * cos(th),

                    fk == μk * n,

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,

                    W_F == F * d,

                    W_f == -fk * d,
                                                                                
                    W_g == - F_g * sin(th) * d,

                    ΣW == Kf - Ki,

                    ΣW == W_F + W_f + W_g,

                    m != 0
                    
                    );

                var vals = new List<Equation>()
                {
                    m == 10.0, g == 9.8, d == 5.0, th == (20).ToRadians(), μk == 0.4, F == 100.0,
                    vi == 1.5, Pi == Math.PI
                };

                // W_g, W_f, W_F
                eqs
                    .EliminateVariables(F_g, fk, n)

                    .AssertEqTo(
                        and(
                            Kf == m * (vf ^ 2) / 2,
                            Ki == m * (vi ^ 2) / 2,
                            W_F == d * F,
                            W_f == -cos(th) * d * g * m * μk,
                            W_g == -d * g * m * sin(th),
                            ΣW == Kf - Ki,
                            ΣW == W_f + W_F + W_g,
                            m != 0
                        ))
                    
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(
                        and(
                            Kf == 5.0 * (vf ^ 2),
                            Ki == 11.25,
                            W_F == 500.0,
                            W_f == -184.17975367403804,
                            W_g == -167.58987022957766,
                            ΣW == Kf - Ki,
                            ΣW == W_f + W_F + W_g
                        ));
                
                // ΣW
                eqs
                    .EliminateVariables(F_g, fk, n, W_F, W_f, W_g)
                    
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(
                        and(
                            Kf == 5.0 * (vf ^ 2),
                            Ki == 11.25,
                            ΣW == Kf - Ki,
                            ΣW == 148.23037609638431
                        ));

                // vf
                eqs
                    .EliminateVariables(F_g, fk, n, W_F, W_f, W_g, ΣW, Kf, Ki)

                    .IsolateVariable(vf)

                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                                                                                 
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(or(vf == 5.6476610396939435, vf == -5.6476610396939435));

            }
            #endregion
            
            #region PSE 5E P7.39
            {
                // A bullet with a mass of 5.00 g and a speed of 600 m/s
                // penetrates a tree to a depth of 4.00 cm.

                // (a) Use work and energy considerations to find the average
                // frictional force that stops the bullet.

                // (b) Assuming that the frictional force is constant,
                // determine how much time elapsed between the moment
                // the bullet entered the tree and the moment it stopped.

                var ΣW = new Symbol("ΣW");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");
                
                var m = new Symbol("m");
                var d = new Symbol("d");
                
                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");
                                
                var W_f = new Symbol("W_f");

                var t = new Symbol("t");

                var eqs = and(
                    
                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,

                    W_f == -fk * d,

                    ΣW == Kf - Ki,

                    ΣW == W_f
                    
                    );

                var vals = new List<Equation>() { m == 0.005, vi == 600.0, vf == 0.0, d == 0.04 };

                // fk
                eqs
                    .EliminateVariables(W_f, ΣW, Ki, Kf)
                    .IsolateVariable(fk)
                    .AssertEqTo(
                    
                        fk == (m * (vi ^ 2) / 2 - m * (vf ^ 2) / 2) / d
                        
                        )
                    
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(fk == 22500.0);
                
                // t
                (d == (vi + vf) * t / 2)
                    .IsolateVariable(t)
                    .AssertEqTo(t == 2 * d / (vf + vi))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(t == 1.3333333333333334e-4);
                
            }
            #endregion
            
            #region PSE 5E P7.41
            {
                // A 2.00-kg block is attached to a spring of force constant
                // 500 N/m, as shown in Figure 7.10. The block is pulled
                // 5.00 cm to the right of equilibrium and is then released
                // from rest. Find the speed of the block as it passes
                // through equilibrium if

                // (a) the horizontal surface is frictionless

                // (b) the coefficient of friction between the block and the surface is 0.350.

                var ΣW = new Symbol("ΣW");

                var Kf = new Symbol("Kf");
                var Ki = new Symbol("Ki");
                                
                var m = new Symbol("m");
                var d = new Symbol("d");

                var n = new Symbol("n");
                var g = new Symbol("g");
                var k = new Symbol("k");

                var vf = new Symbol("vf");
                var vi = new Symbol("vi");

                var fk = new Symbol("fk");
                                
                var W_f = new Symbol("W_f");
                var W_s = new Symbol("W_s");

                var μk = new Symbol("μk");
                                
                var xi = new Symbol("xi");
                var xf = new Symbol("xf");
                
                var eqs = and(
                    
                    n == m * g,

                    fk == μk * n,

                    Kf == m * (vf ^ 2) / 2,
                    Ki == m * (vi ^ 2) / 2,

                    W_f == -fk * d,
                                                            
                    W_s == k * (xi ^ 2) / 2 - k * (xf ^ 2) / 2,                    

                    ΣW == Kf - Ki,

                    ΣW == W_f + W_s,

                    m != 0
                    
                    );

                var vals = new List<Equation>()
                { m == 2.0, k == 500, xi == 0.05, xf == 0.0, vi == 0, d == 0.05, g == 9.8 };

                eqs
                    .EliminateVariables(Kf, Ki, ΣW, W_f, W_s, n, fk)
                    .IsolateVariable(vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)

                    .AssertEqTo(
                        or(
                            and(
                                vf == sqrt(-2 * m * (-m * (vi ^ 2) / 2 + k * (xf ^ 2) / 2 - k * (xi ^ 2) / 2 + d * g * m * μk)) / m,
                                m != 0
                            ),
                            and(
                                vf == -sqrt(-2 * m * (-m * (vi ^ 2) / 2 + k * (xf ^ 2) / 2 - k * (xi ^ 2) / 2 + d * g * m * μk)) / m,
                                m != 0)))

                    .SubstituteEqLs(vals).SubstituteEq(μk == 0)

                    .AssertEqTo(or(vf == 0.79056941504209488, vf == -0.79056941504209488));

                eqs
                    .EliminateVariables(Kf, Ki, ΣW, W_f, W_s, n, fk)
                    .IsolateVariable(vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)
                    .SubstituteEqLs(vals).SubstituteEq(μk == 0.35)
                    .AssertEqTo(or(vf == 0.53103672189407025, vf == -0.53103672189407025));
            }
            #endregion
            
            #region PSE 5E 7.55
            {
                // A baseball outfielder throws a 0.150-kg baseball at a
                // speed of 40.0 m/s and an initial angle of 30.0°. What is
                // the kinetic energy of the baseball at the highest point of
                // the trajectory?

                var vx = new Symbol("vx");
                var vi = new Symbol("vi");
                var th = new Symbol("th");

                var m = new Symbol("m");
                var K = new Symbol("K");

                var vals = new List<Equation>() { m == 0.15, vi == 40.0, th == (30).ToRadians() };

                var eqs = and(

                    vx == vi * cos(th),
                    
                    K == m * (vx ^ 2) / 2
                    
                    );

                eqs
                    .EliminateVariables(vx)
                    
                    .AssertEqTo(K == (cos(th) ^ 2) * m * (vi ^ 2) / 2)
                    
                    .SubstituteEqLs(vals)

                    .AssertEqTo(K == 90.0);
            }
            #endregion

            #region PSE 5E E8.2
            {
                // A ball  of mass m is dropped from a height h above the
                // ground, as shown in Figure 8.6.

                // (a) Neglecting air resistance, determine the speed of
                // the ball when it is at a height ya bove the ground.

                // (b) Determine the speed of the ball at y if at the instant of
                // release it already has an initial speed vi at the initial altitude h.
                
                var m = new Symbol("m");

                var yi = new Symbol("yi");
                var yf = new Symbol("yf");

                var vi = new Symbol("vi");
                var vf = new Symbol("vf");

                var Ki = new Symbol("Ki");
                var Kf = new Symbol("Kf");

                var Ugi = new Symbol("Ugi");
                var Ugf = new Symbol("Ugf");

                var ΣUi = new Symbol("ΣUi");
                var ΣUf = new Symbol("ΣUf");

                var Ei = new Symbol("Ei");
                var Ef = new Symbol("Ef");

                var g = new Symbol("g");

                var h = new Symbol("h");
                var y = new Symbol("y");

                var eqs = and(
                    Ki == m * (vi^2) / 2,
                    Kf == m * (vf^2) / 2,

                    Ugi == m * g * yi,
                    Ugf == m * g * yf,

                    ΣUi == Ugi,
                    ΣUf == Ugf,

                    Ei == Ki + ΣUi,
                    Ef == Kf + ΣUf,

                    Ei == Ef
                );

                var vals = new List<Equation>() { yi == h, yf == y };

                // vf, vi == 0
                eqs
                    .EliminateVariables(Ugi, Ugf, ΣUi, ΣUf, Ki, Kf, Ei, Ef)
                    .MultiplyBothSidesBy(1 / m)
                    .AlgebraicExpand()
                    .IsolateVariable(vf)
                    .SubstituteEqLs(vals)
                    .SubstituteEq(vi == 0)

                    .AssertEqTo(
                        or(
                            vf == -sqrt(2 * (g * h - g * y)),
                            vf == sqrt(2 * (g * h - g * y))
                        ));

                // vf
                eqs
                    .EliminateVariables(Ugi, Ugf, ΣUi, ΣUf, Ki, Kf, Ei, Ef)
                    .MultiplyBothSidesBy(1 / m)
                    .AlgebraicExpand()
                    .IsolateVariable(vf)
                    .SubstituteEqLs(vals)
                    
                    .AssertEqTo(
                        or(
                            vf == -sqrt(2 * (g * h + (vi ^ 2) / 2 - g * y)),
                            vf == sqrt(2 * (g * h + (vi ^ 2) / 2 - g * y))
                        ));
                
            }
            #endregion
                                    
            #region PSE 5E E8.3
            {
                // A pendulum consists of a sphere of mass mattached to a light
                // cord of length L, as shown in Figure 8.7. The sphere is released
                // from rest when the cord makes an angle thA with the vertical,
                // and the pivot at P is frictionless.

                // (a) Find the speed of the sphere when it is at the lowest point B.

                // (b) What is the tension T_B in the cord at B?

                // (c) A pendulum of length 2.00 m and mass 0.500 kg
                // is released from rest when the cord makes an angle of 30.0°
                // with the vertical. Find the speed of the sphere and the tension
                // in the cord when the sphere is at its lowest point.
                
                var m = new Symbol("m");

                var yi = new Symbol("yi");
                var yf = new Symbol("yf");

                var vi = new Symbol("vi");
                var vf = new Symbol("vf");

                var Ki = new Symbol("Ki");
                var Kf = new Symbol("Kf");

                var Ugi = new Symbol("Ugi");
                var Ugf = new Symbol("Ugf");

                var ΣUi = new Symbol("ΣUi");
                var ΣUf = new Symbol("ΣUf");

                var Ei = new Symbol("Ei");
                var Ef = new Symbol("Ef");

                var g = new Symbol("g");

                var L = new Symbol("L");

                var thA = new Symbol("thA");

                var ar_f = new Symbol("ar_f");

                var r = new Symbol("r");

                var ΣFr = new Symbol("ΣFr");

                var T_f = new Symbol("T_f");

                var vf_sq = new Symbol("vf_sq");

                var eqs = and(
                    
                    Ki == m * (vi^2) / 2,
                    Kf == m * (vf^2) / 2,
                
                    Ugi == m * g * yi,
                    Ugf == m * g * yf,
                
                    ΣUi == Ugi,
                    ΣUf == Ugf,

                    Ei == Ki + ΣUi,
                    Ef == Kf + ΣUf,

                    Ei == Ef,

                    ar_f == (vf ^ 2) / r,

                    ΣFr == T_f - m * g,

                    ΣFr == m * ar_f

                    );

                var vals = new List<Equation>()
                {
                    yi == -L * cos(thA),
                    yf == -L,
                    vi == 0,

                    r == L
                };

                var numerical_vals = new List<Equation>() { L == 2.0, m == 0.5, thA == (30).ToRadians(), g == 9.8 };

                // vf
                eqs
                    .SubstituteEqLs(vals)
                    .EliminateVariables(ar_f, ΣFr, T_f, Ki, Kf, Ugi, Ugf, ΣUi, ΣUf, Ei, Ef)
                    .MultiplyBothSidesBy(1 / m)
                    .AlgebraicExpand()
                    .IsolateVariable(vf)

                    .AssertEqTo(

                        or(
                            vf == -sqrt(2 * (g * L - cos(thA) * g * L)),
                            vf == sqrt(2 * (g * L - cos(thA) * g * L))
                        )

                    )
                    
                    .SubstituteEqLs(numerical_vals).Substitute(3, 3.0)

                    .AssertEqTo(
                        or(
                            vf == -2.2916815161906787,
                            vf == 2.2916815161906787
                        )
                    );

                // T_f
                eqs
                    .SubstituteEqLs(vals)
                    .Substitute(vf ^ 2, vf_sq)
                    .EliminateVariables(Ki, Kf, Ugi, Ugf, ΣUi, ΣUf, Ei, Ef, ar_f, ΣFr, vf_sq)
                    .MultiplyBothSidesBy(1 / m)
                    .AlgebraicExpand()
                    .IsolateVariable(T_f)

                    .AssertEqTo(
                        
                        T_f == (3 * g - 2 * cos(thA) * g) * m
                        
                    );
                
            }
            #endregion
                        
            #region PSE 5E E8.4
            {
                // A 3.00-kg crate slides down a ramp. The ramp is 1.00 m in
                // length and inclined at an angle of 30.0°, as shown in Figure
                // 8.8. The crate starts from rest at the top, experiences a
                // constant frictional force of magnitude 5.00 N, and continues to
                // move a short distance on the flat floor after it leaves the
                // ramp. Use energy methods to determine the speed of the
                // crate at the bottom of the ramp.

                var m = new Symbol("m");

                var yi = new Symbol("yi");
                var yf = new Symbol("yf");

                var vi = new Symbol("vi");
                var vf = new Symbol("vf");

                var Ki = new Symbol("Ki");
                var Kf = new Symbol("Kf");

                var Ugi = new Symbol("Ugi");
                var Ugf = new Symbol("Ugf");

                var ΣUi = new Symbol("ΣUi");
                var ΣUf = new Symbol("ΣUf");

                var Ei = new Symbol("Ei");
                var Ef = new Symbol("Ef");

                var fk = new Symbol("fk");

                var W_f = new Symbol("W_f");

                var ΔE = new Symbol("ΔE");

                var g = new Symbol("g");

                var d = new Symbol("d");

                var θ = new Symbol("θ");

                var eqs = and(

                    yi == d * sin(θ),

                    Ki == m * (vi ^ 2) / 2,
                    Kf == m * (vf ^ 2) / 2,

                    Ugi == m * g * yi,
                    Ugf == m * g * yf,

                    ΣUi == Ugi,
                    ΣUf == Ugf,

                    W_f == -fk * d,

                    ΔE == W_f,

                    Ei == Ki + ΣUi,
                    Ef == Kf + ΣUf,

                    Ei + ΔE == Ef,

                    m != 0

                    );

                var vals = new List<Equation>()
                { m == 3.0, d == 1.0, θ == (30).ToRadians(), fk == 5.0, vi == 0.0, g == 9.8, yf == 0.0 };
                    
                eqs
                    .EliminateVariables(Ei, Ef, ΔE, Ki, Kf, ΣUi, ΣUf, W_f, Ugi, Ugf, yi)
                    .IsolateVariable(vf)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical().CheckVariable(m)

                    .AssertEqTo(
                        or(
                            and(
                                vf == -sqrt(2 * m * (-d * fk + m * (vi ^ 2) / 2 - g * m * yf + g * m * d * sin(θ))) / m,
                                m != 0
                            ),
                            and(
                                vf == sqrt(2 * m * (-d * fk + m * (vi ^ 2) / 2 - g * m * yf + g * m * d * sin(θ))) / m,
                                m != 0
                            )))
                            
                    .SubstituteEqLs(vals)

                    .AssertEqTo(or(vf == -2.54296414970142, vf == 2.54296414970142));
            }
            #endregion

            #region PSE 5E Example 8.5
            {
                // A child of mass mrides on an irregularly curved slide of
                // height as shown in  Figure 8.9.The child starts
                // from rest at the top.

                // (a) Determine his speed at the bottom, assuming no friction is present.

                // (b) If a force of kinetic friction acts on the child, how
                // much mechanical energy does the system lose? Assume that
                // vf = 3.0 m/s and m = 20.0 kg.

                var m = new Symbol("m");

                var yi = new Symbol("yi");
                var yf = new Symbol("yf");

                var vi = new Symbol("vi");
                var vf = new Symbol("vf");

                var Ki = new Symbol("Ki");
                var Kf = new Symbol("Kf");

                var Ugi = new Symbol("Ugi");
                var Ugf = new Symbol("Ugf");

                var ΣUi = new Symbol("ΣUi");
                var ΣUf = new Symbol("ΣUf");

                var Ei = new Symbol("Ei");
                var Ef = new Symbol("Ef");

                var fk = new Symbol("fk");

                var W_f = new Symbol("W_f");

                var ΔE = new Symbol("ΔE");

                var g = new Symbol("g");

                var d = new Symbol("d");

                var eqs = and(

                    Ki == m * (vi ^ 2) / 2,
                    Kf == m * (vf ^ 2) / 2,

                    Ugi == m * g * yi,
                    Ugf == m * g * yf,

                    ΣUi == Ugi,
                    ΣUf == Ugf,

                    W_f == -fk * d,

                    ΔE == W_f,

                    Ei == Ki + ΣUi,
                    Ef == Kf + ΣUf,

                    Ei + ΔE == Ef);

                {
                    var vals = new List<Equation>()
                    { yi == 2.0, yf == 0, vi == 0, fk == 0, g == 9.8 };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // vf
                    eqs
                        .SubstituteEqLs(zeros)
                        .EliminateVariables(Ei, Ef, ΔE, Ki, Kf, ΣUi, ΣUf, W_f, Ugi, Ugf)
                        .MultiplyBothSidesBy(1 / m)
                        .IsolateVariable(vf)

                        .AssertEqTo(
                            or(
                                vf == -sqrt(2 * g * yi),
                                vf == sqrt(2 * g * yi)))

                        .SubstituteEqLs(vals)

                        .AssertEqTo(
                            or(
                                vf == -6.2609903369994111,
                                vf == 6.2609903369994111));
                }

                {
                    var vals = new List<Equation>()
                    { m == 20.0, yi == 2.0, yf == 0, vi == 0, vf == 3.0, g == 9.8 };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    // ΔE
                    eqs
                        .SubstituteEqLs(zeros)
                        .EliminateVariables(fk, Ei, Ef, Ki, Kf, ΣUi, ΣUf, Ugi, Ugf, W_f)
                        .IsolateVariable(ΔE)
                        
                        .AssertEqTo(ΔE == m * (vf ^ 2) / 2 - g * m * yi)
                        
                        .SubstituteEqLs(vals)
                        
                        .AssertEqTo(ΔE == -302.0);
                }
            }
            #endregion
            
            Console.WriteLine("Testing complete");
            
            Console.ReadLine();
        }
Ejemplo n.º 21
0
 public void Visit(And and)
 {
     ResultIsBoolAndBothOperandsMustBeBool(and);
 }
        private BizBus.Filter.Filter GetFilter()
        {
            BizBus.Filter.Filter filter = new BizBus.Filter.Filter();
            And and = new And();

            filter.Matcher = and;

            if (this.BizQuery == null)
            {
                return(filter);
            }
            //读取默认值和传入的映射
            Dictionary <string, object> items = new Dictionary <string, object>();
            Dictionary <string, DataModel.BizQueryItem> QueryItems = new Dictionary <string, DataModel.BizQueryItem>();

            if (this.BizQuery.QueryItems == null)
            {
                this.BizQuery.QueryItems = new DataModel.BizQueryItem[] {}
            }
            ;
            foreach (DataModel.BizQueryItem QueryItem in this.BizQuery.QueryItems)
            {
                QueryItems.Add(QueryItem.PropertyName, QueryItem);
                if (QueryItem.FilterType == OThinker.H3.DataModel.FilterType.SystemParam)
                {
                    items.Add(QueryItem.PropertyName, SheetUtility.GetSystemParamValue(this.UserValidator, QueryItem.DefaultValue));
                }
                else
                {
                    //设置默认值
                    if (!string.IsNullOrWhiteSpace(QueryItem.DefaultValue))
                    {
                        items.Add(QueryItem.PropertyName, SheetUtility.GetSystemParamValue(this.UserValidator, QueryItem.DefaultValue));
                    }
                    //设置映射传入的值
                    if (this.InputMapping != null)
                    {
                        if (this.InputMapping.ContainsKey(QueryItem.PropertyName))
                        {
                            if (items.ContainsKey(QueryItem.PropertyName))
                            {
                                items[QueryItem.PropertyName] = this.InputMapping[QueryItem.PropertyName];
                            }
                            else
                            {
                                items.Add(QueryItem.PropertyName, this.InputMapping[QueryItem.PropertyName]);
                            }
                        }
                    }
                }
            }
            //页面传过来的值
            string FilterStr = Request["Filters"] ?? "";

            if (!string.IsNullOrWhiteSpace(FilterStr))
            {
                Dictionary <string, string> Filters = Newtonsoft.Json.JsonConvert.DeserializeObject <Dictionary <string, string> >(FilterStr);
                foreach (string key in Filters.Keys)
                {
                    if (!QueryItems.ContainsKey(key))
                    {
                        continue;
                    }
                    DataModel.BizQueryItem QueryItem = QueryItems[key];
                    if (QueryItem.FilterType == OThinker.H3.DataModel.FilterType.SystemParam)
                    {
                        continue;
                    }
                    if (QueryItem.Visible == OThinker.Data.BoolMatchValue.False)
                    {
                        continue;
                    }

                    if (items.ContainsKey(key))
                    {
                        items[key] = Filters[key];
                    }
                    else
                    {
                        items.Add(key, Filters[key]);
                    }
                }
            }
            //添加到过滤集合
            foreach (string key in items.Keys)
            {
                DataModel.BizQueryItem QueryItem = QueryItems[key];
                if (QueryItem.FilterType == OThinker.H3.DataModel.FilterType.Equals ||
                    QueryItem.FilterType == OThinker.H3.DataModel.FilterType.SystemParam)
                {
                    and.Add(new ItemMatcher(key, OThinker.Data.ComparisonOperatorType.Equal, items[key]));
                }
                else if (QueryItem.FilterType == OThinker.H3.DataModel.FilterType.Contains)
                {
                    and.Add(new ItemMatcher(key, OThinker.Data.ComparisonOperatorType.Contain, items[key]));
                }
                else if (QueryItem.FilterType == OThinker.H3.DataModel.FilterType.Scope)
                {
                    string[] vals = items[key].ToString().Split(';');
                    if (vals.Length > 1)
                    {
                        and.Add(new ItemMatcher(key, OThinker.Data.ComparisonOperatorType.NotBelow, vals[0]));
                    }
                    if (vals.Length > 2)
                    {
                        and.Add(new ItemMatcher(key, OThinker.Data.ComparisonOperatorType.NotAbove, vals[1]));
                    }
                }
            }
            //设置排序
            filter.AddSortBy(new SortBy(this.BizQuery.Columns.FirstOrDefault().PropertyName, SortDirection.Ascending));
            return(filter);
        }
    }
Ejemplo n.º 23
0
 public void Visit(And and)
 {
     // Nothing to do here...
 }
Ejemplo n.º 24
0
        public void ResultTypeBoolBoolTest()
        {
            var exp = new And(new Bool(true), new Bool(false));

            Assert.Equal(ExpressionResultType.Boolean, exp.ResultType);
        }
Ejemplo n.º 25
0
        static void Main()
        {
            #region Propositional Logic & FOL

            var p = new Variable(true)
            {
                Name = "p"
            };
            var q = new Variable(true)
            {
                Name = "q"
            };
            var r = new Variable(true)
            {
                Name = "r"
            };
            var u = new Variable(true)
            {
                Name = "u"
            };
            var m = new Variable(true)
            {
                Name = "m"
            };
            var n = new Variable(true)
            {
                Name = "n"
            };
            var l = new Variable(true)
            {
                Name = "l"
            };
            var t = new Variable(true)
            {
                Name = "t"
            };

            // p v q ^ p v 'q ^ 'p v q ^ 'p v 'r
            //var f1 = new And(new Or(p, q), new Or(p, new Not(q)));
            //var f2 = new And(new Or(new Not(p), q), new Or(new Not(p), new Not(r)));
            //var formula = new And(f1, f2);

            //var f1 = new Or(p, new Not(q));
            //var f2 = new Or(new Not(p), r);
            //var formula = new And(f1, new And(f2, q));

            var f1      = new Or(new Not(n), new Not(t));
            var f2      = new Or(m, new Or(q, n));
            var f3      = new Or(l, new Not(m));
            var f4      = new Or(l, new Not(q));
            var f5      = new Or(new Not(l), new Not(p));
            var f6      = new Or(r, new Or(p, n));
            var f7      = new Or(new Not(r), new Not(l));
            var formula = new And(f1, new And(f2, new And(f3, new And(f4, new And(f5, new And(f6, new And(f7, t)))))));

            // (p v q v r) ^ (p v q v 'r) ^ (p v 'q v r) ^ (p v 'q v 'r) ^ ('p v q v r) ^ ('p v q v 'r) ^ ('p v 'q v r)
            //var f1 = new Or(p, new Or(q, r));
            //var f2 = new Or(p, new Or(q, new Not(r)));
            //var f3 = new Or(p, new Or(new Not(q), r));
            //var f4 = new Or(p, new Or(new Not(q), new Not(r)));
            //var f5 = new Or(new Not(p), new Or(q, r));
            //var f6 = new Or(new Not(p), new Or(q, new Not(r)));
            //var f7 = new Or(new Not(p), new Or(new Not(q), r));
            //var formula = new And(f1, new And(f2, new And(f3, new And(f4, new And(f5, new And(f6, f7))))));

            // (p v q v 'r) ^ (p v q v r) ^ (p v 'q) ^ 'p
            //var f1 = new Or(p, new Or(q, new Not(r)));
            //var f2 = new Or(p, new Or(q, r));
            //var f3 = new Or(p, new Not(q));
            //var formula = new And(f1, new And(f2, new And(f3, new Not(p))));

            //var formula = new And(new Not(p), p);
            //var bdt = BinaryDecisionTree.FromFormula(formula);

            //var nnf = formula.ToNnf();
            //Console.WriteLine("NNF: " + nnf);

            //nnf = nnf.ToCnf();
            //var cnf = new Cnf(nnf as And);
            //cnf.SimplifyCnf();

            //Console.WriteLine("CNF: " + cnf);
            //Console.WriteLine("SAT: " + cnf.Dpll());

            p.Value = true;
            // Console.WriteLine(formula.Evaluate());

            #endregion

            #region Agents

            //var terrain = new [,]
            //                  {
            //                      {0, 0, 0},
            //                      {1, 1, 1},
            //                      {2, 2, 2}
            //                  };
            var terrain = new int[1000, 1];
            var random  = new Random();

            //for (int i = 0; i < terrain.GetLength(0); i++)
            //{
            //      for (int j = 0; j < terrain.GetLength(1); j++)
            //     {
            //         if (i == terrain.GetLength(0) - 1)
            //            terrain[i, j] = 1;
            //     }
            //}

            //var cleaningRobot = new CleaningAgent(terrain, 0, 0);
            //cleaningRobot.Print();
            //cleaningRobot.Start(200);
            //cleaningRobot.Print();


            //var johnny = new Dog("Johnny", 17.5, Gender.Male);
            //var jack = new Dog("Jack", 23.5, Gender.Male);
            //var jordan = new Dog("Jack", 21.2, Gender.Male);
            //var melissa = new Dog("Melissa", 19.7, Gender.Female);
            //var dogs = new List<Dog> { johnny, jack, jordan, melissa };

            //Predicate<Dog> maleFinder = (Dog d) => { return d.Sex == Gender.Male; };
            //Predicate<Dog> heavyDogsFinder = (Dog d) => { return d.Weight >= 22; };

            //var maleDogs = dogs.Find(maleFinder);
            //var heavyDogs = dogs.Find(heavyDogsFinder);

            var water = new List <Tuple <int, int> >
            {
                new Tuple <int, int> (1, 2),
                new Tuple <int, int> (3, 5),
            };

            var obstacles = new List <Tuple <int, int> >
            {
                new Tuple <int, int> (2, 2),
                new Tuple <int, int> (4, 5),
            };

            var beliefs = new List <Belief> {
                new Belief(TypesBelief.PotentialWaterSpots, water),
                new Belief(TypesBelief.ObstaclesOnTerrain, obstacles),
            };

            var marsTerrain = new [, ]
            {
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0.8, -1, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0.8, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0.8, 0, 0, 0, 0 },
                { 0, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
            };


            var marsUnderneathTerrain = new [, ]
            {
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, true, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
                { false, false, false, false, false, false, false, false, false, false },
            };

            var marsRocksCompound = new [, ]
            {
                { "", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "AXY", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "AXY", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "", "", "", "", "", "", "", "", "", "" },
                { "AXY", "", "", "", "", "", "", "", "", "" }
            };

            var roverTerrain = new [, ]
            {
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0.8, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0.8, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0.8, 0, 0, 0, 0 },
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            };

            var mars  = new Mars(marsTerrain);
            var rover = new MarsRover(mars, roverTerrain, 7, 8, beliefs, 0.75, 2);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            // Application.Run(new MarsWorld(rover, mars, 10, 10));

            #endregion

            #region Multi-Agent Systems

            //var room = new [,]
            //               {
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            //                   {2, 0, 0, 1, 0, 0, 0, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            //                   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
            //               };

            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);

            //const int N = 10;
            //const int M = 10;
            //var roomGui = new Room(N, M, room);

            //InitCommunicationService();

            //var clAgent1 = new MasCleaningAgent(Guid.NewGuid(), room, roomGui, 0, 0, Color.Teal);
            //var clAgent2 = new MasCleaningAgent(Guid.NewGuid(), room, roomGui, 1, 1, Color.Yellow);
            //var clAgent3 = new MasCleaningAgent(Guid.NewGuid(), room, roomGui, 1, 2, Color.Tomato);
            //var clAgent4 = new MasCleaningAgent(Guid.NewGuid(), room, roomGui, 2, 1, Color.LightSkyBlue);
            //var clAgent5 = new MasCleaningAgent(Guid.NewGuid(), room, roomGui, 2, 2, Color.Black);

            //roomGui.CleaningAgents = new List<MasCleaningAgent> { clAgent1, clAgent2, clAgent3, clAgent4, clAgent5 };
            //var platform = new CleaningAgentPlatform(roomGui.CleaningAgents, new CleaningTask(M, roomGui.CleaningAgents.Count));

            //Application.Run(roomGui);

            #endregion

            #region Simulation

            //var airplanes = new List<Airplane>
            //                    {
            //                        new Airplane(100),
            //                        new Airplane(300),
            //                        new Airplane(50),
            //                        new Airplane(250),
            //                        new Airplane(150),
            //                        new Airplane(200),
            //                        new Airplane(120)
            //                    };

            //var sim = new Simulation.Airport.Simulation(new TimeSpan(0, 13, 0, 0), new TimeSpan(0, 15, 0, 0), airplanes);
            //sim.Execute();

            #endregion

            #region SVM

            //var trainingSamples = new List<TrainingSample>
            //                          {
            //                              new TrainingSample(new double[] {1, 1}, 1),
            //                              new TrainingSample(new double[] {1, 0}, 1),
            //                              new TrainingSample(new double[] {2, 2}, -1),
            //                              new TrainingSample(new double[] {2, 3}, -1),
            //                          };

            //var svmClassifier = new LinearSvmClassifier(trainingSamples);
            //svmClassifier.Training();
            //svmClassifier.Predict(new List<double[]>
            //                          {
            //                              new double[] {1, 1},
            //                              new double[] {1, 0},
            //                              new double[] {2, 2},
            //                              new double[] {2, 3},
            //                              new double[] {2, 0},
            //                              new []   {2.5, 1.5},
            //                              new []   {0.5, 1.5},
            //                          });

            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new SvmGui(svmClassifier.Weights, svmClassifier.Bias, svmClassifier.ModelToUse, svmClassifier.SetA, svmClassifier.SetB, svmClassifier.Hyperplane));

            #endregion

            #region Decision Trees

            //var values = new [,]
            //                 {
            //                     { "sunny", "12", "high", "weak", "no" },
            //                     { "sunny", "12", "high", "strong", "no" },
            //                     { "cloudy", "14", "high", "weak", "yes" },
            //                     { "rainy", "12", "high", "weak", "yes" },
            //                     { "rainy", "20", "normal", "weak", "yes" },
            //                     { "rainy", "20", "normal", "strong", "no" },
            //                     { "cloudy", "20", "normal", "strong", "yes" },
            //                     { "sunny", "12", "high", "weak", "no" },
            //                     { "sunny", "14", "normal", "weak", "yes" },
            //                     { "rainy", "20", "normal", "weak", "yes" },
            //                     { "sunny", "14", "normal", "strong", "yes" },
            //                     { "cloudy", "20", "high", "strong", "yes" },
            //                     { "cloudy", "20", "normal", "weak", "yes" },
            //                     { "rainy", "14", "high", "strong", "no" },
            //                 };

            //var attribs = new List<Attribute>
            //                  {
            //                      new Attribute("Outlook", new[] { "sunny", "cloudy", "rainy" }, TypeAttrib.NonGoal, TypeVal.Discrete),
            //                      new Attribute("Temperature", new[] { "12", "14", "20" }, TypeAttrib.NonGoal, TypeVal.Continuous),
            //                      new Attribute("Humidity", new[] { "high", "normal" }, TypeAttrib.NonGoal, TypeVal.Discrete),
            //                      new Attribute("Wind", new[] { "weak", "strong" }, TypeAttrib.NonGoal, TypeVal.Discrete),
            //                  };

            //var goalAttrib = new Attribute("Play Baseball", new[] { "yes", "no" }, TypeAttrib.Goal, TypeVal.Discrete);
            //var trainingDataSet = new TrainingDataSet(values, attribs, goalAttrib);
            //var dtree = DecisionTree.Learn(trainingDataSet, DtTrainingAlgorithm.Id3);
            //dtree.Visualize();

            #endregion

            #region Neural Networks

            //var trainingSamples = new List<TrainingSample>
            //                          {
            //                              new TrainingSample(new double[] {1, 1}, 0, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {1, 0}, 0, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {0, 1}, 0, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {0, 0}, 0, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {1, 2}, 1, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {2, 2}, 1, new List<double> { 1 } ),
            //                              new TrainingSample(new double[] {2, 3}, 1, new List<double> { 1 } ),
            //                              new TrainingSample(new double[] {0, 3}, 1, new List<double> { 1 } ),
            //                              new TrainingSample(new double[] {0, 2}, 1, new List<double> { 1 } ),
            //                          };

            //var trainingSamplesXor = new List<TrainingSample>
            //                          {
            //                              new TrainingSample(new double[] {0, 0}, -1, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {1, 1}, -1, new List<double> { 0 } ),
            //                              new TrainingSample(new double[] {0, 1}, -1, new List<double> { 1 } ),
            //                              new TrainingSample(new double[] {1, 0}, -1, new List<double> { 1 } ),
            //                          };

            //var perceptron = new Perceptron(trainingSamples, 2, 0.01);
            //var adaline = new Adaline(trainingSamples, 2, 0.01);
            //var multilayer = new MultiLayerNetwork(trainingSamplesXor, 2, 3, 1, 0.01);

            //adaline.Training();

            //var toPredict = new List<double[]>
            //                  {
            //                      new double[] {1, 1},
            //                      new double[] {1, 0},
            //                      new double[] {0, 0},
            //                      new double[] {0, 1},
            //                      new double[] {2, 0},
            //                      new[] {2.5, 2},
            //                      new[] {0.5, 1.5},
            //                  };

            //var predictions = adaline.PredictSet(toPredict);

            //for (var i = 0; i < predictions.Count; i++)
            //    Console.WriteLine("Data: ( {0} , {1} ) Classified as: {2}", toPredict[i][0], toPredict[i][1], predictions[i]);

            #endregion

            #region Handwritten Digit Recognition

            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new HandwrittenRecognitionGui());

            #endregion

            #region Clustering


            //var elements = new List<UnsupervisedLearning.Clustering.Element>
            //                   {
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {1, 2}),
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {1, 3}),
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {3, 3}),
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {3, 4}),
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {6, 6}),
            //                       new UnsupervisedLearning.Clustering.Element(new double[] {6, 7})
            //                   };
            //var dataSet = new DataSet();
            //dataSet.Load(elements);

            //var kMeans = new KMeans(3, dataSet);
            //kMeans.Start();

            //foreach (var cluster in kMeans.Clusters)
            //{
            //    Console.WriteLine("Cluster No {0}", cluster.ClusterNo);
            //    foreach (var obj in cluster.Objects)
            //        Console.WriteLine("({0}, {1}) in {2}", obj.Features[0], obj.Features[1], obj.Cluster);
            //    Console.WriteLine("--------------");
            //}

            #endregion

            #region MetaHeuristics

            //var f = new Function("f", "(x1)^2", "x1");
            //var hillClimbing = new HillClimbing(f, 5, 4);
            //var result = hillClimbing.Execute();

            //Console.WriteLine("Result: {0}", result[0]);

            //var map = new double[,] {
            //    {1, 2, 3, 1, 5},
            //    {5, 1, 1, 1, 8},
            //    {1, 7, 2, 1, 9},
            //    {1, 1, 6, 1, 8},
            //    {1, 1, 4, 1, 2},
            //};

            //var ga = new GeneticAlgorithmTsp(100, new Tsp(map), 100);
            //var best = ga.Execute();

            //Console.WriteLine("Solution:");
            //foreach (var d in best.Ordering)
            //    Console.Write("{0},", d);
            //Console.WriteLine('\n' + "Fitness: {0}", best.Fitness);

            #endregion

            #region Game Programming

            //var tree = new Tree<string> { State = "A" };
            //tree.Children.Add(new Tree<string> { State = "B",
            //    Children = new List<Tree<string>>
            //                   {
            //                       new Tree<string>("E")
            //                   } });
            //tree.Children.Add(new Tree<string> { State = "C",
            // Children = new List<Tree<string>>
            //                   {
            //                       new Tree<string>("F")
            //                   }
            //});
            //tree.Children.Add(new Tree<string> { State = "D" });

            //var bfs = new Bfs<string>(tree);
            //var dfs = new Dfs<string>(tree);
            //var dls = new Dls<string>(tree, 21, "E");
            //var ids = new Ids<string>(tree, 10, "F");
            ////var path = bfs.Execute();
            ////var path = dfs.Execute();
            ////var path = dls.Execute();
            ////var path = ids.Execute();

            //var state = new[,]
            //                {
            //                    {6, 4, 7},
            //                    {8, 5, 0},
            //                    {3, 2, 1}
            //                };

            ////var state = new[,]
            ////                {
            ////                    {1, 0, 2},
            ////                    {4, 5, 3},
            ////                    {7, 8, 6}
            //                //};

            //var goalState = new[,]
            //                {
            //                    {1, 2, 3},
            //                    {4, 5, 6},
            //                    {7, 8, 0}
            //                };

            //var board = new Board<int>(state, 0, new Tuple<int, int>(1, 2), "");
            //var goal = new Board<int>(goalState, 0, new Tuple<int, int>(2, 2), "");
            //var slidingTilesPuzzle = new SlidingTilesPuzzle<int>(board, goal);
            //var bidirectionalSearch = new Bs<int>(slidingTilesPuzzle);
            //var stopWatch = new Stopwatch();
            //stopWatch.Start();
            //var path = bidirectionalSearch.BidirectionalBfs();
            //stopWatch.Stop();

            //foreach (var e in path)
            //    Console.Write(e + ", ");
            //Console.WriteLine('\n' + "Total steps: " + path.Length);
            //Console.WriteLine("Elapsed Time: " + stopWatch.ElapsedMilliseconds / 1000 + " secs");

            //board = new Board<int>(state, 0, new Tuple<int, int>(1, 2), "");

            //for (var i = 0; i < path.Length; i++)
            //{
            //    if (path[i] == 'R')
            //        board = board.Move(Move.Right);
            //    if (path[i] == 'D')
            //        board = board.Move(Move.Down);
            //    if (path[i] == 'U')
            //        board = board.Move(Move.Up);
            //    if (path[i] == 'L')
            //        board = board.Move(Move.Left);
            //}

            #endregion

            #region Game Theory

            //var board = new OthelloBoard(8, 8);

            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new OthelloGui(board));

            #endregion

            #region Reinforcement Learning

            var map = new [, ]
            {
                { true, false, true, false, true },
                { true, true, true, false, true },
                { true, false, true, false, true },
                { true, false, true, true, true },
                { true, true, true, false, true }
            };

            var reward = new [, ]
            {
                { -0.01, -0.01, -0.01, -0.01, -0.01 },
                { -0.01, -0.01, -0.01, -0.01, -0.01 },
                { -0.01, -0.01, -0.01, -0.01, -0.01 },
                { -0.01, -0.01, -0.01, -0.01, -0.01 },
                { -0.01, -0.01, -0.01, -0.01, 1 },
            };

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MazeGui(5, 5, map, reward));

            #endregion

            Console.Read();
        }
Ejemplo n.º 26
0
 public void And_RegisterOperands_ResultIsCorrect()
 {
     var prev = new MutableState().Set(Register.A, 6).Set(Register.B, 5);
     var state = new And(new Reg(Register.A), new Reg(Register.B)).Apply(prev);
     Assert.AreEqual(0x04, state.Get(Register.A));
 }
Ejemplo n.º 27
0
	public void And(Rule rule)
	{
		And newRoot = new And(root, rule.root);
		root = newRoot;
	}
Ejemplo n.º 28
0
 public BuiltInFunctions()
 {
     // Text
     Functions["len"]         = new Len();
     Functions["lower"]       = new Lower();
     Functions["upper"]       = new Upper();
     Functions["left"]        = new Left();
     Functions["right"]       = new Right();
     Functions["mid"]         = new Mid();
     Functions["replace"]     = new Replace();
     Functions["rept"]        = new Rept();
     Functions["substitute"]  = new Substitute();
     Functions["concatenate"] = new Concatenate();
     Functions["concat"]      = new Concat();
     Functions["textjoin"]    = new Textjoin();
     Functions["char"]        = new CharFunction();
     Functions["exact"]       = new Exact();
     Functions["find"]        = new Find();
     Functions["fixed"]       = new Fixed();
     Functions["proper"]      = new Proper();
     Functions["search"]      = new Search();
     Functions["text"]        = new Text.Text();
     Functions["t"]           = new T();
     Functions["hyperlink"]   = new Hyperlink();
     Functions["value"]       = new Value(CultureInfo.CurrentCulture);
     Functions["trim"]        = new Trim();
     Functions["clean"]       = new Clean();
     Functions["unicode"]     = new Unicode();
     Functions["unichar"]     = new Unichar();
     Functions["numbervalue"] = new NumberValue();
     // Numbers
     Functions["int"] = new CInt();
     // Math
     Functions["abs"]             = new Abs();
     Functions["asin"]            = new Asin();
     Functions["asinh"]           = new Asinh();
     Functions["acot"]            = new Acot();
     Functions["acoth"]           = new Acoth();
     Functions["cos"]             = new Cos();
     Functions["cot"]             = new Cot();
     Functions["coth"]            = new Coth();
     Functions["cosh"]            = new Cosh();
     Functions["csc"]             = new Csc();
     Functions["csch"]            = new Csch();
     Functions["power"]           = new Power();
     Functions["gcd"]             = new Gcd();
     Functions["lcm"]             = new Lcm();
     Functions["sec"]             = new Sec();
     Functions["sech"]            = new SecH();
     Functions["sign"]            = new Sign();
     Functions["sqrt"]            = new Sqrt();
     Functions["sqrtpi"]          = new SqrtPi();
     Functions["pi"]              = new Pi();
     Functions["product"]         = new Product();
     Functions["ceiling"]         = new Ceiling();
     Functions["ceiling.precise"] = new CeilingPrecise();
     Functions["ceiling.math"]    = new CeilingMath();
     Functions["iso.ceiling"]     = new IsoCeiling();
     Functions["combin"]          = new Combin();
     Functions["combina"]         = new Combina();
     Functions["count"]           = new Count();
     Functions["counta"]          = new CountA();
     Functions["countblank"]      = new CountBlank();
     Functions["countif"]         = new CountIf();
     Functions["countifs"]        = new CountIfs();
     Functions["fact"]            = new Fact();
     Functions["factdouble"]      = new FactDouble();
     Functions["floor"]           = new Floor();
     Functions["floor.precise"]   = new FloorPrecise();
     Functions["floor.math"]      = new FloorMath();
     Functions["radians"]         = new Radians();
     Functions["roman"]           = new Roman();
     Functions["sin"]             = new Sin();
     Functions["sinh"]            = new Sinh();
     Functions["sum"]             = new Sum();
     Functions["sumif"]           = new SumIf();
     Functions["sumifs"]          = new SumIfs();
     Functions["sumproduct"]      = new SumProduct();
     Functions["sumsq"]           = new Sumsq();
     Functions["sumxmy2"]         = new Sumxmy2();
     Functions["sumx2my2"]        = new SumX2mY2();
     Functions["sumx2py2"]        = new SumX2pY2();
     Functions["seriessum"]       = new Seriessum();
     Functions["stdev"]           = new Stdev();
     Functions["stdevp"]          = new StdevP();
     Functions["stdev.s"]         = new StdevDotS();
     Functions["stdev.p"]         = new StdevDotP();
     Functions["subtotal"]        = new Subtotal();
     Functions["exp"]             = new Exp();
     Functions["log"]             = new Log();
     Functions["log10"]           = new Log10();
     Functions["ln"]              = new Ln();
     Functions["max"]             = new Max();
     Functions["maxa"]            = new Maxa();
     Functions["median"]          = new Median();
     Functions["min"]             = new Min();
     Functions["mina"]            = new Mina();
     Functions["mod"]             = new Mod();
     Functions["mode"]            = new Mode();
     Functions["mode.sngl"]       = new ModeSngl();
     Functions["mround"]          = new Mround();
     Functions["average"]         = new Average();
     Functions["averagea"]        = new AverageA();
     Functions["averageif"]       = new AverageIf();
     Functions["averageifs"]      = new AverageIfs();
     Functions["round"]           = new Round();
     Functions["rounddown"]       = new Rounddown();
     Functions["roundup"]         = new Roundup();
     Functions["rand"]            = new Rand();
     Functions["randbetween"]     = new RandBetween();
     Functions["rank"]            = new Rank();
     Functions["rank.eq"]         = new RankEq();
     Functions["rank.avg"]        = new RankAvg();
     Functions["percentile"]      = new Percentile();
     Functions["percentile.inc"]  = new PercentileInc();
     Functions["percentrank"]     = new Percentrank();
     Functions["percentrank.inc"] = new PercentrankInc();
     Functions["quotient"]        = new Quotient();
     Functions["trunc"]           = new Trunc();
     Functions["tan"]             = new Tan();
     Functions["tanh"]            = new Tanh();
     Functions["atan"]            = new Atan();
     Functions["atan2"]           = new Atan2();
     Functions["atanh"]           = new Atanh();
     Functions["acos"]            = new Acos();
     Functions["acosh"]           = new Acosh();
     Functions["var"]             = new Var();
     Functions["var.s"]           = new VarDotS();
     Functions["varp"]            = new VarP();
     Functions["var.p"]           = new VarDotP();
     Functions["large"]           = new Large();
     Functions["small"]           = new Small();
     Functions["degrees"]         = new Degrees();
     Functions["odd"]             = new Odd();
     Functions["even"]            = new Even();
     // Information
     Functions["isblank"]    = new IsBlank();
     Functions["isnumber"]   = new IsNumber();
     Functions["istext"]     = new IsText();
     Functions["isnontext"]  = new IsNonText();
     Functions["iserror"]    = new IsError();
     Functions["iserr"]      = new IsErr();
     Functions["error.type"] = new ErrorType();
     Functions["iseven"]     = new IsEven();
     Functions["isodd"]      = new IsOdd();
     Functions["islogical"]  = new IsLogical();
     Functions["isna"]       = new IsNa();
     Functions["na"]         = new Na();
     Functions["n"]          = new N();
     Functions["type"]       = new TypeFunction();
     // Logical
     Functions["if"]      = new If();
     Functions["ifs"]     = new Ifs();
     Functions["maxifs"]  = new MaxIfs();
     Functions["minifs"]  = new MinIfs();
     Functions["iferror"] = new IfError();
     Functions["ifna"]    = new IfNa();
     Functions["not"]     = new Not();
     Functions["and"]     = new And();
     Functions["or"]      = new Or();
     Functions["true"]    = new True();
     Functions["false"]   = new False();
     Functions["switch"]  = new Switch();
     // Reference and lookup
     Functions["address"]  = new Address();
     Functions["hlookup"]  = new HLookup();
     Functions["vlookup"]  = new VLookup();
     Functions["lookup"]   = new Lookup();
     Functions["match"]    = new Match();
     Functions["row"]      = new Row();
     Functions["rows"]     = new Rows();
     Functions["column"]   = new Column();
     Functions["columns"]  = new Columns();
     Functions["choose"]   = new Choose();
     Functions["index"]    = new RefAndLookup.Index();
     Functions["indirect"] = new Indirect();
     Functions["offset"]   = new Offset();
     // Date
     Functions["date"]             = new Date();
     Functions["today"]            = new Today();
     Functions["now"]              = new Now();
     Functions["day"]              = new Day();
     Functions["month"]            = new Month();
     Functions["year"]             = new Year();
     Functions["time"]             = new Time();
     Functions["hour"]             = new Hour();
     Functions["minute"]           = new Minute();
     Functions["second"]           = new Second();
     Functions["weeknum"]          = new Weeknum();
     Functions["weekday"]          = new Weekday();
     Functions["days"]             = new Days();
     Functions["days360"]          = new Days360();
     Functions["yearfrac"]         = new Yearfrac();
     Functions["edate"]            = new Edate();
     Functions["eomonth"]          = new Eomonth();
     Functions["isoweeknum"]       = new IsoWeekNum();
     Functions["workday"]          = new Workday();
     Functions["workday.intl"]     = new WorkdayIntl();
     Functions["networkdays"]      = new Networkdays();
     Functions["networkdays.intl"] = new NetworkdaysIntl();
     Functions["datevalue"]        = new DateValue();
     Functions["timevalue"]        = new TimeValue();
     // Database
     Functions["dget"]     = new Dget();
     Functions["dcount"]   = new Dcount();
     Functions["dcounta"]  = new DcountA();
     Functions["dmax"]     = new Dmax();
     Functions["dmin"]     = new Dmin();
     Functions["dsum"]     = new Dsum();
     Functions["daverage"] = new Daverage();
     Functions["dvar"]     = new Dvar();
     Functions["dvarp"]    = new Dvarp();
     //Finance
     Functions["cumipmt"]    = new Cumipmt();
     Functions["cumprinc"]   = new Cumprinc();
     Functions["ddb"]        = new Ddb();
     Functions["effect"]     = new Effect();
     Functions["fvschedule"] = new FvSchedule();
     Functions["pduration"]  = new Pduration();
     Functions["rri"]        = new Rri();
     Functions["pmt"]        = new Pmt();
     Functions["ppmt"]       = new Ppmt();
     Functions["ipmt"]       = new Ipmt();
     Functions["ispmt"]      = new IsPmt();
     Functions["pv"]         = new Pv();
     Functions["fv"]         = new Fv();
     Functions["npv"]        = new Npv();
     Functions["rate"]       = new Rate();
     Functions["nper"]       = new Nper();
     Functions["nominal"]    = new Nominal();
     Functions["irr"]        = new Irr();
     Functions["mirr"]       = new Mirr();
     Functions["xirr"]       = new Xirr();
     Functions["sln"]        = new Sln();
     Functions["syd"]        = new Syd();
     Functions["xnpv"]       = new Xnpv();
     Functions["coupdays"]   = new Coupdays();
     Functions["coupdaysnc"] = new Coupdaysnc();
     Functions["coupdaybs"]  = new Coupdaybs();
     Functions["coupnum"]    = new Coupnum();
     Functions["coupncd"]    = new Coupncd();
     Functions["couppcd"]    = new Couppcd();
     Functions["price"]      = new Price();
     Functions["yield"]      = new Yield();
     Functions["duration"]   = new Duration();
     Functions["disc"]       = new Disc();
     //Engineering
     Functions["bitand"]       = new BitAnd();
     Functions["bitor"]        = new BitOr();
     Functions["bitxor"]       = new BitXor();
     Functions["bitlshift"]    = new BitLshift();
     Functions["bitrshift"]    = new BitRshift();
     Functions["convert"]      = new ConvertFunction();
     Functions["bin2dec"]      = new Bin2Dec();
     Functions["bin2hex"]      = new Bin2Hex();
     Functions["bin2oct"]      = new Bin2Oct();
     Functions["dec2bin"]      = new Dec2Bin();
     Functions["dec2hex"]      = new Dec2Hex();
     Functions["dec2oct"]      = new Dec2Oct();
     Functions["hex2bin"]      = new Hex2Bin();
     Functions["hex2dec"]      = new Hex2Dec();
     Functions["hex2oct"]      = new Hex2Oct();
     Functions["oct2bin"]      = new Oct2Bin();
     Functions["oct2dec"]      = new Oct2Dec();
     Functions["oct2hex"]      = new Oct2Hex();
     Functions["delta"]        = new Delta();
     Functions["erf"]          = new Erf();
     Functions["erf.precise"]  = new ErfPrecise();
     Functions["erfc"]         = new Erfc();
     Functions["erfc.precise"] = new ErfcPrecise();
     Functions["besseli"]      = new BesselI();
     Functions["besselj"]      = new BesselJ();
     Functions["besselk"]      = new BesselK();
     Functions["bessely"]      = new BesselY();
 }
Ejemplo n.º 29
0
        public void ResultTypeNumVarTest()
        {
            var exp = new And(new Number(1), new Variable("x"));

            Assert.Equal(ExpressionResultType.Number, exp.ResultType);
        }
 //-----------------------------------------------------------
 public string Visit(And node)
 {
     return(VisitBinaryOperator("and", node));
 }
Ejemplo n.º 31
0
 public void Setup()
 {
     _byteFactory       = new ByteFactory(new Base10Converter());
     _and               = new And();
     _memoryGateFactory = new MemoryGateFactory(new NAnd(new Not(), _and));
 }
Ejemplo n.º 32
0
        public static Node Simplify(this Node node)
        {
            var nvars = node.ReferencedObstacles ().Count ()
                + node.ReferencedVariables ().Count ()
                    + node.ReferencedDomainProperties ().Count ();

            var conversionMap = new Dictionary<Obstacle, int> ();
            var i = 0;
            var iEnumerable = node.ReferencedObstacles ();
            foreach (var o in iEnumerable) {
                if (!conversionMap.ContainsKey (o))
                    conversionMap.Add (o, i++);
            }

            var conditionMap = new Dictionary<Condition, int> ();
            var iEnumerable2 = node.ReferencedVariables ();
            foreach (var o in iEnumerable2) {
                if (!conditionMap.ContainsKey (o))
                    conditionMap.Add (o, i++);
            }

            var dompropMap = new Dictionary<DomainProperty, int> ();
            var iEnumerable3 = node.ReferencedDomainProperties ();
            foreach (var o in iEnumerable3) {
                if (!dompropMap.ContainsKey (o))
                    dompropMap.Add (o, i++);
            }

            // Console.WriteLine (node);
            node = node.AndDistribute ();
            //            Console.WriteLine (node);
            node = node.Flatten ();
            //            Console.WriteLine (node);

            if (node is Or) {
                var or = (Or)node;
                var terms = new List<BoolSimplify.Term> ();
                foreach (var n in or.Nodes) {
                    var vars = new byte[nvars];
                    for (int j = 0; j < nvars; j++)
                        vars [j] = Term.DontCare;

                    if (NewMethod (n, vars, conversionMap, conditionMap, dompropMap)) {
                        terms.Add (new Term (vars));
                    }
                }

                var karnaughFormula = new BoolSimplify.Formula (terms);
                if (karnaughFormula.Terms.Count() == 0)
                    return new False ();
                 //Console.WriteLine (karnaughFormula);
                karnaughFormula.ReduceToPrimeImplicants ();
                if (karnaughFormula.Terms.Count() == 0)
                    return new False ();
            //                 Console.WriteLine (karnaughFormula);
                karnaughFormula.ReducePrimeImplicantsToSubset ();
                if (karnaughFormula.Terms.Count() == 0)
                    return new False ();
            //                 Console.WriteLine (karnaughFormula);

                var simplifiedFormula = new Or ();
                foreach (var t in karnaughFormula.Terms) {
                    var and = new And ();
                    for (int j = 0; j < t.NumVars; j++) {
                        if (t.Values [j] == 1) {
                            if (conversionMap.ContainsValue (j)) {
                                and.Nodes.Add (new ObstacleRef () {
                                    Obstacle = conversionMap.Where (x => x.Value == j).Select (x => x.Key).Single ()
                                });
                            }
                            if (conditionMap.ContainsValue (j)) {
                                and.Nodes.Add (conditionMap.Where (x => x.Value == j).Select (x => x.Key).Single ());
                            }
                            if (dompropMap.ContainsValue (j)) {
                                and.Nodes.Add (new DomPropRef () {
                                    DomainProperty = dompropMap.Where (x => x.Value == j).Select (x => x.Key).Single ()
                                });
                            }
                        }
                        if (t.Values [j] == 0) {
                            if (conversionMap.ContainsValue (j)) {
                                and.Nodes.Add (new ObstacleRef () {
                                    Obstacle = conversionMap.Where (x => x.Value == j).Select (x => x.Key).Single ()
                                }.Negate ());
                            }
                            if (conditionMap.ContainsValue (j)) {
                                and.Nodes.Add (conditionMap.Where (x => x.Value == j).Select (x => x.Key).Single ().Negate ());
                            }
                            if (dompropMap.ContainsValue (j)) {
                                and.Nodes.Add (new DomPropRef () {
                                    DomainProperty = dompropMap.Where (x => x.Value == j).Select (x => x.Key).Single ()
                                }.Negate ());
                            }
                        }
                    }
                    if (and.Nodes.Count > 0)
                        simplifiedFormula.Nodes.Add (and);
                }

                if (simplifiedFormula.Nodes.Count > 0)
                    return simplifiedFormula;
                else
                    return new Not { Enclosed = new False () };
            }

            if (node is ObstacleRef | node is DomPropRef | node is False)
                return node;

            return node;
            // throw new NotSupportedException (node.GetType ().ToString ());
        }
Ejemplo n.º 33
0
        private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter,
                                              IFunctionRegistry functionRegistry)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;

                return(Expression.Convert(Expression.Constant(constant.Value, typeof(int)), typeof(double)));
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;

                return(Expression.Constant(constant.Value, typeof(double)));
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Type contextType    = typeof(FormulaContext);
                Type dictionaryType = typeof(IDictionary <string, double>);

                Variable variable = (Variable)operation;

                Expression          getVariables = Expression.Property(contextParameter, "Variables");
                ParameterExpression value        = Expression.Variable(typeof(double), "value");

                Expression variableFound = Expression.Call(getVariables,
                                                           dictionaryType.GetRuntimeMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() }),
                                                           Expression.Constant(variable.Name),
                                                           value);

                Expression throwException = Expression.Throw(
                    Expression.New(typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(string.Format("The variable \"{0}\" used is not defined.", variable.Name))));

                LabelTarget returnLabel = Expression.Label(typeof(double));

                return(Expression.Block(
                           new[] { value },
                           Expression.IfThenElse(
                               variableFound,
                               Expression.Return(returnLabel, value),
                               throwException
                               ),
                           Expression.Label(returnLabel, Expression.Constant(0.0))
                           ));
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                Expression     argument1      = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry);
                Expression     argument2      = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry);

                return(Expression.Multiply(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition   addition  = (Addition)operation;
                Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Add(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition  = (Subtraction)operation;
                Expression  argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression  argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Subtract(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division   division = (Division)operation;
                Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry);

                return(Expression.Divide(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo     modulo   = (Modulo)operation;
                Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry);

                return(Expression.Modulo(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentation = (Exponentiation)operation;
                Expression     @base         = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry);
                Expression     exponent      = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry);

                return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                Expression argument   = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry);
                return(Expression.Negate(argument));
            }
            else if (operation.GetType() == typeof(And))
            {
                And        and       = (And)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.And(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Or))
            {
                Or         and       = (Or)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.Or(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan   lessThan  = (LessThan)operation;
                Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;
                Expression      argument1       = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression      argument2       = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;
                Expression  argument1   = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry);
                Expression  argument2   = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;
                Expression         argument1          = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression         argument2          = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal      equal     = (Equal)operation;
                Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.Equal(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual   notEqual  = (NotEqual)operation;
                Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.NotEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);
                Type         funcType;
                Type[]       parameterTypes;
                Expression[] arguments;

                if (functionInfo.IsDynamicFunc)
                {
                    funcType       = typeof(DynamicFunc <double, double>);
                    parameterTypes = new Type[] { typeof(double[]) };


                    Expression[] arrayArguments = new Expression[function.Arguments.Count];
                    for (int i = 0; i < function.Arguments.Count; i++)
                    {
                        arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }

                    arguments    = new Expression[1];
                    arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments);
                }
                else
                {
                    funcType       = GetFuncType(functionInfo.NumberOfParameters);
                    parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters)
                                      select typeof(double)).ToArray();

                    arguments = new Expression[functionInfo.NumberOfParameters];
                    for (int i = 0; i < functionInfo.NumberOfParameters; i++)
                    {
                        arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }
                }

                Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry");

                ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo));

                return(Expression.Block(
                           new[] { functionInfoVariable },
                           Expression.Assign(
                               functionInfoVariable,
                               Expression.Call(getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName))
                               ),
                           Expression.Call(
                               Expression.Convert(Expression.Property(functionInfoVariable, "Function"), funcType),
                               funcType.GetRuntimeMethod("Invoke", parameterTypes),
                               arguments)));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
Ejemplo n.º 34
0
        public static Node GetNonSatisfactionFormula(this Obstacle o)
        {
            if (o.Refinements ().Count () == 0) {
                return new ObstacleRef { Obstacle = o };
            }

            var or = new Or ();
            foreach (var refinement in o.Refinements ()) {
                var and = new And ();
                foreach (var obstacle in refinement.SubObstacles ()) {
                    and.Nodes.Add (GetNonSatisfactionFormula (obstacle));
                }
                foreach (var domprop in refinement.DomainProperties ()) {
                    and.Nodes.Add (GetNonSatisfactionFormula (domprop));
                }

                if (and.Nodes.Count == 1)
                    or.Nodes.Add (and.Nodes.Single ());
                else
                    or.Nodes.Add (and);
            }

            if (or.Nodes.Count == 1)
                return or.Nodes.Single ();

            return or;
        }
        /**
         * A ^ B -> A,B
         * ~~A -> A
         * ~(A v B) = ~A ^ ~B
         * ~(A => B) = A ^ ~B
         */
        public void ExpandToAndTest()
        {
            Symbol        s;
            Variable      A = new Variable('a');
            Variable      B = new Variable('b');
            List <Symbol> res;
            List <Symbol> expected;

            // test 01
            s        = new And(A, B);
            res      = SemanticTableau.ExpandToAnd(s);
            expected = new List <Symbol>()
            {
                A, B
            };

            Assert.AreEqual(expected.Count(), res.Count());
            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.AreEqual(expected[i].ToString(), res[i].ToString());
            }

            // test 02: ~~A -> A
            s        = new Not(new Not(A));
            res      = SemanticTableau.ExpandToAnd(s);
            expected = new List <Symbol>()
            {
                A
            };

            Assert.AreEqual(expected.Count(), res.Count());
            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.AreEqual(expected[i].ToString(), res[i].ToString());
            }

            // test 03: ~(A v B) = ~A ^ ~B
            s        = new Not(new Or(A, B));
            res      = SemanticTableau.ExpandToAnd(s);
            expected = new List <Symbol>()
            {
                new Not(A),
                new Not(B)
            };

            Assert.AreEqual(expected.Count(), res.Count());
            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.AreEqual(expected[i].ToString(), res[i].ToString());
            }

            // test 04: ~(A => B) = A ^ ~B
            s        = new Not(new Implication(A, B));
            res      = SemanticTableau.ExpandToAnd(s);
            expected = new List <Symbol>()
            {
                A,
                new Not(B)
            };

            Assert.AreEqual(expected.Count(), res.Count());
            for (int i = 0; i < expected.Count(); i++)
            {
                Assert.AreEqual(expected[i].ToString(), res[i].ToString());
            }
        }
Ejemplo n.º 36
0
        public static Node GetNonSatisfactionFormula(this Goal g)
        {
            var refinements = g.Refinements ();
            if (refinements.Count () > 1)
                throw new NotSupportedException ();

            if (refinements.Count () == 1) {
                var refinement = refinements.Single ();

                if (refinement.RefinementPattern == RefinementPattern.Redundant) {
                    return ANDPropagate (refinement);
                }

                if (refinement.RefinementPattern == RefinementPattern.Case) {
                    var orNode = new Or();

                    if (refinement.SubGoals().Count () != 2) {
                        throw new NotImplementedException ();
                    }

                    int index = 0;
                    foreach (var c in refinement.SubGoals ()) {
                        var andNode = new And ();
                        var probability = refinement.Parameters.ElementAt (index);
                        var condition = new Condition {
                            Cond = string.Format ("Case condition {0}", index),
                            Proba = probability
                        };

                        if (index == 0)
                            andNode.Nodes.Add (condition);
                        else if (index == 1)
                            andNode.Nodes.Add (condition.Negate ());

                        // TODO fix this bug, with Simplify() required.
                        var node = GetNonSatisfactionFormula (c);
                        andNode.Nodes.Add (node);

                        orNode.Nodes.Add (andNode);
                        index++;
                    }

                    return orNode;//.ToOr ();
                }

                return ORPropagate (refinement);
            }

            if (g.Obstructions().Count () == 1)
                return GetNonSatisfactionFormula (g.Obstructions().Single().Obstacle ());

            return new False ();
        }
Ejemplo n.º 37
0
        private static Activity HandleBinaryExpression <TLeft, TRight, TResult>(BinaryOperator op, TestExpression left, TestExpression right)
        {
            Activity           we           = null;
            InArgument <TLeft> leftArgument = (InArgument <TLeft>)TestExpression.GetInArgumentFromExpectedNode <TLeft>(left);

            leftArgument.EvaluationOrder = 0;
            InArgument <TRight> rightArgument = (InArgument <TRight>)TestExpression.GetInArgumentFromExpectedNode <TRight>(right);

            rightArgument.EvaluationOrder = 1;

            switch (op)
            {
            case BinaryOperator.Add:
                we = new Add <TLeft, TRight, TResult>()
                {
                    Checked = false,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            case BinaryOperator.And:
                we = new And <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.AndAlso:
                we = new AndAlso()
                {
                    Left  = TestExpression.GetWorkflowElementFromExpectedNode <bool>(left),
                    Right = TestExpression.GetWorkflowElementFromExpectedNode <bool>(right)
                };
                break;

            case BinaryOperator.CheckedAdd:
                we = new Add <TLeft, TRight, TResult>()
                {
                    Checked = true,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            case BinaryOperator.CheckedMultiply:
                we = new Multiply <TLeft, TRight, TResult>()
                {
                    Checked = true,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            case BinaryOperator.CheckedSubtract:
                we = new Subtract <TLeft, TRight, TResult>()
                {
                    Checked = true,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            case BinaryOperator.Divide:
                we = new Divide <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.Equal:
                we = new Equal <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.GreaterThan:
                we = new GreaterThan <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.GreaterThanOrEqual:
                we = new GreaterThanOrEqual <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.LessThan:
                we = new LessThan <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.LessThanOrEqual:
                we = new LessThanOrEqual <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.Or:
                we = new Or <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.Multiply:
                we = new Multiply <TLeft, TRight, TResult>()
                {
                    Checked = false,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            case BinaryOperator.NotEqual:
                we = new NotEqual <TLeft, TRight, TResult>()
                {
                    Left  = leftArgument,
                    Right = rightArgument
                };
                break;

            case BinaryOperator.OrElse:
                we = new OrElse()
                {
                    Left  = TestExpression.GetWorkflowElementFromExpectedNode <bool>(left),
                    Right = TestExpression.GetWorkflowElementFromExpectedNode <bool>(right)
                };
                break;

            case BinaryOperator.Subtract:
                we = new Subtract <TLeft, TRight, TResult>()
                {
                    Checked = false,
                    Left    = leftArgument,
                    Right   = rightArgument
                };
                break;

            default:
                throw new NotSupportedException(string.Format("Operator: {0} is unsupported", op.ToString()));
            }

            return(we);
        }
 public BuiltInFunctions()
 {
     // Text
     Functions["len"]         = new Len();
     Functions["lower"]       = new Lower();
     Functions["upper"]       = new Upper();
     Functions["left"]        = new Left();
     Functions["right"]       = new Right();
     Functions["mid"]         = new Mid();
     Functions["replace"]     = new Replace();
     Functions["rept"]        = new Rept();
     Functions["substitute"]  = new Substitute();
     Functions["concatenate"] = new Concatenate();
     Functions["char"]        = new CharFunction();
     Functions["exact"]       = new Exact();
     Functions["find"]        = new Find();
     Functions["fixed"]       = new Fixed();
     Functions["proper"]      = new Proper();
     Functions["search"]      = new Search();
     Functions["text"]        = new Text.Text();
     Functions["t"]           = new T();
     Functions["hyperlink"]   = new Hyperlink();
     Functions["value"]       = new Value();
     // Numbers
     Functions["int"] = new CInt();
     // Math
     Functions["abs"]         = new Abs();
     Functions["asin"]        = new Asin();
     Functions["asinh"]       = new Asinh();
     Functions["cos"]         = new Cos();
     Functions["cosh"]        = new Cosh();
     Functions["power"]       = new Power();
     Functions["sign"]        = new Sign();
     Functions["sqrt"]        = new Sqrt();
     Functions["sqrtpi"]      = new SqrtPi();
     Functions["pi"]          = new Pi();
     Functions["product"]     = new Product();
     Functions["ceiling"]     = new Ceiling();
     Functions["count"]       = new Count();
     Functions["counta"]      = new CountA();
     Functions["countblank"]  = new CountBlank();
     Functions["countif"]     = new CountIf();
     Functions["countifs"]    = new CountIfs();
     Functions["fact"]        = new Fact();
     Functions["floor"]       = new Floor();
     Functions["sin"]         = new Sin();
     Functions["sinh"]        = new Sinh();
     Functions["sum"]         = new Sum();
     Functions["sumif"]       = new SumIf();
     Functions["sumifs"]      = new SumIfs();
     Functions["sumproduct"]  = new SumProduct();
     Functions["sumsq"]       = new Sumsq();
     Functions["stdev"]       = new Stdev();
     Functions["stdevp"]      = new StdevP();
     Functions["stdev.s"]     = new Stdev();
     Functions["stdev.p"]     = new StdevP();
     Functions["subtotal"]    = new Subtotal();
     Functions["exp"]         = new Exp();
     Functions["log"]         = new Log();
     Functions["log10"]       = new Log10();
     Functions["ln"]          = new Ln();
     Functions["max"]         = new Max();
     Functions["maxa"]        = new Maxa();
     Functions["median"]      = new Median();
     Functions["min"]         = new Min();
     Functions["mina"]        = new Mina();
     Functions["mod"]         = new Mod();
     Functions["average"]     = new Average();
     Functions["averagea"]    = new AverageA();
     Functions["averageif"]   = new AverageIf();
     Functions["averageifs"]  = new AverageIfs();
     Functions["round"]       = new Round();
     Functions["rounddown"]   = new Rounddown();
     Functions["roundup"]     = new Roundup();
     Functions["rand"]        = new Rand();
     Functions["randbetween"] = new RandBetween();
     Functions["rank"]        = new Rank();
     Functions["rank.eq"]     = new Rank();
     Functions["rank.avg"]    = new Rank(true);
     Functions["quotient"]    = new Quotient();
     Functions["trunc"]       = new Trunc();
     Functions["tan"]         = new Tan();
     Functions["tanh"]        = new Tanh();
     Functions["atan"]        = new Atan();
     Functions["atan2"]       = new Atan2();
     Functions["atanh"]       = new Atanh();
     Functions["acos"]        = new Acos();
     Functions["acosh"]       = new Acosh();
     Functions["var"]         = new Var();
     Functions["varp"]        = new VarP();
     Functions["large"]       = new Large();
     Functions["small"]       = new Small();
     Functions["degrees"]     = new Degrees();
     // Information
     Functions["isblank"]    = new IsBlank();
     Functions["isnumber"]   = new IsNumber();
     Functions["istext"]     = new IsText();
     Functions["isnontext"]  = new IsNonText();
     Functions["iserror"]    = new IsError();
     Functions["iserr"]      = new IsErr();
     Functions["error.type"] = new ErrorType();
     Functions["iseven"]     = new IsEven();
     Functions["isodd"]      = new IsOdd();
     Functions["islogical"]  = new IsLogical();
     Functions["isna"]       = new IsNa();
     Functions["na"]         = new Na();
     Functions["n"]          = new N();
     // Logical
     Functions["if"]      = new If();
     Functions["iferror"] = new IfError();
     Functions["ifna"]    = new IfNa();
     Functions["not"]     = new Not();
     Functions["and"]     = new And();
     Functions["or"]      = new Or();
     Functions["true"]    = new True();
     Functions["false"]   = new False();
     // Reference and lookup
     Functions["address"]  = new Address();
     Functions["hlookup"]  = new HLookup();
     Functions["vlookup"]  = new VLookup();
     Functions["lookup"]   = new Lookup();
     Functions["match"]    = new Match();
     Functions["row"]      = new Row();
     Functions["rows"]     = new Rows();
     Functions["column"]   = new Column();
     Functions["columns"]  = new Columns();
     Functions["choose"]   = new Choose();
     Functions["index"]    = new RefAndLookup.Index();
     Functions["indirect"] = new Indirect();
     Functions["offset"]   = new Offset();
     // Date
     Functions["date"]             = new Date();
     Functions["today"]            = new Today();
     Functions["now"]              = new Now();
     Functions["day"]              = new Day();
     Functions["month"]            = new Month();
     Functions["year"]             = new Year();
     Functions["time"]             = new Time();
     Functions["hour"]             = new Hour();
     Functions["minute"]           = new Minute();
     Functions["second"]           = new Second();
     Functions["weeknum"]          = new Weeknum();
     Functions["weekday"]          = new Weekday();
     Functions["days360"]          = new Days360();
     Functions["yearfrac"]         = new Yearfrac();
     Functions["edate"]            = new Edate();
     Functions["eomonth"]          = new Eomonth();
     Functions["isoweeknum"]       = new IsoWeekNum();
     Functions["workday"]          = new Workday();
     Functions["networkdays"]      = new Networkdays();
     Functions["networkdays.intl"] = new NetworkdaysIntl();
     Functions["datevalue"]        = new DateValue();
     Functions["timevalue"]        = new TimeValue();
     // Database
     Functions["dget"]     = new Dget();
     Functions["dcount"]   = new Dcount();
     Functions["dcounta"]  = new DcountA();
     Functions["dmax"]     = new Dmax();
     Functions["dmin"]     = new Dmin();
     Functions["dsum"]     = new Dsum();
     Functions["daverage"] = new Daverage();
     Functions["dvar"]     = new Dvar();
     Functions["dvarp"]    = new Dvarp();
     //Finance
     Functions["pmt"] = new Pmt();
 }
Ejemplo n.º 39
0
        protected void PerformStep(Clause c, Lit lit, out Clause newClause1, out Clause newClause2)
        {
            //List<Clause> ret = new List<Clause>();
            Term formula = lit.Atom;

            if (formula is Max)
            {
                Max m = (Max)formula;
                Lit l = new Lit(m.Left, Assignment.Unassigned, true);
                Lit r = new Lit(m.Right, Assignment.Unassigned, true);
                c.AddChecked(l);
                c.AddChecked(r);
                newClause1 = c;
                newClause2 = null;
                return;
            }
            if (formula is And)
            {
                And    m  = (And)formula;
                Lit    l  = new Lit(m.Left, Assignment.Unassigned, true);
                Lit    r  = new Lit(m.Right, Assignment.Unassigned, true);
                Clause c2 = c.Clone();
                c.AddChecked(l);
                c2.AddChecked(r);
                newClause1 = c;
                newClause2 = c2;
                return;
            }
            if (formula is Or)
            {
                Or  m = (Or)formula;
                Lit l = new Lit(m.Left, Assignment.Unassigned, true);
                Lit r = new Lit(m.Right, Assignment.Unassigned, true);
                c.AddChecked(l);
                c.AddChecked(r);
                newClause1 = c;
                newClause2 = null;
                return;
            }
            if (formula is Min)
            {
                Min    m  = (Min)formula;
                Lit    l  = new Lit(m.Left, Assignment.Unassigned, true);
                Lit    r  = new Lit(m.Right, Assignment.Unassigned, true);
                Clause c2 = c.Clone();
                c.AddChecked(l);
                c2.AddChecked(r);
                newClause1 = c;
                newClause2 = c2;
                return;
            }
            if (formula is LTConstraint)
            {
                lit.IsTemporary = false;
                lit.ComputeVariableCount();
                lit.Sign = Assignment.True;
                this.AtomOccurrence++;
                Var v = null;
#if USE_EXTENDED_EQUALITY
                if (this.TryGetVar(lit.Atom, out v))
                {
#else
                if (this.Atoms.TryGetValue(lit.Atom, out v))
                {
#endif
                    lit.Var = v;
                }
                else
                {
                    lit.Var      = solver.newVar();
                    lit.Var.Term = lit.Atom;
                    this.Atoms.Add(lit.Atom, lit.Var);
                }
                c.AddChecked(lit);
                newClause1 = c;
                newClause2 = null;
                return;
            }
            if (formula is LTEConstraint)
            {
                lit.IsTemporary = false;
                lit.ComputeVariableCount();
                lit.Sign = Assignment.False;
                this.AtomOccurrence++;
                Term p = ((LTEConstraint)formula).Negate();
                lit.Atom = p;
                Var v = null;
#if USE_EXTENDED_EQUALITY
                if (this.TryGetVar(p, out v))
                {
#else
                if (this.Atoms.TryGetValue(p, out v))
                {
#endif
                    lit.Var = v;
                }
                else
                {
                    lit.Var      = solver.newVar();
                    lit.Var.Term = p;
                    this.Atoms.Add(p, lit.Var);
                }
                c.AddChecked(lit);
                newClause1 = c;
                newClause2 = null;
                return;
            }
            if (formula is Constant)
            {
                if (((Constant)formula).Value <= 0.0)
                {
                    newClause1 = c;
                }
                else
                {
                    newClause1 = null;
                }
                newClause2 = null;
                return;
            }
            Console.Error.WriteLine("U C: {0}", formula);
            throw new Exception("Unknown constraint in transformation: " + formula);
        }
Ejemplo n.º 40
0
        protected internal virtual void create()
        {
            int  num  = this.string_0.Length;
            Unit unit = null;
            int  num2 = 0;

            while (this.int_0 < num)
            {
                char ch2 = this.string_0[this.int_0];
                if (char.IsWhiteSpace(ch2))
                {
                    goto Label_041D;
                }
                unit = null;
                char ch = ch2;
                switch (ch)
                {
                case '!':
                    this.int_0++;
                    if ((this.int_0 < num) && (this.string_0[this.int_0] == '='))
                    {
                        unit = new NotEquals();
                        this.int_0++;
                    }
                    if (unit == null)
                    {
                        unit = new Not();
                    }
                    goto Label_03B6;

                case '"':
                case '#':
                case '$':
                case '\'':
                case ';':
                    goto Label_02D1;

                case '%':
                    unit = new Mod();
                    this.int_0++;
                    goto Label_03B6;

                case '&':
                    this.int_0++;
                    if ((this.int_0 >= num) || (this.string_0[this.int_0] != '&'))
                    {
                        break;
                    }
                    unit = new And();
                    this.int_0++;
                    goto Label_03B6;

                case '(':
                    goto Label_02DD;

                case ')':
                    goto Label_02F4;

                case '*':
                    goto Label_0312;

                case '+':
                    goto Label_032B;

                case ',':
                    throw new ReportError(new StringBuilder("位置").Append(this.int_0).Append("不应该出现逗号").ToString().ToString());

                case '-':
                    goto Label_0341;

                case '.':
                    goto Label_0357;

                case '/':
                    unit = new Divide();
                    this.int_0++;
                    goto Label_03B6;

                case ':':
                    unit = new Link(this.cellExt1_0);
                    this.int_0++;
                    goto Label_03B6;

                case '<':
                    this.int_0++;
                    if ((this.int_0 < num) && (this.string_0[this.int_0] == '='))
                    {
                        unit = new NotGreater();
                        this.int_0++;
                    }
                    if (unit == null)
                    {
                        unit = new Smaller();
                    }
                    goto Label_03B6;

                case '=':
                    this.int_0++;
                    if ((this.int_0 < num) && (this.string_0[this.int_0] == '='))
                    {
                        this.int_0++;
                    }
                    unit = new Equals();
                    goto Label_03B6;

                case '>':
                    this.int_0++;
                    if ((this.int_0 < num) && (this.string_0[this.int_0] == '='))
                    {
                        unit = new NotSmaller();
                        this.int_0++;
                    }
                    if (unit == null)
                    {
                        unit = new Greater();
                    }
                    goto Label_03B6;

                default:
                    if (ch != '|')
                    {
                        goto Label_02D1;
                    }
                    this.int_0++;
                    if ((this.int_0 >= num) || (this.string_0[this.int_0] != '|'))
                    {
                        throw new ReportError("不能识别标识符|");
                    }
                    unit = new Or();
                    this.int_0++;
                    goto Label_03B6;
                }
                unit = LoadFunction.newFunction("address", this.env_0, this.cellExt1_0, this.dataSet_0);
                goto Label_03B6;
Label_02D1:
                unit = this.createNode();
                goto Label_03B6;
Label_02DD:
                num2++;
                this.int_0++;
                continue;
Label_02F4:
                if (--num2 < 0)
                {
                    throw new ReportError("括号不匹配,右括号太多!");
                }
                this.int_0++;
                continue;
Label_0312:
                unit = new Multiply();
                this.int_0++;
                goto Label_03B6;
Label_032B:
                unit = new Add();
                this.int_0++;
                goto Label_03B6;
Label_0341:
                unit = new Subtract();
                this.int_0++;
                goto Label_03B6;
Label_0357:
                if ((this.unit_1 != null) && !this.unit_1.Operator)
                {
                    unit = LoadFunction.newFunction("dsmember", this.env_0, this.cellExt1_0, this.dataSet_0);
                    this.int_0++;
                }
                else
                {
                    unit = this.createNode();
                }
Label_03B6:
                unit.InBrackets = num2;
                this.unit_1     = unit;
                if (this.unit_0 != null)
                {
                    Unit right = this.unit_0;
                    Unit unit2 = null;
                    while (right != null)
                    {
                        if (right.Priority >= unit.Priority)
                        {
                            break;
                        }
                        unit2 = right;
                        right = right.Right;
                    }
                    unit.Left = right;
                    if (unit2 == null)
                    {
                        this.unit_0 = unit;
                    }
                    else
                    {
                        unit2.Right = unit;
                    }
                    continue;
                }
                this.unit_0 = unit;
                continue;
Label_041D:
                this.int_0++;
            }
            if (num2 > 0)
            {
                throw new ReportError("括号不匹配,左括号太多!");
            }
        }
Ejemplo n.º 41
0
 public void Visit(And and)
 {
     and.Left.Accept(this);
     _sb.Append(" && ");
     and.Right.Accept(this);
 }
Ejemplo n.º 42
0
 public string Visit(And node) {
     return Visit((dynamic) node[0])
         + Visit((dynamic) node[1])
         + "\t\tand\n";               
 }
        //static private Dictionary<Pair<NEC, Hla>, bool> CloseHuman = null;

        //GeneratorType.Hla | GeneratorType.Position | GeneratorType.Property | GeneratorType.AndHla | GeneratorType.Zero6Supertype | GeneratorType.AndZero6Supertype
        private static Set <IHashableFeature> GenerateFeatureSet(
            object entity, string supertypeTableSource,
            int?flankSizeOrNull,
            bool includeFlankNECFeatures,
            bool includeChemicalProperties, bool includeAAFeatures,
            bool addEiFeatures
            )
        {
            bool includeAndHlaAndSTWithEpitopeAdjFeatures = false;
            bool subtractSupertypeFeatures         = false;
            bool subtractHlaFeatures               = false;
            bool substractChemAACrissCrossFeatures = false;


            SpecialFunctions.CheckCondition(!includeAndHlaAndSTWithEpitopeAdjFeatures || includeFlankNECFeatures);

            Pair <NEC, Hla> necAndHlaX = (Pair <NEC, Hla>)entity;
            NEC             nec        = (null == flankSizeOrNull) ? necAndHlaX.First : NEC.GetInstance(necAndHlaX.First, (int)flankSizeOrNull);
            Hla             hla        = necAndHlaX.Second;

            Debug.Assert(nec.N.Length == nec.C.Length); // real assert
            Pair <NEC, Hla> necAndHla = new Pair <NEC, Hla>(nec, hla);

            Set <IHashableFeature> hlaishFeatureSet = new Set <IHashableFeature>();

            CreateAndAddHlaFeature(subtractHlaFeatures, hla, necAndHla, ref hlaishFeatureSet);
            CreateAndAddFeatureSupertype(supertypeTableSource, subtractSupertypeFeatures, hla, necAndHla, ref hlaishFeatureSet, Assembly.GetExecutingAssembly(), Predictor.ResourceString);

            Set <IHashableFeature> featureSet = Set <IHashableFeature> .GetInstance(hlaishFeatureSet);

            if (addEiFeatures)
            {
                AddEiFeatures(includeChemicalProperties, includeAAFeatures, substractChemAACrissCrossFeatures, nec, necAndHla, hlaishFeatureSet, featureSet);
            }



            if (includeFlankNECFeatures)
            {
                List <IHashableFeature> aaInNFlankFeatureList = new List <IHashableFeature>(In.GetAASeqInRegionInstance(1, necAndHla, NFlank.GetInstance()));
                DebugCheckThatEvaluatesToTrue(necAndHla, aaInNFlankFeatureList);



                if (includeAAFeatures)
                {
                    featureSet.AddNewRange(aaInNFlankFeatureList);                                                    //AA in N flank
                    featureSet.AddNewRange(In.GetAASeqInRegionInstance(2, necAndHla, NFlank.GetInstance()));          //AA1-AA2 in Nflank
                    featureSet.AddNewRange(SubSeq.GetInSubSeqEnumeration(NFlank.GetInstance(), false, 1, necAndHla)); //AA@x in N flank (numbering is 5 4 3 2 1)
                    featureSet.AddNewRange(SubSeq.GetInSubSeqEnumeration(NFlank.GetInstance(), false, 2, necAndHla)); //AA1-AA2@x in Nflank (x is position of AA2, i.e., the smaller number)


                    featureSet.AddNewRange(In.GetAASeqInRegionInstance(1, necAndHla, CFlank.GetInstance()));         //AA in Cflank
                    featureSet.AddNewRange(In.GetAASeqInRegionInstance(2, necAndHla, CFlank.GetInstance()));         //AA1-AA2 in Cflank
                    featureSet.AddNewRange(SubSeq.GetInSubSeqEnumeration(CFlank.GetInstance(), true, 1, necAndHla)); //AA@x in C flank (numbering is 1 2 3 4 5)
                    featureSet.AddNewRange(SubSeq.GetInSubSeqEnumeration(CFlank.GetInstance(), true, 2, necAndHla)); //AA1-AA2@x in Cflank (x is position of AA1, i.e., the smaller number)
                }

                if (includeChemicalProperties)
                {
                    featureSet.AddNewOrOldRange(InProperty.GetPropertySeqInRegionInstance(1, necAndHla, NFlank.GetInstance()));
                    featureSet.AddNewOrOldRange(SubSeq.GetInPropertySubSeqEnumeration(NFlank.GetInstance(), false, 1, necAndHla));
                    featureSet.AddNewOrOldRange(InProperty.GetPropertySeqInRegionInstance(1, necAndHla, CFlank.GetInstance()));
                    featureSet.AddNewOrOldRange(SubSeq.GetInPropertySubSeqEnumeration(CFlank.GetInstance(), true, 1, necAndHla));
                    featureSet.AddNewOrOldRange(InProperty.GetPropertySeqInRegionInstance(2, necAndHla, NFlank.GetInstance()));
                    featureSet.AddNewOrOldRange(SubSeq.GetInPropertySubSeqEnumeration(NFlank.GetInstance(), false, 2, necAndHla));
                    featureSet.AddNewOrOldRange(InProperty.GetPropertySeqInRegionInstance(2, necAndHla, CFlank.GetInstance()));
                    featureSet.AddNewOrOldRange(SubSeq.GetInPropertySubSeqEnumeration(CFlank.GetInstance(), true, 2, necAndHla));
                }
            }
            if (includeFlankNECFeatures)
            {
                if (includeAAFeatures)
                {
                    //EV in Epitope
                    AddFeatureWithOptionalAndHlaAndST(In.GetAASeqInRegionInstance(2, necAndHla, Epitope.GetInstance()), includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, false, ref featureSet);//AA1-AA2 in Epitope

                    //RR in Epitope[@1-2]
                    AddFeatureWithOptionalAndHlaAndST(SubSeq.GetInSubSeqEnumeration(Epitope.GetInstance(), true, 2, necAndHla), includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, false, ref featureSet);//AA1-AA2@x in Epitope (x is position of AA1, i.e., the smaller number)
                }
                if (includeChemicalProperties)
                {
                    //polar,cyclic in Epitope
                    AddFeatureWithOptionalAndHlaAndST(InProperty.GetPropertySeqInRegionInstance(2, necAndHla, Epitope.GetInstance()), includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, false, ref featureSet);
                    //polar,large in Epitope[@8-9]
                    AddFeatureWithOptionalAndHlaAndST(SubSeq.GetInPropertySubSeqEnumeration(Epitope.GetInstance(), true, 2, necAndHla), includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, false, ref featureSet);
                }

                //AA1-AA2 in Nflank,Epitope, etc
                if (null != flankSizeOrNull && (int)flankSizeOrNull > 0)
                {
                    string epitope = (string)Epitope.GetInstance().Evaluate(entity);

                    SubSeq lastNAAFeature = SubSeq.GetInstance(1, 1, false, NFlank.GetInstance());
                    string lastNAA        = (string)lastNAAFeature.Evaluate(entity);
                    In     inLastNAA      = In.GetInstance(lastNAA, lastNAAFeature);

                    SubSeq firstEAAFeature = SubSeq.GetInstance(1, 1, true, Epitope.GetInstance());
                    string firstEAA        = (string)firstEAAFeature.Evaluate(entity);
                    Debug.Assert(firstEAA == epitope.Substring(0, 1));// real assert
                    In inFirstEAA = In.GetInstance(firstEAA, firstEAAFeature);

                    SubSeq lastEAAFeature = SubSeq.GetInstance(epitope.Length, epitope.Length, true, Epitope.GetInstance());
                    string lastEAA        = (string)lastEAAFeature.Evaluate(entity);
                    In     inLastEAA      = In.GetInstance(lastEAA, lastEAAFeature);

                    SubSeq firstCAAFeature = SubSeq.GetInstance(1, 1, true, CFlank.GetInstance());
                    string firstCAA        = (string)firstCAAFeature.Evaluate(entity);
                    In     inFirstCAA      = In.GetInstance(firstCAA, firstCAAFeature);

                    if (includeAAFeatures)
                    {
                        And andLastNNAAFirstEAA = And.GetInstance(inLastNAA, inFirstEAA);
                        AddFeatureWithOptionalAndHlaAndST(andLastNNAAFirstEAA, includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, /*checkThatNew*/ true, ref featureSet);

                        And andLastEAAFirstCAA = And.GetInstance(inLastEAA, inFirstCAA);
                        AddFeatureWithOptionalAndHlaAndST(andLastEAAFirstCAA, includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, /*checkThatNew*/ true, ref featureSet);
                    }

                    if (includeChemicalProperties)
                    {
                        foreach (string lastNProperty in KmerProperties.AaToPropList[Biology.GetInstance().OneLetterAminoAcidAbbrevTo3Letter[lastNAA[0]]])
                        {
                            InProperty inLastNProperty = InProperty.GetInstance(lastNProperty, lastNAAFeature);

                            foreach (string firstEProperty in KmerProperties.AaToPropList[Biology.GetInstance().OneLetterAminoAcidAbbrevTo3Letter[firstEAA[0]]])
                            {
                                InProperty inFirstEProperty = InProperty.GetInstance(firstEProperty, firstEAAFeature); //!!!get this out of the loop?
                                And        andLastNPropertyFirstEProperty = And.GetInstance(inLastNProperty, inFirstEProperty);
                                AddFeatureWithOptionalAndHlaAndST(andLastNPropertyFirstEProperty, includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, /*checkThatNew*/ false, ref featureSet);
                                Debug.Assert((bool)andLastNPropertyFirstEProperty.Evaluate(necAndHla));
                            }
                        }
                        foreach (string lastEProperty in KmerProperties.AaToPropList[Biology.GetInstance().OneLetterAminoAcidAbbrevTo3Letter[lastEAA[0]]])
                        {
                            InProperty inlastEProperty = InProperty.GetInstance(lastEProperty, lastEAAFeature);

                            foreach (string firstCProperty in KmerProperties.AaToPropList[Biology.GetInstance().OneLetterAminoAcidAbbrevTo3Letter[firstCAA[0]]])
                            {
                                InProperty infirstCProperty = InProperty.GetInstance(firstCProperty, firstCAAFeature); //!!!get this out of the loop?
                                And        andlastEPropertyfirstCProperty = And.GetInstance(inlastEProperty, infirstCProperty);
                                AddFeatureWithOptionalAndHlaAndST(andlastEPropertyfirstCProperty, includeAndHlaAndSTWithEpitopeAdjFeatures, hlaishFeatureSet, /*checkThatNew*/ false, ref featureSet);
                                Debug.Assert((bool)andlastEPropertyfirstCProperty.Evaluate(necAndHla));
                            }
                        }
                    }
                }
            }

            return(featureSet);
        }
Ejemplo n.º 44
0
        public double Execute(Operation operation,
                              IFunctionRegistry functionRegistry,
                              IConstantRegistry constantRegistry,
                              IDictionary <string, double> variables)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Variable variable = (Variable)operation;

                double value;
                bool   variableFound = variables.TryGetValue(variable.Name, out value);

                if (variableFound)
                {
                    return(value);
                }
                else
                {
                    throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                }
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                return(Execute(multiplication.Argument1, functionRegistry, constantRegistry, variables) * Execute(multiplication.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) + Execute(addition.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition = (Subtraction)operation;
                return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) - Execute(addition.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) / Execute(division.Divisor, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo division = (Modulo)operation;
                return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) % Execute(division.Divisor, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentiation = (Exponentiation)operation;
                return(Math.Pow(Execute(exponentiation.Base, functionRegistry, constantRegistry, variables), Execute(exponentiation.Exponent, functionRegistry, constantRegistry, variables)));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                return(-Execute(unaryMinus.Argument, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(And))
            {
                And and        = (And)operation;
                var operation1 = Execute(and.Argument1, functionRegistry, constantRegistry, variables) != 0;
                var operation2 = Execute(and.Argument2, functionRegistry, constantRegistry, variables) != 0;

                return((operation1 && operation2) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Or))
            {
                Or  or         = (Or)operation;
                var operation1 = Execute(or.Argument1, functionRegistry, constantRegistry, variables) != 0;
                var operation2 = Execute(or.Argument2, functionRegistry, constantRegistry, variables) != 0;

                return((operation1 || operation2) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan lessThan = (LessThan)operation;
                return((Execute(lessThan.Argument1, functionRegistry, constantRegistry, variables) < Execute(lessThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;
                return((Execute(lessOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) <= Execute(lessOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;
                return((Execute(greaterThan.Argument1, functionRegistry, constantRegistry, variables) > Execute(greaterThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;
                return((Execute(greaterOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) >= Execute(greaterOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal equal = (Equal)operation;
                return((Execute(equal.Argument1, functionRegistry, constantRegistry, variables) == Execute(equal.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual notEqual = (NotEqual)operation;
                return((Execute(notEqual.Argument1, functionRegistry, constantRegistry, variables) != Execute(notEqual.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);

                double[] arguments = new double[functionInfo.IsDynamicFunc ? function.Arguments.Count : functionInfo.NumberOfParameters];
                for (int i = 0; i < arguments.Length; i++)
                {
                    arguments[i] = Execute(function.Arguments[i], functionRegistry, constantRegistry, variables);
                }

                return(Invoke(functionInfo.Function, arguments));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
Ejemplo n.º 45
0
 private static Function[] ProduceFunctions()
 {
     Function[] retval = new Function[368];
     retval[0]                        = new Count();                            // COUNT
     retval[FunctionID.IF]            = new If();                               // IF
     retval[2]                        = LogicalFunction.ISNA;                   // IsNA
     retval[3]                        = LogicalFunction.ISERROR;                // IsERROR
     retval[FunctionID.SUM]           = AggregateFunction.SUM;                  // SUM
     retval[5]                        = AggregateFunction.AVERAGE;              // AVERAGE
     retval[6]                        = AggregateFunction.MIN;                  // MIN
     retval[7]                        = AggregateFunction.MAX;                  // MAX
     retval[8]                        = new Row();                              // ROW
     retval[9]                        = new Column();                           // COLUMN
     retval[10]                       = new Na();                               // NA
     retval[11]                       = new Npv();                              // NPV
     retval[12]                       = AggregateFunction.STDEV;                // STDEV
     retval[13]                       = NumericFunction.DOLLAR;                 // DOLLAR
     retval[14]                       = new NotImplementedFunction("FIXED");    // FIXED
     retval[15]                       = NumericFunction.SIN;                    // SIN
     retval[16]                       = NumericFunction.COS;                    // COS
     retval[17]                       = NumericFunction.TAN;                    // TAN
     retval[18]                       = NumericFunction.ATAN;                   // ATAN
     retval[19]                       = new Pi();                               // PI
     retval[20]                       = NumericFunction.SQRT;                   // SQRT
     retval[21]                       = NumericFunction.EXP;                    // EXP
     retval[22]                       = NumericFunction.LN;                     // LN
     retval[23]                       = NumericFunction.LOG10;                  // LOG10
     retval[24]                       = NumericFunction.ABS;                    // ABS
     retval[25]                       = NumericFunction.INT;                    // INT
     retval[26]                       = NumericFunction.SIGN;                   // SIGN
     retval[27]                       = NumericFunction.ROUND;                  // ROUND
     retval[28]                       = new Lookup();                           // LOOKUP
     retval[29]                       = new Index();                            // INDEX
     retval[30]                       = new NotImplementedFunction("REPT");     // REPT
     retval[31]                       = TextFunction.MID;                       // MID
     retval[32]                       = TextFunction.LEN;                       // LEN
     retval[33]                       = new Value();                            // VALUE
     retval[34]                       = new True();                             // TRUE
     retval[35]                       = new False();                            // FALSE
     retval[36]                       = new And();                              // AND
     retval[37]                       = new Or();                               // OR
     retval[38]                       = new Not();                              // NOT
     retval[39]                       = NumericFunction.MOD;                    // MOD
     retval[40]                       = new NotImplementedFunction("DCOUNT");   // DCOUNT
     retval[41]                       = new NotImplementedFunction("DSUM");     // DSUM
     retval[42]                       = new NotImplementedFunction("DAVERAGE"); // DAVERAGE
     retval[43]                       = new NotImplementedFunction("DMIN");     // DMIN
     retval[44]                       = new NotImplementedFunction("DMAX");     // DMAX
     retval[45]                       = new NotImplementedFunction("DSTDEV");   // DSTDEV
     retval[46]                       = AggregateFunction.VAR;                  // VAR
     retval[47]                       = new NotImplementedFunction("DVAR");     // DVAR
     retval[48]                       = TextFunction.TEXT;                      // TEXT
     retval[49]                       = new NotImplementedFunction("LINEST");   // LINEST
     retval[50]                       = new NotImplementedFunction("TREND");    // TREND
     retval[51]                       = new NotImplementedFunction("LOGEST");   // LOGEST
     retval[52]                       = new NotImplementedFunction("GROWTH");   // GROWTH
     retval[53]                       = new NotImplementedFunction("GOTO");     // GOTO
     retval[54]                       = new NotImplementedFunction("HALT");     // HALT
     retval[56]                       = FinanceFunction.PV;                     // PV
     retval[57]                       = FinanceFunction.FV;                     // FV
     retval[58]                       = FinanceFunction.NPER;                   // NPER
     retval[59]                       = FinanceFunction.PMT;                    // PMT
     retval[60]                       = new Rate();                             // RATE
     retval[61]                       = new NotImplementedFunction("MIRR");     // MIRR
     retval[62]                       = new Irr();                              // IRR
     retval[63]                       = new Rand();                             // RAND
     retval[64]                       = new Match();                            // MATCH
     retval[65]                       = DateFunc.instance;                      // DATE
     retval[66]                       = new TimeFunc();                         // TIME
     retval[67]                       = CalendarFieldFunction.DAY;              // DAY
     retval[68]                       = CalendarFieldFunction.MONTH;            // MONTH
     retval[69]                       = CalendarFieldFunction.YEAR;             // YEAR
     retval[70]                       = WeekdayFunc.instance;                   // WEEKDAY
     retval[71]                       = CalendarFieldFunction.HOUR;
     retval[72]                       = CalendarFieldFunction.MINUTE;
     retval[73]                       = CalendarFieldFunction.SECOND;
     retval[74]                       = new Now();
     retval[75]                       = new NotImplementedFunction("AREAS");          // AREAS
     retval[76]                       = new Rows();                                   // ROWS
     retval[77]                       = new Columns();                                // COLUMNS
     retval[FunctionID.OFFSET]        = new Offset();                                 // Offset.Evaluate has a different signature
     retval[79]                       = new NotImplementedFunction("ABSREF");         // ABSREF
     retval[80]                       = new NotImplementedFunction("RELREF");         // RELREF
     retval[81]                       = new NotImplementedFunction("ARGUMENT");       // ARGUMENT
     retval[82]                       = TextFunction.SEARCH;
     retval[83]                       = new NotImplementedFunction("TRANSPOSE");      // TRANSPOSE
     retval[84]                       = new NotImplementedFunction("ERROR");          // ERROR
     retval[85]                       = new NotImplementedFunction("STEP");           // STEP
     retval[86]                       = new NotImplementedFunction("TYPE");           // TYPE
     retval[87]                       = new NotImplementedFunction("ECHO");           // ECHO
     retval[88]                       = new NotImplementedFunction("SetNAME");        // SetNAME
     retval[89]                       = new NotImplementedFunction("CALLER");         // CALLER
     retval[90]                       = new NotImplementedFunction("DEREF");          // DEREF
     retval[91]                       = new NotImplementedFunction("WINDOWS");        // WINDOWS
     retval[92]                       = new NotImplementedFunction("SERIES");         // SERIES
     retval[93]                       = new NotImplementedFunction("DOCUMENTS");      // DOCUMENTS
     retval[94]                       = new NotImplementedFunction("ACTIVECELL");     // ACTIVECELL
     retval[95]                       = new NotImplementedFunction("SELECTION");      // SELECTION
     retval[96]                       = new NotImplementedFunction("RESULT");         // RESULT
     retval[97]                       = NumericFunction.ATAN2;                        // ATAN2
     retval[98]                       = NumericFunction.ASIN;                         // ASIN
     retval[99]                       = NumericFunction.ACOS;                         // ACOS
     retval[FunctionID.CHOOSE]        = new Choose();
     retval[101]                      = new Hlookup();                                // HLOOKUP
     retval[102]                      = new Vlookup();                                // VLOOKUP
     retval[103]                      = new NotImplementedFunction("LINKS");          // LINKS
     retval[104]                      = new NotImplementedFunction("INPUT");          // INPUT
     retval[105]                      = LogicalFunction.ISREF;                        // IsREF
     retval[106]                      = new NotImplementedFunction("GetFORMULA");     // GetFORMULA
     retval[107]                      = new NotImplementedFunction("GetNAME");        // GetNAME
     retval[108]                      = new NotImplementedFunction("SetVALUE");       // SetVALUE
     retval[109]                      = NumericFunction.LOG;                          // LOG
     retval[110]                      = new NotImplementedFunction("EXEC");           // EXEC
     retval[111]                      = TextFunction.CHAR;                            // CHAR
     retval[112]                      = TextFunction.LOWER;                           // LOWER
     retval[113]                      = TextFunction.UPPER;                           // UPPER
     retval[114]                      = new NotImplementedFunction("PROPER");         // PROPER
     retval[115]                      = TextFunction.LEFT;                            // LEFT
     retval[116]                      = TextFunction.RIGHT;                           // RIGHT
     retval[117]                      = TextFunction.EXACT;                           // EXACT
     retval[118]                      = TextFunction.TRIM;                            // TRIM
     retval[119]                      = new Replace();                                // Replace
     retval[120]                      = new Substitute();                             // SUBSTITUTE
     retval[121]                      = new NotImplementedFunction("CODE");           // CODE
     retval[122]                      = new NotImplementedFunction("NAMES");          // NAMES
     retval[123]                      = new NotImplementedFunction("DIRECTORY");      // DIRECTORY
     retval[124]                      = TextFunction.FIND;                            // Find
     retval[125]                      = new NotImplementedFunction("CELL");           // CELL
     retval[126]                      = LogicalFunction.ISERR;                        // IsERR
     retval[127]                      = LogicalFunction.ISTEXT;                       // IsTEXT
     retval[128]                      = LogicalFunction.ISNUMBER;                     // IsNUMBER
     retval[129]                      = LogicalFunction.ISBLANK;                      // IsBLANK
     retval[130]                      = new T();                                      // T
     retval[131]                      = new NotImplementedFunction("N");              // N
     retval[132]                      = new NotImplementedFunction("FOPEN");          // FOPEN
     retval[133]                      = new NotImplementedFunction("FCLOSE");         // FCLOSE
     retval[134]                      = new NotImplementedFunction("FSIZE");          // FSIZE
     retval[135]                      = new NotImplementedFunction("FReadLN");        // FReadLN
     retval[136]                      = new NotImplementedFunction("FRead");          // FRead
     retval[137]                      = new NotImplementedFunction("FWriteLN");       // FWriteLN
     retval[138]                      = new NotImplementedFunction("FWrite");         // FWrite
     retval[139]                      = new NotImplementedFunction("FPOS");           // FPOS
     retval[140]                      = new NotImplementedFunction("DATEVALUE");      // DATEVALUE
     retval[141]                      = new NotImplementedFunction("TIMEVALUE");      // TIMEVALUE
     retval[142]                      = new NotImplementedFunction("SLN");            // SLN
     retval[143]                      = new NotImplementedFunction("SYD");            // SYD
     retval[144]                      = new NotImplementedFunction("DDB");            // DDB
     retval[145]                      = new NotImplementedFunction("GetDEF");         // GetDEF
     retval[146]                      = new NotImplementedFunction("REFTEXT");        // REFTEXT
     retval[147]                      = new NotImplementedFunction("TEXTREF");        // TEXTREF
     retval[FunctionID.INDIRECT]      = null;                                         // Indirect.Evaluate has different signature
     retval[149]                      = new NotImplementedFunction("REGISTER");       // REGISTER
     retval[150]                      = new NotImplementedFunction("CALL");           // CALL
     retval[151]                      = new NotImplementedFunction("AddBAR");         // AddBAR
     retval[152]                      = new NotImplementedFunction("AddMENU");        // AddMENU
     retval[153]                      = new NotImplementedFunction("AddCOMMAND");     // AddCOMMAND
     retval[154]                      = new NotImplementedFunction("ENABLECOMMAND");  // ENABLECOMMAND
     retval[155]                      = new NotImplementedFunction("CHECKCOMMAND");   // CHECKCOMMAND
     retval[156]                      = new NotImplementedFunction("RenameCOMMAND");  // RenameCOMMAND
     retval[157]                      = new NotImplementedFunction("SHOWBAR");        // SHOWBAR
     retval[158]                      = new NotImplementedFunction("DELETEMENU");     // DELETEMENU
     retval[159]                      = new NotImplementedFunction("DELETECOMMAND");  // DELETECOMMAND
     retval[160]                      = new NotImplementedFunction("GetCHARTITEM");   // GetCHARTITEM
     retval[161]                      = new NotImplementedFunction("DIALOGBOX");      // DIALOGBOX
     retval[162]                      = TextFunction.CLEAN;                           // CLEAN
     retval[163]                      = new NotImplementedFunction("MDETERM");        // MDETERM
     retval[164]                      = new NotImplementedFunction("MINVERSE");       // MINVERSE
     retval[165]                      = new NotImplementedFunction("MMULT");          // MMULT
     retval[166]                      = new NotImplementedFunction("FILES");          // FILES
     retval[167]                      = new NotImplementedFunction("IPMT");           // IPMT
     retval[168]                      = new NotImplementedFunction("PPMT");           // PPMT
     retval[169]                      = new Counta();                                 // COUNTA
     retval[170]                      = new NotImplementedFunction("CANCELKEY");      // CANCELKEY
     retval[175]                      = new NotImplementedFunction("INITIATE");       // INITIATE
     retval[176]                      = new NotImplementedFunction("REQUEST");        // REQUEST
     retval[177]                      = new NotImplementedFunction("POKE");           // POKE
     retval[178]                      = new NotImplementedFunction("EXECUTE");        // EXECUTE
     retval[179]                      = new NotImplementedFunction("TERMINATE");      // TERMINATE
     retval[180]                      = new NotImplementedFunction("RESTART");        // RESTART
     retval[181]                      = new NotImplementedFunction("HELP");           // HELP
     retval[182]                      = new NotImplementedFunction("GetBAR");         // GetBAR
     retval[183]                      = AggregateFunction.PRODUCT;                    // PRODUCT
     retval[184]                      = NumericFunction.FACT;                         // FACT
     retval[185]                      = new NotImplementedFunction("GetCELL");        // GetCELL
     retval[186]                      = new NotImplementedFunction("GetWORKSPACE");   // GetWORKSPACE
     retval[187]                      = new NotImplementedFunction("GetWINDOW");      // GetWINDOW
     retval[188]                      = new NotImplementedFunction("GetDOCUMENT");    // GetDOCUMENT
     retval[189]                      = new NotImplementedFunction("DPRODUCT");       // DPRODUCT
     retval[190]                      = LogicalFunction.ISNONTEXT;                    // IsNONTEXT
     retval[191]                      = new NotImplementedFunction("GetNOTE");        // GetNOTE
     retval[192]                      = new NotImplementedFunction("NOTE");           // NOTE
     retval[193]                      = new NotImplementedFunction("STDEVP");         // STDEVP
     retval[194]                      = AggregateFunction.VARP;                       // VARP
     retval[195]                      = new NotImplementedFunction("DSTDEVP");        // DSTDEVP
     retval[196]                      = new NotImplementedFunction("DVARP");          // DVARP
     retval[197]                      = NumericFunction.TRUNC;                        // TRUNC
     retval[198]                      = LogicalFunction.ISLOGICAL;                    // IsLOGICAL
     retval[199]                      = new NotImplementedFunction("DCOUNTA");        // DCOUNTA
     retval[200]                      = new NotImplementedFunction("DELETEBAR");      // DELETEBAR
     retval[201]                      = new NotImplementedFunction("UNREGISTER");     // UNREGISTER
     retval[204]                      = new NotImplementedFunction("USDOLLAR");       // USDOLLAR
     retval[205]                      = new NotImplementedFunction("FindB");          // FindB
     retval[206]                      = new NotImplementedFunction("SEARCHB");        // SEARCHB
     retval[207]                      = new NotImplementedFunction("ReplaceB");       // ReplaceB
     retval[208]                      = new NotImplementedFunction("LEFTB");          // LEFTB
     retval[209]                      = new NotImplementedFunction("RIGHTB");         // RIGHTB
     retval[210]                      = new NotImplementedFunction("MIDB");           // MIDB
     retval[211]                      = new NotImplementedFunction("LENB");           // LENB
     retval[212]                      = NumericFunction.ROUNDUP;                      // ROUNDUP
     retval[213]                      = NumericFunction.ROUNDDOWN;                    // ROUNDDOWN
     retval[214]                      = new NotImplementedFunction("ASC");            // ASC
     retval[215]                      = new NotImplementedFunction("DBCS");           // DBCS
     retval[216]                      = new Rank();                                   // RANK
     retval[219]                      = new Address();                                // AddRESS
     retval[220]                      = new Days360();                                // DAYS360
     retval[221]                      = new Today();                                  // TODAY
     retval[222]                      = new NotImplementedFunction("VDB");            // VDB
     retval[227]                      = AggregateFunction.MEDIAN;                     // MEDIAN
     retval[228]                      = new Sumproduct();                             // SUMPRODUCT
     retval[229]                      = NumericFunction.SINH;                         // SINH
     retval[230]                      = NumericFunction.COSH;                         // COSH
     retval[231]                      = NumericFunction.TANH;                         // TANH
     retval[232]                      = NumericFunction.ASINH;                        // ASINH
     retval[233]                      = NumericFunction.ACOSH;                        // ACOSH
     retval[234]                      = NumericFunction.ATANH;                        // ATANH
     retval[235]                      = new NotImplementedFunction("DGet");           // DGet
     retval[236]                      = new NotImplementedFunction("CreateOBJECT");   // CreateOBJECT
     retval[237]                      = new NotImplementedFunction("VOLATILE");       // VOLATILE
     retval[238]                      = new NotImplementedFunction("LASTERROR");      // LASTERROR
     retval[239]                      = new NotImplementedFunction("CUSTOMUNDO");     // CUSTOMUNDO
     retval[240]                      = new NotImplementedFunction("CUSTOMREPEAT");   // CUSTOMREPEAT
     retval[241]                      = new NotImplementedFunction("FORMULAConvert"); // FORMULAConvert
     retval[242]                      = new NotImplementedFunction("GetLINKINFO");    // GetLINKINFO
     retval[243]                      = new NotImplementedFunction("TEXTBOX");        // TEXTBOX
     retval[244]                      = new NotImplementedFunction("INFO");           // INFO
     retval[245]                      = new NotImplementedFunction("GROUP");          // GROUP
     retval[246]                      = new NotImplementedFunction("GetOBJECT");      // GetOBJECT
     retval[247]                      = new NotImplementedFunction("DB");             // DB
     retval[248]                      = new NotImplementedFunction("PAUSE");          // PAUSE
     retval[250]                      = new NotImplementedFunction("RESUME");         // RESUME
     retval[252]                      = new NotImplementedFunction("FREQUENCY");      // FREQUENCY
     retval[253]                      = new NotImplementedFunction("AddTOOLBAR");     // AddTOOLBAR
     retval[254]                      = new NotImplementedFunction("DELETETOOLBAR");  // DELETETOOLBAR
     retval[FunctionID.EXTERNAL_FUNC] = null;                                         // ExternalFunction is a FreeREfFunction
     retval[256]                      = new NotImplementedFunction("RESetTOOLBAR");   // RESetTOOLBAR
     retval[257]                      = new NotImplementedFunction("EVALUATE");       // EVALUATE
     retval[258]                      = new NotImplementedFunction("GetTOOLBAR");     // GetTOOLBAR
     retval[259]                      = new NotImplementedFunction("GetTOOL");        // GetTOOL
     retval[260]                      = new NotImplementedFunction("SPELLINGCHECK");  // SPELLINGCHECK
     retval[261]                      = new Errortype();                              // ERRORTYPE
     retval[262]                      = new NotImplementedFunction("APPTITLE");       // APPTITLE
     retval[263]                      = new NotImplementedFunction("WINDOWTITLE");    // WINDOWTITLE
     retval[264]                      = new NotImplementedFunction("SAVETOOLBAR");    // SAVETOOLBAR
     retval[265]                      = new NotImplementedFunction("ENABLETOOL");     // ENABLETOOL
     retval[266]                      = new NotImplementedFunction("PRESSTOOL");      // PRESSTOOL
     retval[267]                      = new NotImplementedFunction("REGISTERID");     // REGISTERID
     retval[268]                      = new NotImplementedFunction("GetWORKBOOK");    // GetWORKBOOK
     retval[269]                      = AggregateFunction.AVEDEV;                     // AVEDEV
     retval[270]                      = new NotImplementedFunction("BETADIST");       // BETADIST
     retval[271]                      = new NotImplementedFunction("GAMMALN");        // GAMMALN
     retval[272]                      = new NotImplementedFunction("BETAINV");        // BETAINV
     retval[273]                      = new NotImplementedFunction("BINOMDIST");      // BINOMDIST
     retval[274]                      = new NotImplementedFunction("CHIDIST");        // CHIDIST
     retval[275]                      = new NotImplementedFunction("CHIINV");         // CHIINV
     retval[276]                      = NumericFunction.COMBIN;                       // COMBIN
     retval[277]                      = new NotImplementedFunction("CONFIDENCE");     // CONFIDENCE
     retval[278]                      = new NotImplementedFunction("CRITBINOM");      // CRITBINOM
     retval[279]                      = new Even();                                   // EVEN
     retval[280]                      = new NotImplementedFunction("EXPONDIST");      // EXPONDIST
     retval[281]                      = new NotImplementedFunction("FDIST");          // FDIST
     retval[282]                      = new NotImplementedFunction("FINV");           // FINV
     retval[283]                      = new NotImplementedFunction("FISHER");         // FISHER
     retval[284]                      = new NotImplementedFunction("FISHERINV");      // FISHERINV
     retval[285]                      = NumericFunction.FLOOR;                        // FLOOR
     retval[286]                      = new NotImplementedFunction("GAMMADIST");      // GAMMADIST
     retval[287]                      = new NotImplementedFunction("GAMMAINV");       // GAMMAINV
     retval[288]                      = NumericFunction.CEILING;                      // CEILING
     retval[289]                      = new NotImplementedFunction("HYPGEOMDIST");    // HYPGEOMDIST
     retval[290]                      = new NotImplementedFunction("LOGNORMDIST");    // LOGNORMDIST
     retval[291]                      = new NotImplementedFunction("LOGINV");         // LOGINV
     retval[292]                      = new NotImplementedFunction("NEGBINOMDIST");   // NEGBINOMDIST
     retval[293]                      = new NotImplementedFunction("NORMDIST");       // NORMDIST
     retval[294]                      = new NotImplementedFunction("NORMSDIST");      // NORMSDIST
     retval[295]                      = new NotImplementedFunction("NORMINV");        // NORMINV
     retval[296]                      = new NotImplementedFunction("NORMSINV");       // NORMSINV
     retval[297]                      = new NotImplementedFunction("STANDARDIZE");    // STANDARDIZE
     retval[298]                      = new Odd();                                    // ODD
     retval[299]                      = new NotImplementedFunction("PERMUT");         // PERMUT
     retval[300]                      = NumericFunction.POISSON;                      // POISSON
     retval[301]                      = new NotImplementedFunction("TDIST");          // TDIST
     retval[302]                      = new NotImplementedFunction("WEIBULL");        // WEIBULL
     retval[303]                      = new Sumxmy2();                                // SUMXMY2
     retval[304]                      = new Sumx2my2();                               // SUMX2MY2
     retval[305]                      = new Sumx2py2();                               // SUMX2PY2
     retval[306]                      = new NotImplementedFunction("CHITEST");        // CHITEST
     retval[307]                      = new NotImplementedFunction("CORREL");         // CORREL
     retval[308]                      = new NotImplementedFunction("COVAR");          // COVAR
     retval[309]                      = new NotImplementedFunction("FORECAST");       // FORECAST
     retval[310]                      = new NotImplementedFunction("FTEST");          // FTEST
     retval[311]                      = new NotImplementedFunction("INTERCEPT");      // INTERCEPT
     retval[312]                      = new NotImplementedFunction("PEARSON");        // PEARSON
     retval[313]                      = new NotImplementedFunction("RSQ");            // RSQ
     retval[314]                      = new NotImplementedFunction("STEYX");          // STEYX
     retval[315]                      = new NotImplementedFunction("SLOPE");          // SLOPE
     retval[316]                      = new NotImplementedFunction("TTEST");          // TTEST
     retval[317]                      = new NotImplementedFunction("PROB");           // PROB
     retval[318]                      = AggregateFunction.DEVSQ;                      // DEVSQ
     retval[319]                      = new NotImplementedFunction("GEOMEAN");        // GEOMEAN
     retval[320]                      = new NotImplementedFunction("HARMEAN");        // HARMEAN
     retval[321]                      = AggregateFunction.SUMSQ;                      // SUMSQ
     retval[322]                      = new NotImplementedFunction("KURT");           // KURT
     retval[323]                      = new NotImplementedFunction("SKEW");           // SKEW
     retval[324]                      = new NotImplementedFunction("ZTEST");          // ZTEST
     retval[325]                      = AggregateFunction.LARGE;                      // LARGE
     retval[326]                      = AggregateFunction.SMALL;                      // SMALL
     retval[327]                      = new NotImplementedFunction("QUARTILE");       // QUARTILE
     retval[328]                      = new NotImplementedFunction("PERCENTILE");     // PERCENTILE
     retval[329]                      = new NotImplementedFunction("PERCENTRANK");    // PERCENTRANK
     retval[330]                      = new Mode();                                   // MODE
     retval[331]                      = new NotImplementedFunction("TRIMMEAN");       // TRIMMEAN
     retval[332]                      = new NotImplementedFunction("TINV");           // TINV
     retval[334]                      = new NotImplementedFunction("MOVIECOMMAND");   // MOVIECOMMAND
     retval[335]                      = new NotImplementedFunction("GetMOVIE");       // GetMOVIE
     retval[336]                      = TextFunction.CONCATENATE;                     // CONCATENATE
     retval[337]                      = NumericFunction.POWER;                        // POWER
     retval[338]                      = new NotImplementedFunction("PIVOTAddDATA");   // PIVOTAddDATA
     retval[339]                      = new NotImplementedFunction("GetPIVOTTABLE");  // GetPIVOTTABLE
     retval[340]                      = new NotImplementedFunction("GetPIVOTFIELD");  // GetPIVOTFIELD
     retval[341]                      = new NotImplementedFunction("GetPIVOTITEM");   // GetPIVOTITEM
     retval[342]                      = NumericFunction.RADIANS;
     ;                                                                                // RADIANS
     retval[343] = NumericFunction.DEGREES;                                           // DEGREES
     retval[344] = new Subtotal();                                                    // SUBTOTAL
     retval[345] = new Sumif();                                                       // SUMIF
     retval[346] = new Countif();                                                     // COUNTIF
     retval[347] = new Countblank();                                                  // COUNTBLANK
     retval[348] = new NotImplementedFunction("SCENARIOGet");                         // SCENARIOGet
     retval[349] = new NotImplementedFunction("OPTIONSLISTSGet");                     // OPTIONSLISTSGet
     retval[350] = new NotImplementedFunction("IsPMT");                               // IsPMT
     retval[351] = new NotImplementedFunction("DATEDIF");                             // DATEDIF
     retval[352] = new NotImplementedFunction("DATESTRING");                          // DATESTRING
     retval[353] = new NotImplementedFunction("NUMBERSTRING");                        // NUMBERSTRING
     retval[354] = new NotImplementedFunction("ROMAN");                               // ROMAN
     retval[355] = new NotImplementedFunction("OPENDIALOG");                          // OPENDIALOG
     retval[356] = new NotImplementedFunction("SAVEDIALOG");                          // SAVEDIALOG
     retval[357] = new NotImplementedFunction("VIEWGet");                             // VIEWGet
     retval[358] = new NotImplementedFunction("GetPIVOTDATA");                        // GetPIVOTDATA
     retval[359] = new Hyperlink();                                                   // HYPERLINK
     retval[360] = new NotImplementedFunction("PHONETIC");                            // PHONETIC
     retval[361] = new NotImplementedFunction("AVERAGEA");                            // AVERAGEA
     retval[362] = new Maxa();                                                        // MAXA
     retval[363] = new Mina();                                                        // MINA
     retval[364] = new NotImplementedFunction("STDEVPA");                             // STDEVPA
     retval[365] = new NotImplementedFunction("VARPA");                               // VARPA
     retval[366] = new NotImplementedFunction("STDEVA");                              // STDEVA
     retval[367] = new NotImplementedFunction("VARA");                                // VARA
     return(retval);
 }
Ejemplo n.º 46
0
        public void ResultTypeVerVarTest()
        {
            var exp = new And(new Variable("y"), new Variable("x"));

            Assert.Equal(ExpressionResultType.Number | ExpressionResultType.Boolean, exp.ResultType);
        }
Ejemplo n.º 47
0
        /// <summary>
        /// Call a SmartObject get list and return a data table
        /// </summary>
        /// <param name="objectName">SmartObjec Name</param>
        /// <param name="methodName">Method Name</param>
        /// <param name="properties">Collection of Properties for the input parameters of the method</param>
        /// <returns>Generic list of Collection of Properties from the SmartObject return property collection</returns>
        public DataTable CallSmartObjectListMethod(string objectName, string methodName, Dictionary<string, object> properties, bool useFilter)
        {
            List<Dictionary<string, object>> returnCollection = new List<Dictionary<string, object>>();
            if (!SMOServer.Connection.IsConnected) return new DataTable();

            SmartObject smartObject = SMOServer.GetSmartObject(objectName);
            smartObject.MethodToExecute = methodName;
            if (useFilter)
            {
                SmartListMethod getList = smartObject.ListMethods[methodName];
                LogicalFilter currentFilter = null;
                LogicalFilter lastFilter = null;

                foreach (var prop in properties)
                {
                    lastFilter = currentFilter;
                    currentFilter = CreateEqualsFilter(prop.Key, prop.Value);
                    if (lastFilter != null)
                    {
                        //keeps creating 'and' filters for all properties 
                        //e.g. PIID=1243 AND DataName="Data.Field" AND ProcessName = "myProcess"
                        currentFilter = new And(lastFilter, currentFilter);
                    }
                }

                ////////var leftFilter = CreateEqualsFilter(properties[0],int.Parse(properties["ProcessInstanceID"].ToString())) ;
                ////////var rightFilter = CreateEqualsFilter("DataName", properties["DataName"].ToString());
                if (currentFilter != null)
                {// if there is more than one filter
                    //If only one property, then this is an Equals filter
                    //for more than one property it is an AND filter
                    getList.Filter = currentFilter;
                }
            }
            else
            {
                //Set Parameter
                foreach (SmartParameter para in smartObject.ListMethods[methodName].Parameters)
                {
                    if (properties.ContainsKey(para.Name)) SetPropertyValue(para, properties[para.Name]);
                }

                //Set propery
                foreach (SmartProperty prop in smartObject.ListMethods[methodName].InputProperties)
                {
                    //See if this key exists in the data properteries
                    if (properties.ContainsKey(prop.Name)) SetPropertyValue(prop, properties[prop.Name]);
                }
            }
            //maybe temp, remove space from displayname
            return K2Field.Helpers.Core.Code.Converters.RemoveSpaceInColumnNameSpaces(SMOServer.ExecuteListDataTable(smartObject));
        }
Ejemplo n.º 48
0
        public void ExecuteTest1()
        {
            var exp = new And(new Number(1), new Number(3));

            Assert.Equal(1.0, exp.Execute());
        }
Ejemplo n.º 49
0
 public void Visit(And and)
 {
     and.Left.Accept(this);
     _sb.Append(" && ");
     and.Right.Accept(this);
 }
Ejemplo n.º 50
0
        public void ExecuteTest2()
        {
            var exp = new And(new Number(1.5), new Number(2.5));

            Assert.Equal(2.0, exp.Execute());
        }
Ejemplo n.º 51
0
        static void Main(string[] args)
        {
            Action<Equation> AssertIsTrue = (eq) =>
            {
                if (!eq) Console.WriteLine(eq.ToString());
            };

            Func<MathObject, MathObject> sin = obj => Trig.Sin(obj);
            Func<MathObject, MathObject> cos = obj => Trig.Cos(obj);
            Func<MathObject, MathObject> tan = obj => new Tan(obj).Simplify();

            Func<MathObject, MathObject> asin = obj => new Asin(obj).Simplify();
            Func<MathObject, MathObject> atan = obj => new Atan(obj).Simplify();

            {
                var a = new Symbol("a");
                var b = new Symbol("b");
                var c = new Symbol("c");
                var d = new Symbol("d");

                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                Func<int, Integer> Int = (n) => new Integer(n);

                {
                    DoubleFloat.tolerance = 0.000000001;

                    Assert(new DoubleFloat(1.2).Equals(new DoubleFloat(1.2)), "new DoubleFloat(1.2).Equals(new DoubleFloat(1.2))");

                    Assert(new DoubleFloat(1.20000001).Equals(new DoubleFloat(1.20000002)) == false, "new DoubleFloat(1.20000001).Equals(new DoubleFloat(1.20000002)) == false");

                    Assert(new DoubleFloat(1.2000000000001).Equals(new DoubleFloat(1.200000000002)), "new DoubleFloat(1.2000000000001).Equals(new DoubleFloat(1.200000000002))");

                    Assert(new DoubleFloat(1.2).Equals(new DoubleFloat(1.23)) == false, "new DoubleFloat(1.2).Equals(new DoubleFloat(1.23)) == false");

                    DoubleFloat.tolerance = null;
                }

                #region Simplify

                AssertIsTrue(x + x == 2 * x);

                AssertIsTrue(x + x == 2 * x);

                AssertIsTrue(x + x + x == 3 * x);

                AssertIsTrue(5 + x + 2 == 7 + x);

                AssertIsTrue(3 + x + 5 + x == 8 + 2 * x);

                AssertIsTrue(4 * x + 3 * x == 7 * x);

                AssertIsTrue(x + y + z + x + y + z == 2 * x + 2 * y + 2 * z);

                AssertIsTrue(10 - x == 10 + x * -1);

                AssertIsTrue(x * y / 3 == Int(1) / 3 * x * y);

                AssertIsTrue(x / y == x * (y ^ -1));

                AssertIsTrue(x / 3 == x * (Int(1) / 3));

                AssertIsTrue(6 * x * y / 3 == 2 * x * y);

                AssertIsTrue((((x ^ Int(1) / 2) ^ Int(1) / 2) ^ 8) == (x ^ 2));

                AssertIsTrue(((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2) == (x * y * (z ^ 4)));

                AssertIsTrue(x / x == 1);

                AssertIsTrue(x / y * y / x == 1);

                AssertIsTrue((x ^ 2) * (x ^ 3) == (x ^ 5));

                AssertIsTrue(x + y + x + z + 5 + z == 5 + 2 * x + y + 2 * z);

                AssertIsTrue(((Int(1) / 2) * x + (Int(3) / 4) * x) == Int(5) / 4 * x);

                AssertIsTrue(1.2 * x + 3 * x == 4.2 * x);

                AssertIsTrue(3 * x + 1.2 * x == 4.2 * x);

                AssertIsTrue(1.2 * x * 3 * y == 3.5999999999999996 * x * y);

                AssertIsTrue(3 * x * 1.2 * y == 3.5999999999999996 * x * y);

                AssertIsTrue(3.4 * x * 1.2 * y == 4.08 * x * y);

                AssertIsTrue((a == b) == (a == b));

                #endregion

                #region Power.Simplify

                AssertIsTrue((0 ^ x) == 0);
                AssertIsTrue((1 ^ x) == 1);
                AssertIsTrue((x ^ 0) == 1);
                AssertIsTrue((x ^ 1) == x);

                #endregion

                // Product.Simplify

                AssertIsTrue(x * 0 == 0);

                // Difference

                AssertIsTrue(-x == -1 * x);

                AssertIsTrue(x - y == x + -1 * y);

                #region Substitute

                AssertIsTrue(Int(10).Substitute(Int(10), 20) == 20);
                AssertIsTrue(Int(10).Substitute(Int(15), 20) == 10);

                AssertIsTrue(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.0), 2.0) == 2.0);
                AssertIsTrue(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.5), 2.0) == 1.0);

                AssertIsTrue((Int(1) / 2).Substitute(Int(1) / 2, Int(3) / 4) == Int(3) / 4);
                AssertIsTrue((Int(1) / 2).Substitute(Int(1) / 3, Int(3) / 4) == Int(1) / 2);

                AssertIsTrue(x.Substitute(x, y) == y);
                AssertIsTrue(x.Substitute(y, y) == x);

                AssertIsTrue((x ^ y).Substitute(x, 10) == (10 ^ y));
                AssertIsTrue((x ^ y).Substitute(y, 10) == (x ^ 10));

                AssertIsTrue((x ^ y).Substitute(x ^ y, 10) == 10);

                AssertIsTrue((x * y * z).Substitute(x, y) == ((y ^ 2) * z));
                AssertIsTrue((x * y * z).Substitute(x * y * z, x) == x);

                AssertIsTrue((x + y + z).Substitute(x, y) == ((y * 2) + z));
                AssertIsTrue((x + y + z).Substitute(x + y + z, x) == x);

                AssertIsTrue(
                    ((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2)
                        .Substitute(x, 10)
                        .Substitute(y, 20)
                        .Substitute(z, 3)
                        == 16200
                        );

                #region Equation.Substitute

                AssertIsTrue((x == y).Substitute(y, z) == (x == z));

                AssertIsTrue((x != y).Substitute(y, z) == (x != z));

                (x == 0).Substitute(x, 0).AssertEqTo(true);

                (x == 0).Substitute(x, 1).AssertEqTo(false);

                (x != 0).Substitute(x, 0).AssertEqTo(false);

                (x != 0).Substitute(x, 1).AssertEqTo(true);

                #endregion

                #endregion

                AssertIsTrue(sin(new DoubleFloat(3.14159 / 2)) == 0.99999999999911982);

                AssertIsTrue(sin(x + y) + sin(x + y) == 2 * sin(x + y));

                AssertIsTrue(sin(x + x) == sin(2 * x));

                AssertIsTrue(sin(x + x).Substitute(x, 1) == sin(Int(2)));

                AssertIsTrue(sin(x + x).Substitute(x, 1.0) == 0.90929742682568171);

                AssertIsTrue(sin(2 * x).Substitute(x, y) == sin(2 * y));

                // Product.RecursiveSimplify

                AssertIsTrue(1 * x == x);

                AssertIsTrue(x * 1 == x);

                AssertIsTrue(x != y);

                AssertIsTrue(x != 10);

                // ==(double a, MathObject b)

                AssertIsTrue(1.0 == new DoubleFloat(3.0) - 2.0);

                AssertIsTrue((a == b) != (a != b));

                #region Equation.ToString

                Assert((x == y).ToString() == "x == y", "x == y");

                Assert((x != y).ToString() == "x != y", "x != y");

                #endregion

                #region Function.ToString

                Assert(new And().ToString() == "And()", "And()");

                #endregion

                #region Equation.Simplify

                (new Integer(0) == new Integer(0)).Simplify().AssertEqTo(true);

                (new Integer(0) == new Integer(1)).Simplify().AssertEqTo(false);

                (new Integer(0) != new Integer(1)).Simplify().AssertEqTo(true);

                (new Integer(0) != new Integer(0)).Simplify().AssertEqTo(false);

                #endregion

                #region And

                new And().Simplify().AssertEqTo(true);

                new And(10).Simplify().AssertEqTo(10);

                new And(true).Simplify().AssertEqTo(true);

                new And(false).Simplify().AssertEqTo(false);

                new And(10, 20, 30).Simplify().AssertEqTo(new And(10, 20, 30));

                new And(10, false, 20).Simplify().AssertEqTo(false);

                new And(10, true, 20).Simplify().AssertEqTo(new And(10, 20));

                new And(10, new And(20, 30), 40)
                    .Simplify()
                    .AssertEqTo(new And(10, 20, 30, 40));

                #endregion

                #region Or

                new Or(10).Simplify().AssertEqTo(10);

                new Or(true).Simplify().AssertEqTo(true);

                new Or(false).Simplify().AssertEqTo(false);

                new Or(10, 20, false).Simplify().AssertEqTo(new Or(10, 20));

                new Or(false, false).Simplify().AssertEqTo(false);

                new Or(10, true, 20, false).Simplify().AssertEqTo(true);

                new Or(10, false, 20).Simplify().AssertEqTo(new Or(10, 20));

                new Or(10, new Or(20, 30), 40)
                    .Simplify()
                    .AssertEqTo(new Or(10, 20, 30, 40));

                #endregion

                #region Function.Map

                new And(1, 2, 3, 4, 5, 6).Map(elt => elt * 2)
                    .AssertEqTo(new And(2, 4, 6, 8, 10, 12));

                new And(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
                    .AssertEqTo(false);

                new Or(1, 2, 3).Map(elt => elt * 2)
                    .AssertEqTo(new Or(2, 4, 6));

                new Or(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
                    .AssertEqTo(new Or(2, 4, 6));

                #endregion Function.Map

                #region Sum

                Assert((x + y).Equals(x * y) == false, "(x + y).Equals(x * y)");

                #endregion

                #region Has

                Assert(a.Has(elt => elt == a), "a.Has(elt => elt == a)");

                Assert(a.Has(elt => elt == b) == false, "a.Has(elt => elt == b) == false");

                Assert((a == b).Has(elt => elt == a), "Has - 3");

                Assert((a == b).Has(elt => elt == c) == false, "Has - 4");

                Assert(((a + b) ^ c).Has(elt => elt == a + b), "Has - 5");

                Assert(((a + b) ^ c).Has(elt => (elt is Power) && (elt as Power).exp == c), "Has - 6");

                Assert((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).Has(b)), "Has - 7");

                Assert((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).elts.Any(obj => obj == b)), "Has - 8");

                Assert((x * (a + b + c)).Has(elt => (elt is Product) && (elt as Product).elts.Any(obj => obj == b)) == false, "Has - 9");

                #endregion

                #region FreeOf

                Assert((a + b).FreeOf(b) == false, "(a + b).FreeOf(b)");
                Assert((a + b).FreeOf(c) == true, "(a + b).FreeOf(c)");
                Assert(((a + b) * c).FreeOf(a + b) == false, "((a + b) * c).FreeOf(a + b)");
                Assert((sin(x) + 2 * x).FreeOf(sin(x)) == false, "(sin(x) + 2 * x).FreeOf(sin(x))");
                Assert(((a + b + c) * d).FreeOf(a + b) == true, "((a + b + c) * d).FreeOf(a + b)");
                Assert(((y + 2 * x - y) / x).FreeOf(x) == true, "((y + 2 * x - y) / x).FreeOf(x)");
                Assert(((x * y) ^ 2).FreeOf(x * y) == true, "((x * y) ^ 2).FreeOf(x * y)");

                #endregion

                #region Denominator
                {
                    ((new Integer(2) / 3) * ((x * (x + 1)) / (x + 2)) * (y ^ z))
                        .Denominator()
                        .AssertEqTo(3 * (x + 2));
                }
                #endregion

                #region LogicalExpand

                new And(new Or(a, b), c)
                    .LogicalExpand()
                    .AssertEqTo(
                        new Or(
                            new And(a, c),
                            new And(b, c)));

                new And(a, new Or(b, c))
                    .LogicalExpand()
                    .AssertEqTo(new Or(new And(a, b), new And(a, c)));

                new And(a, new Or(b, c), d)
                    .LogicalExpand()
                    .AssertEqTo(
                        new Or(
                            new And(a, b, d),
                            new And(a, c, d)));

                new And(new Or(a == b, b == c), x == y)
                    .LogicalExpand()
                    .AssertEqTo(
                        new Or(
                            new And(a == b, x == y),
                            new And(b == c, x == y)));

                new And(
                    new Or(a == b, b == c),
                    new Or(c == d, d == a),
                    x == y)
                    .LogicalExpand()
                    .AssertEqTo(
                        new Or(
                            new And(a == b, c == d, x == y),
                            new And(a == b, d == a, x == y),
                            new And(b == c, c == d, x == y),
                            new And(b == c, d == a, x == y)));

                #endregion

                #region SimplifyEquation

                (2 * x == 0)
                    .SimplifyEquation()
                    .AssertEqTo(x == 0);

                (2 * x != 0)
                    .SimplifyEquation()
                    .AssertEqTo(x != 0);

                ((x ^ 2) == 0)
                    .SimplifyEquation()
                    .AssertEqTo(x == 0);

                #endregion

                #region SimplifyLogical

                new And(a, b, c, a)
                    .SimplifyLogical()
                    .AssertEqTo(new And(a, b, c));

                #endregion SimplifyLogical

                #region DegreeGpe

                {
                    var w = new Symbol("w");

                    Assert(
                        ((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z }) == 6,
                        "((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z })");

                    Assert(
                        ((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x }) == 2,
                        "((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x })");

                    Assert(
                        (a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) }) == 2,
                        "(a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) })");

                    Assert(
                        (2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z }) == 7,
                        "(2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z })");
                }

                #endregion

                #region CoefficientGpe

                AssertIsTrue((a * (x ^ 2) + b * x + c).CoefficientGpe(x, 2) == a);

                AssertIsTrue((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 1) == 3 * (y ^ 2) + 7);

                AssertIsTrue((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 3) == 0);

                Assert(
                    (3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null,
                    "(3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null");

                #endregion

                #region AlgebraicExpand

                AssertIsTrue(
                    ((x + 2) * (x + 3) * (x + 4)).AlgebraicExpand()
                    ==
                    24 + 26 * x + 9 * (x ^ 2) + (x ^ 3));

                AssertIsTrue(
                    ((x + y + z) ^ 3).AlgebraicExpand()
                    ==
                    (x ^ 3) + (y ^ 3) + (z ^ 3) +
                    3 * (x ^ 2) * y +
                    3 * (y ^ 2) * x +
                    3 * (x ^ 2) * z +
                    3 * (y ^ 2) * z +
                    3 * (z ^ 2) * x +
                    3 * (z ^ 2) * y +
                    6 * x * y * z);

                AssertIsTrue(
                    (((x + 1) ^ 2) + ((y + 1) ^ 2)).AlgebraicExpand()
                    ==
                    2 + 2 * x + (x ^ 2) + 2 * y + (y ^ 2));

                AssertIsTrue(
                    ((((x + 2) ^ 2) + 3) ^ 2).AlgebraicExpand()
                    ==
                    49 + 56 * x + 30 * (x ^ 2) + 8 * (x ^ 3) + (x ^ 4));

                AssertIsTrue(
                    sin(x * (y + z)).AlgebraicExpand()
                    ==
                    sin(x * y + x * z));

                AssertIsTrue(
                    (a * (b + c) == x * (y + z)).AlgebraicExpand()
                    ==
                    (a * b + a * c == x * y + x * z));

                #endregion

                #region IsolateVariable

                (x + y + z == 0).IsolateVariable(a).AssertEqTo(x + y + z == 0);

                // (x * a + x * b == 0).IsolateVariable(x).Disp();

                (x * (a + b) - x * a - x * b + x == c)
                    .IsolateVariable(x)
                    .AssertEqTo(x == c);

                new And(x == y, a == b)
                    .IsolateVariable(b)
                    .AssertEqTo(new And(x == y, b == a));

                new Or(new And(y == x, z == x), new And(b == x, c == x))
                    .IsolateVariable(x)
                    .AssertEqTo(new Or(new And(x == y, x == z), new And(x == b, x == c)));

                Assert((0 == x - y).IsolateVariableEq(x).Equals(x == y), "(0 == x - y).IsolateVariable(x).Equals(x == y)");

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                (a * (x ^ 2) + b * x + c == 0)
                    .IsolateVariable(x)
                    .AssertEqTo(

                        new Or(

                            new And(
                                x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            new And(
                                x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            new And(x == -c / b, a == 0, b != 0),

                            new And(a == 0, b == 0, c == 0)
                        )
                    );

                (a * (x ^ 2) + c == 0)
                    .IsolateVariable(x)
                    .AssertEqTo(

                        new Or(
                            new And(
                                x == sqrt(-4 * a * c) / (2 * a),
                                a != 0
                            ),

                            new And(
                                x == -sqrt(-4 * a * c) / (2 * a),
                                a != 0
                            ),

                            new And(a == 0, c == 0)
                        )
                    );

                // a x^2 + b x + c == 0
                // a x^2 + c == - b x
                // (a x^2 + c) / x == - b

                ((a * (x ^ 2) + c) / x == -b)
                    .IsolateVariable(x)
                    .AssertEqTo(

                    new Or(

                            new And(
                                x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            new And(
                                x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
                                a != 0
                            ),

                            new And(x == -c / b, a == 0, b != 0),

                            new And(a == 0, b == 0, c == 0)
                        )
                );

                (sqrt(x + y) == z).IsolateVariable(x).AssertEqTo(x == (z ^ 2) - y);

                (a * b + a == c)
                    .IsolateVariable(a)
                    .AssertEqTo(a == c / (b + 1));

                (a * b + a * c == d)
                    .IsolateVariable(a)
                    .AssertEqTo(a == d / (b + c));

                (1 / sqrt(x) == y)
                    .IsolateVariable(x)
                    .AssertEqTo(x == (y ^ -2));

                (y == sqrt(x) / x)
                    .IsolateVariable(x)
                    .AssertEqTo(x == (y ^ -2));

                (-sqrt(x) + z * x == y)
                    .IsolateVariable(x)
                    .AssertEqTo(-sqrt(x) + z * x == y);

                (sqrt(a + x) - z * x == -y)
                    .IsolateVariable(x)
                    .AssertEqTo(sqrt(a + x) - z * x == -y);

                (sqrt(2 + x) * sqrt(3 + x) == y)
                    .IsolateVariable(x)
                    .AssertEqTo(sqrt(2 + x) * sqrt(3 + x) == y);

                #endregion

                #region EliminateVariable

                new And((x ^ 3) == (y ^ 5), z == x)
                .EliminateVariable(x)
                .AssertEqTo((z ^ 3) == (y ^ 5));

                new And((x ^ 3) == (y ^ 5), z == (x ^ 7))
                .EliminateVariable(x)
                .AssertEqTo(new And((x ^ 3) == (y ^ 5), z == (x ^ 7)));

                #endregion

            }

            #region EliminateVariable

            #region
            {

                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                var eqs = new And()
                {
                    args =
                    {
                        (x ^ 2) - 4 == 0,
                        y + x == 0,
                        x + z == 10
                    }
                }
                .Simplify();

                var half = new Integer(1) / 2;

                Func<MathObject, MathObject> sqrt = obj => obj ^ half;

                ((x ^ 2) - 4 == 0)
                    .IsolateVariableEq(x)
                    .AssertEqTo(new Or(x == half * sqrt(16), x == -half * sqrt(16)));

                eqs.EliminateVariable(x)
                    .AssertEqTo(
                        new Or(
                            new And(
                                half * sqrt(16) + y == 0,
                                half * sqrt(16) + z == 10
                            ),
                            new And(
                                -half * sqrt(16) + y == 0,
                                -half * sqrt(16) + z == 10
                            )
                        )
                    );

            }
            #endregion

            #region
            {
                var a = new Symbol("a");
                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                new Or(
                    new And(x == y, x == z, x == a),
                    new And(x == -y, x == z, x == a)
                    )
                    .EliminateVariable(x)
                    .AssertEqTo(
                        new Or(
                            new And(y == z, y == a),
                            new And(-y == z, -y == a)
                        )
                    )
                    .EliminateVariable(y)
                    .AssertEqTo(new Or(z == a, z == a));
            }
            #endregion

            {
                var x = new Symbol("x");
                var y = new Symbol("y");
                var z = new Symbol("z");

                new And(y != z, y == x, y == 10)
                    .EliminateVariable(y)
                    .AssertEqTo(new And(x != z, x == 10));
            }

            #region PSE Example 2.6

            {
                var sAC = new Symbol("sAC");
                var sAB = new Symbol("sAB");

                var vA = new Symbol("vA");
                var vB = new Symbol("vB");
                var vC = new Symbol("vC");

                var a = new Symbol("a");

                var tAC = new Symbol("tAC");
                var tAB = new Symbol("tAB");

                var eqs = new And(tAB == tAC / 2);

                eqs.args.AddRange(Kinematic(sAC, vA, vC, a, tAC));
                eqs.args.AddRange(Kinematic(sAB, vA, vB, a, tAB));

                var vals = new List<Equation>() { vA == 10, vC == 30, tAC == 10 };

                eqs
                    .EliminateVariables(tAB, sAC, vB, sAB)
                    .IsolateVariable(a)
                    .AssertEqTo(a == (vC - vA) / tAC)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(a == 2);

                eqs
                    .EliminateVariables(vB, a, tAB, sAC)
                    .AssertEqTo(sAB == tAC / 4 * (2 * vA + (vC - vA) / 2))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(sAB == 75);
            }

            #endregion

            #region PSE Example 2.7
            {
                // s =
                // u = 63
                // v =  0
                // a =
                // t =  2

                var s = new Symbol("s");
                var u = new Symbol("u");
                var v = new Symbol("v");
                var a = new Symbol("a");
                var t = new Symbol("t");

                var eqs = new And();

                eqs.args.AddRange(Kinematic(s, u, v, a, t));

                var vals = new List<Equation>() { u == 63, v == 0, t == 2.0 };

                eqs
                    .EliminateVariable(s)
                    .AssertEqTo(v == a * t + u)
                    .IsolateVariable(a)
                    .AssertEqTo(a == (v - u) / t)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(a == -31.5);

                eqs
                    .EliminateVariable(a)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(s == 63.0);
            }
            #endregion

            #region PSE Example 2.8
            {
                // car
                //
                // s1 =
                // u1 = 45
                // v1 = 45
                // a1 =  0
                // t1 =

                // officer
                //
                // s2 =
                // u2 =  0
                // v2 =
                // a2 =  3
                // t2

                var s1 = new Symbol("s1");
                var u1 = new Symbol("u1");
                var v1 = new Symbol("v1");
                var a1 = new Symbol("a1");
                var t1 = new Symbol("t1");

                var s2 = new Symbol("s2");
                var u2 = new Symbol("u2");
                var v2 = new Symbol("v2");
                var a2 = new Symbol("a2");
                var t2 = new Symbol("t2");

                var eqs = new And(
                    u1 == v1,
                    s1 == s2,
                    t2 == t1 - 1);

                eqs.args.AddRange(Kinematic(s1, u1, v1, a1, t1));
                eqs.args.AddRange(Kinematic(s2, u2, v2, a2, t2));

                var vals = new List<Equation>()
                {
                    v1 == 45.0,
                    u2 == 0,
                    a2 == 3
                };

                eqs
                    .EliminateVariables(s2, t1, a1, s1, v2, u1)
                    .IsolateVariable(t2)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(t2 == -0.96871942267131317, t2 == 30.968719422671313));
            }
            #endregion

            #region PSE Example 2.12

            {
                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");
                var yD = new Symbol("yD");

                var tA = new Symbol("tA");
                var tB = new Symbol("tB");
                var tC = new Symbol("tC");
                var tD = new Symbol("tD");

                var vA = new Symbol("vA");
                var vB = new Symbol("vB");
                var vC = new Symbol("vC");
                var vD = new Symbol("vD");

                var a = new Symbol("a");

                var eqs = new And();

                eqs.args.AddRange(Kinematic(yA, yB, vA, vB, a, tA, tB));
                eqs.args.AddRange(Kinematic(yB, yC, vB, vC, a, tB, tC));
                eqs.args.AddRange(Kinematic(yC, yD, vC, vD, a, tC, tD));

                var vals = new List<Equation>()
                {
                    yA == 50,
                    yC == 50,
                    vA == 20,
                    vB == 0,
                    a == -9.8,
                    tA == 0,
                    tD == 5
                };

                // velocity and position at t = 5.00 s

                DoubleFloat.tolerance = 0.000000001;

                eqs
                    .EliminateVariables(tB, tC, vC, yB, yD)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(vD == -29.000000000000004, vD == -29.000000000000007));

                eqs
                    .EliminateVariables(tB, tC, vC, yB, vD)
                    .IsolateVariable(yD)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(yD == 27.499999999, yD == 27.499999999));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE Example 4.3

            {
                var xA = new Symbol("xA");
                var xB = new Symbol("xB");
                var xC = new Symbol("xC");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");
                var vxC = new Symbol("vxC");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var eqs = new And(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    tAC == 2 * tAB,

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxC == vxA + ax * tAB,
                    vyC == vyA + ay * tAB,

                    xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
                    yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2

                    );

                var zeros = new List<Equation>() { xA == 0, yA == 0, ax == 0, vyB == 0 };

                var vals = new List<Equation>() { thA == (20).ToRadians(), vA == 11.0, ay == -9.8, Trig.Pi == Math.PI };

                eqs
                    .EliminateVariables(xB, yC, vxB, vxC, vyC, yB, tAC, vxA, vyA, tAB)
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(xC == -2 * cos(thA) * sin(thA) * (vA ^ 2) / ay)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(xC == 7.9364592624562507);

                eqs
                    .EliminateVariables(xB, yC, vxB, vxC, vyC, xC, vxA, tAC, vyA, tAB)
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(yB == -(sin(thA) ^ 2) * (vA ^ 2) / (2 * ay))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(yB == 0.72215873425009314);
            }

            #endregion

            #region PSE 5E Example 4.5

            {
                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var xB = new Symbol("xB");
                var xC = new Symbol("xC");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");
                var yC = new Symbol("yC");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");
                var vxC = new Symbol("vxC");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var vC = new Symbol("vC");

                var eqs = new And(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    // tAC == 2 * tAB,

                    // vxB == vxA + ax * tAB,
                    // vyB == vyA + ay * tAB,

                    // xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    // yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxC == vxA + ax * tAC,
                    vyC == vyA + ay * tAC,

                    // xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
                    yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2,

                    vC == sqrt((vxC ^ 2) + (vyC ^ 2)),

                    ay != 0
                );

                var zeros = new List<Equation>() { ax == 0, yC == 0 };
                var vals = new List<Equation>() { yA == 45, vA == 20, thA == (30).ToRadians(), ay == -9.8, Trig.Pi == Math.PI };

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .EliminateVariables(vC, vxA, vxC, vyC, vyA)
                    .IsolateVariable(tAC)
                    .LogicalExpand().SimplifyEquation().SimplifyLogical()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        new Or(
                            new And(
                                tAC == -(sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
                                ay != 0),
                            new And(
                                tAC == -(sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(tAC == 4.2180489012229376, tAC == -2.1772325746923267));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxC, vxA, vyA, vyC, tAC)
                    .SimplifyEquation().SimplifyLogical()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        new Or(
                            new And(
                                ay != 0,
                                vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2))),
                            new And(
                                ay != 0,
                                vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2)))))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(vC == 35.805027579936315, vC == 35.805027579936322));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E Example 4.6

            {
                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var xB = new Symbol("xB");

                var yA = new Symbol("yA");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vxB = new Symbol("vxB");

                var vyA = new Symbol("vyA");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var eqs = new And(

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxA != 0,

                    ay != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 100, vxA == 40, vyA == 0, yB == 0, ax == 0, ay == -9.8, Trig.Pi == Math.PI };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .EliminateVariables(vxB, vyB, tAB)
                    .IsolateVariable(xB)
                    .LogicalExpand().SimplifyEquation()
                    .CheckVariable(ay)
                    .CheckVariable(vxA).SimplifyLogical()
                    .SubstituteEq(ax == 0)
                    .AssertEqTo(
                        new Or(
                            new And(
                                vxA != 0,
                                xB == -1 * (ay ^ -1) * (vxA ^ 2) * (-1 * (-1 * (vxA ^ -1) * vyA + ay * (vxA ^ -2) * xA) + sqrt(((-1 * (vxA ^ -1) * vyA + ay * (vxA ^ -2) * xA) ^ 2) + 2 * ay * (vxA ^ -2) * ((vxA ^ -1) * vyA * xA - ay / 2 * (vxA ^ -2) * (xA ^ 2) + -1 * yA + yB))),
                                ay * (vxA ^ -2) != 0,
                                ay != 0),
                            new And(
                                vxA != 0,
                                xB == -1 * (ay ^ -1) * (vxA ^ 2) * (-1 * (-1 * (vxA ^ -1) * vyA + ay * (vxA ^ -2) * xA) + -1 * sqrt(((-1 * (vxA ^ -1) * vyA + ay * (vxA ^ -2) * xA) ^ 2) + 2 * ay * (vxA ^ -2) * ((vxA ^ -1) * vyA * xA - ay / 2 * (vxA ^ -2) * (xA ^ 2) + -1 * yA + yB))),
                                ay * (vxA ^ -2) != 0,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(
                        new Or(
                            new And(
                                vxA != 0,
                                xB == -1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
                                ay / (vxA ^ 2) != 0,
                                ay != 0),
                            new And(
                                vxA != 0,
                                xB == 1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
                                ay / (vxA ^ 2) != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(xB == 180.70158058105022, xB == -180.70158058105022));

                eqs
                    .EliminateVariables(vxB, xB, tAB)
                    .IsolateVariable(vyB)
                    .LogicalExpand().SimplifyEquation()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        new Or(
                            new And(
                                vyB == -1 * ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
                    // (ay ^ -1) != 0,
                                vxA != 0,
                                ay != 0),
                            new And(
                                vyB == ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
                    // (ay ^ -1) != 0,
                                vxA != 0,
                                ay != 0)))
                    .SubstituteEqLs(zeros)
                    .AssertEqTo(
                        new Or(
                          new And(
                              vyB == -ay * sqrt(-2 / ay * yA),
                    // 1 / ay != 0,
                              vxA != 0,
                              ay != 0),
                          new And(
                              vyB == ay * sqrt(-2 / ay * yA),
                    // 1 / ay != 0,
                              vxA != 0,
                              ay != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(vyB == 44.271887242357309, vyB == -44.271887242357309));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E Example 4.7

            {
                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var th = new Symbol("th");
                var d = new Symbol("d");

                var eqs = new And(

                    cos(th) == (xB - xA) / d,
                    sin(th) == (yA - yB) / d,

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    yB != 0,

                    ay != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 0, vxA == 25, vyA == 0, ax == 0, ay == -9.8, th == (35).ToRadians(), Trig.Pi == Math.PI };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, yB, tAB)
                    .IsolateVariable(xB)
                    .LogicalExpand()
                    .CheckVariable(ay)
                    .SimplifyEquation()
                    .AssertEqTo(
                        new Or(
                            new And(
                                xB == -(sin(th) / cos(th) + sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
                                ay / (vxA ^ 2) != 0,
                                sin(th) / cos(th) * xB != 0,
                                ay != 0),
                            new And(
                                xB == -(sin(th) / cos(th) - sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
                                ay / (vxA ^ 2) != 0,
                                sin(th) / cos(th) * xB != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .SimplifyEquation()
                    .AssertEqTo(
                        new Or(
                            new And(
                                xB == 89.312185996136435,
                                xB != 0),
                            new And(
                                xB == 7.0805039835788038E-15,
                                xB != 0)));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, xB, tAB)
                    .IsolateVariable(yB)
                    .LogicalExpand()
                    .CheckVariable(yB)
                    .AssertEqTo(
                        new And(
                            yB == 2 * (sin(th) ^ 2) * (vxA ^ 2) / ay / (cos(th) ^ 2),
                            -ay * (cos(th) ^ 2) / (sin(th) ^ 2) / (vxA ^ 2) / 2 != 0,
                            yB != 0,
                            ay != 0))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(
                        new And(
                            yB == -62.537065888482395,
                            yB != 0));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, d, xB, yB)
                    .IsolateVariable(tAB)
                    .LogicalExpand().CheckVariable(ay).SimplifyEquation().SimplifyLogical()
                    .AssertEqTo(
                        new Or(
                            new And(
                                tAB == -(sin(th) * vxA / cos(th) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
                                ay != 0,
                                sin(th) * tAB * vxA / cos(th) != 0),
                            new And(
                                tAB == -(sin(th) * vxA / cos(th) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
                                ay != 0,
                                sin(th) * tAB * vxA / cos(th) != 0)))
                    .SubstituteEqLs(vals)
                    .CheckVariable(tAB).SimplifyEquation()
                    .AssertEqTo(
                        new And(
                            tAB == 3.5724874398454571,
                            tAB != 0));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, d, tAB, xB, yB)
                    .IsolateVariable(vyB)
                    .LogicalExpand()
                    .CheckVariable(ay)
                    .SimplifyEquation()
                    .CheckVariable(ay)
                    .AssertEqTo(
                        new Or(
                            new And(
                                vyB == -ay * (sin(th) * vxA / (ay * cos(th)) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
                                sin(th) * vxA * vyB / (ay * cos(th)) != 0,
                                ay != 0),
                            new And(
                                vyB == -ay * (sin(th) * vxA / (ay * cos(th)) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
                                sin(th) * vxA * vyB / (ay * cos(th)) != 0,
                                ay != 0)))
                    .SubstituteEqLs(vals)
                    .CheckVariable(vyB)
                    .SimplifyEquation()
                    .CheckVariable(vyB)
                    .AssertEqTo(
                        new And(
                            vyB == -35.010376910485483,
                            vyB != 0));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.9

            {
                // In a local bar, a customer slides an empty beer mug
                // down the counter for a refill. The bartender is momentarily
                // distracted and does not see the mug, which slides
                // off the counter and strikes the floor 1.40 m from the
                // base of the counter. If the height of the counter is
                // 0.860 m, (a) with what velocity did the mug leave the
                // counter and (b) what was the direction of the mug’s
                // velocity just before it hit the floor?

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var thB = new Symbol("thB");
                var vB = new Symbol("vB");

                var eqs = new And(

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    tan(thB) == vyB / vxB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    xB != 0
                );

                var vals = new List<Equation>() { xA == 0, yA == 0.86, /* vxA */ vyA == 0, xB == 1.4, yB == 0, /* vxB vyB vB thB */ /* tAB */ ax == 0, ay == -9.8 };

                var zeros = vals.Where(eq => eq.b == 0).ToList();

                DoubleFloat.tolerance = 0.00001;

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(thB, vxB, vyB, tAB)
                    .IsolateVariable(vxA)
                    .LogicalExpand()
                    .AssertEqTo(
                        new Or(
                            new And(
                                vxA == ay * (xB ^ 2) / yA / 4 * sqrt(-8 / ay * (xB ^ -2) * yA),
                                2 / ay * (xB ^ -2) * yA != 0,
                                xB != 0),
                            new And(
                                vxA == -ay * (xB ^ 2) / yA / 4 * sqrt(-8 / ay * (xB ^ -2) * yA),
                                2 / ay * (xB ^ -2) * yA != 0,
                                xB != 0)))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(new Or(vxA == -3.3417722634053204, vxA == 3.3417722634053204));

                eqs
                    .SubstituteEqLs(zeros)
                    .EliminateVariables(vxB, vyB, tAB, vxA)
                    .LogicalExpand()
                    .CheckVariable(xB)
                    .SimplifyLogical()
                    .IsolateVariable(thB)
                    .AssertEqTo(
                        new And(
                            -tan(thB) / ay != 0,
                            thB == new Atan(-2 * yA / xB),
                            xB != 0))
                    .SubstituteEqLs(vals)
                    .AssertEqTo(
                        new And(
                            0.1020408163265306 * tan(thB) != 0,
                            thB == -0.88760488150470185));

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region SumDifferenceFormulaFunc

            // sin(u) cos(v) - cos(u) sin(v) -> sin(u - v)

            Func<MathObject, MathObject> SumDifferenceFormulaFunc = elt =>
            {
                if (elt is Sum)
                {
                    var items = new List<MathObject>();

                    foreach (var item in (elt as Sum).elts)
                    {
                        if (
                            item is Product &&
                            (item as Product).elts[0] == -1 &&
                            (item as Product).elts[1] is Cos &&
                            (item as Product).elts[2] is Sin
                            )
                        {
                            var u_ = ((item as Product).elts[1] as Cos).args[0];
                            var v_ = ((item as Product).elts[2] as Sin).args[0];

                            Func<MathObject, bool> match = obj =>
                                obj is Product &&
                                (obj as Product).elts[0] is Cos &&
                                (obj as Product).elts[1] is Sin &&

                                ((obj as Product).elts[1] as Sin).args[0] == u_ &&
                                ((obj as Product).elts[0] as Cos).args[0] == v_;

                            if (items.Any(obj => match(obj)))
                            {
                                items = items.Where(obj => match(obj) == false).ToList();

                                items.Add(sin(u_ - v_));
                            }
                            else items.Add(item);
                        }
                        else items.Add(item);
                    }

                    return new Sum() { elts = items }.Simplify();
                }

                return elt;
            };

            #endregion

            {
                var u = new Symbol("u");
                var v = new Symbol("v");

                (sin(u) * cos(v) - cos(u) * sin(v))
                    .DeepSelect(SumDifferenceFormulaFunc)
                    .AssertEqTo(sin(u - v));
            }

            #region DoubleAngleFormulaFunc

            // sin(u) cos(u) -> sin(2 u) / 2

            Func<MathObject, MathObject> DoubleAngleFormulaFunc =
                    elt =>
                    {
                        if (elt is Product)
                        {
                            var items = new List<MathObject>();

                            foreach (var item in (elt as Product).elts)
                            {
                                if (item is Sin)
                                {
                                    var sym = (item as Sin).args.First();

                                    if (items.Any(obj => (obj is Cos) && (obj as Cos).args.First() == sym))
                                    {
                                        items = items.Where(obj => ((obj is Cos) && (obj as Cos).args.First() == sym) == false).ToList();

                                        items.Add(sin(2 * sym) / 2);
                                    }
                                    else items.Add(item);
                                }

                                else if (item is Cos)
                                {
                                    var sym = (item as Cos).args.First();

                                    if (items.Any(obj => (obj is Sin) && (obj as Sin).args.First() == sym))
                                    {
                                        items = items.Where(obj => ((obj is Sin) && (obj as Sin).args.First() == sym) == false).ToList();

                                        items.Add(sin(2 * sym) / 2);
                                    }
                                    else items.Add(item);
                                }

                                else items.Add(item);

                            }
                            return new Product() { elts = items }.Simplify();
                        }
                        return elt;
                    };

            #endregion

            #region PSE 5E P4.11

            {
                // One strategy in a snowball fight is to throw a first snowball
                // at a high angle over level ground. While your opponent is watching
                // the first one, you throw a second one at a low angle and timed
                // to arrive at your opponent before or at the same time as the first one.

                // Assume both snowballs are thrown with a speed of 25.0 m/s.

                // The first one is thrown at an angle of 70.0° with respect to the horizontal.

                // (a) At what angle should the second (lowangle)
                // snowball be thrown if it is to land at the same
                // point as the first?

                // (b) How many seconds later should the second snowball
                // be thrown if it is to land at the same time as the first?

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");

                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");
                var tAC = new Symbol("tAC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = new And(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() { xA == 0, yA == 0, /* vxA vyA */ vA == 25.0, /* thA == 70.0, */ /* xB == 20.497, */ /* yB */ /* vxB */ vyB == 0, /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        // thA = ... || thA = ...

                        var expr = eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(yB, vxA, vyA, vxB, tAB)
                            .DeepSelect(DoubleAngleFormulaFunc)
                            .IsolateVariable(thA);

                        // th_delta = ...

                        var th1 = ((expr as Or).args[0] as Equation).b;
                        var th2 = ((expr as Or).args[1] as Equation).b;

                        var th_delta = new Symbol("th_delta");

                        eqs
                            .Add(th_delta == (th1 - th2).AlgebraicExpand())
                            .SubstituteEqLs(zeros)

                            .EliminateVariables(yB, vxA, vyA, vxB, tAB)

                            .DeepSelect(DoubleAngleFormulaFunc)
                            .EliminateVariable(xB)

                            .AssertEqTo(th_delta == asin(sin(2 * thA)) - Pi / 2)

                            .SubstituteEq(thA == (70).ToRadians())
                            .SubstituteEq(Pi == Math.PI)

                            .AssertEqTo(th_delta == -0.87266462599716454)
                            ;
                    }

                    {
                        // tAB = ...

                        var tAB_eq = eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(yB, vxA, vyA, vxB, xB)
                            .IsolateVariable(tAB);

                        new And(
                            new Or(thA == (20).ToRadians(), thA == (70).ToRadians()),
                            tAB_eq,
                            tAC == tAB * 2)
                            .LogicalExpand()
                            .EliminateVariables(thA, tAB)

                            .AssertEqTo(new Or(
                                tAC == -2 * sin(Pi / 9) * vA / ay,
                                tAC == -2 * sin(7 * Pi / 18) * vA / ay))

                            .SubstituteEqLs(vals)
                            .AssertEqTo(
                                new Or(
                                    tAC == 1.7450007312534115,
                                    tAC == 4.794350106050552));
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.13

            {
                // An artillery shell is fired with an initial velocity of
                // 300 m/s at 55.0° above the horizontal. It explodes on a
                // mountainside 42.0 s after firing. What are the x and y
                // coordinates of the shell where it explodes, relative to its
                // firing point?

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var tAB = new Symbol("tAB");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = new And(
                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>() { xA == 0, yA == 0, /* vxA vyA */ vA == 300.0, thA == (55).ToRadians(), /* xB yB vxB vyB */ tAB == 42, ax == 0, ay == -9.8, Pi == Math.PI };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariable(vxA)
                            .EliminateVariable(vyA)

                            .AssertEqTo(
                                new And(
                                    vxB == cos(thA) * vA,
                                    vyB == ay * tAB + sin(thA) * vA,
                                    xB == cos(thA) * tAB * vA,
                                    yB == ay * (tAB ^ 2) / 2 + sin(thA) * tAB * vA))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                new And(
                                    vxB == 172.07293090531385,
                                    vyB == -165.85438671330249,
                                    xB == 7227.0630980231817,
                                    yB == 1677.7157580412968))

                            ;
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.15

            {
                // A projectile is fired in such a way that its horizontal
                // range is equal to three times its maximum height.
                //
                // What is the angle of projection?
                // Give your answer to three significant figures.

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var xC = new Symbol("xC");
                var yC = new Symbol("yC");

                var vxC = new Symbol("vxC");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tBC = new Symbol("tBC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var eqs = new And(

                    xC - xA == 3 * yB,

                    tAB == tBC,

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,

                    vxC == vxB + ax * tBC,
                    vyC == vyB + ay * tBC,

                    xC == xB + vxB * tBC + ax * (tBC ^ 2) / 2,
                    yC == yB + vyB * tBC + ay * (tBC ^ 2) / 2

                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        xA == 0, yA == 0, /* vxA vyA vA thA */ /* xB yB vxB */ vyB == 0, /* tAB tBC */
                        /* xC */ yC == 0,

                        ax == 0, ay == -9.8, Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    eqs
                        .SubstituteEqLs(zeros)
                        .EliminateVariables(xC, tAB, vxA, vyA, vxB, xB, yB, vxC, vyC, tBC)
                        .IsolateVariable(thA)
                        .AssertEqTo(thA == new Atan(new Integer(4) / 3));
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #region PSE 5E P4.17

            {
                // A cannon with a muzzle speed of 1000 m/s is used to
                // start an avalanche on a mountain slope. The target is
                // 2000 m from the cannon horizontally and 800 m above
                // the cannon.
                //
                // At what angle, above the horizontal, should the cannon be fired?

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                var xA = new Symbol("xA");
                var yA = new Symbol("yA");

                var vxA = new Symbol("vxA");
                var vyA = new Symbol("vyA");

                var vA = new Symbol("vA");
                var thA = new Symbol("thA");

                var xB = new Symbol("xB");
                var yB = new Symbol("yB");

                var vxB = new Symbol("vxB");
                var vyB = new Symbol("vyB");

                var xC = new Symbol("xC");
                var yC = new Symbol("yC");

                var vxC = new Symbol("vxC");
                var vyC = new Symbol("vyC");

                var tAB = new Symbol("tAB");
                var tBC = new Symbol("tBC");

                var ax = new Symbol("ax");
                var ay = new Symbol("ay");

                var Pi = new Symbol("Pi");

                var phi = new Symbol("phi");

                var eqs = new And(

                    vxA == vA * cos(thA),
                    vyA == vA * sin(thA),

                    vxB == vxA + ax * tAB,
                    vyB == vyA + ay * tAB,

                    xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
                    yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
                );

                DoubleFloat.tolerance = 0.00001;

                {
                    var vals = new List<Equation>()
                    {
                        xA ==    0, yA ==   0, /* vxA vyA */ vA == 1000, /* thA */
                        xB == 2000, yB == 800.0, /* vxB vyB */
                        /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI
                    };

                    var zeros = vals.Where(eq => eq.b == 0).ToList();

                    {
                        eqs
                            .SubstituteEqLs(zeros)
                            .EliminateVariables(vxA, vyA, vxB, vyB, tAB)

                            .MultiplyBothSidesBy(cos(thA) ^ 2).AlgebraicExpand()
                            .Substitute(cos(thA) ^ 2, (1 + cos(2 * thA)) / 2)
                            .DeepSelect(DoubleAngleFormulaFunc).AlgebraicExpand()
                            .AddToBothSides(-sin(2 * thA) * xB / 2)
                            .AddToBothSides(-yB / 2)
                            .MultiplyBothSidesBy(2 / xB).AlgebraicExpand()

                            // yB / xB = tan(phi)
                            // yB / xB = sin(phi) / cos(phi)

                            // phi = atan(yB / xB)

                            .Substitute(cos(2 * thA) * yB / xB, cos(2 * thA) * sin(phi) / cos(phi))
                            .MultiplyBothSidesBy(cos(phi)).AlgebraicExpand()
                            .DeepSelect(SumDifferenceFormulaFunc)
                            .IsolateVariable(thA)

                            .Substitute(phi, new Atan(yB / xB).Simplify())

                            .AssertEqTo(
                                new Or(
                                    thA == -(asin(ay * cos(atan(yB / xB)) * (vA ^ -2) * xB + -1 * cos(atan(yB / xB)) * yB / xB) - atan(yB / xB)) / 2,
                                    thA == -(-asin(ay * cos(atan(yB / xB)) * (vA ^ -2) * xB - cos(atan(yB / xB)) * yB / xB) - atan(yB / xB) + Pi) / 2))

                            .SubstituteEqLs(vals)

                            .AssertEqTo(
                                new Or(
                                    thA == 0.39034573609628065,
                                    thA == -1.5806356857788124))
                            ;
                    }
                }

                DoubleFloat.tolerance = null;
            }

            #endregion

            #endregion

            #region PSE 5E Example 4.3
            {
                var thA = new Symbol("thA"); // angle at point A
                var vA = new Symbol("vA"); // velocity at point A

                var g = new Symbol("g"); // magnitude of gravity

                var _g = new Point(0, -g); // gravity vector

                var objA =
                    new Obj()
                    {
                        position = new Point(0, 0),
                        velocity = Point.FromAngle(thA, vA),
                        acceleration = _g,
                        time = new Integer(0)
                    };

                var objB =
                    new Obj()
                    {
                        velocity = new Point(objA.velocity.x, 0),
                        acceleration = _g
                    };

                var timeB = Calc.Time(objA, objB);
                var timeC = timeB * 2;

                objB = objA.AtTime(timeB);
                var objC = objA.AtTime(timeC);

                //Console.WriteLine("How far does he dump in the horizontal direction?");

                AssertIsTrue(objC.position.x == 2 * Trig.Cos(thA) * Trig.Sin(thA) * (vA ^ 2) / g);

                //Console.WriteLine("What is the maximum height reached?");

                AssertIsTrue(objB.position.y == (Trig.Sin(thA) ^ 2) * (vA ^ 2) / 2 / g);

                // Console.WriteLine("Distance jumped: ");

                var deg = 3.14159 / 180.0;

                AssertIsTrue(
                    objC.position.x
                    // .Substitute(thA, Trig.ToRadians(20))
                    .Substitute(thA, 20 * deg)
                    .Substitute(g, 9.8)
                    .Substitute(Trig.Pi, 3.14159)
                    .Substitute(vA, 11)
                    ==
                    7.9364536850196412);

                //Console.WriteLine("Maximum height reached: ");

                AssertIsTrue(
                    objB.position.y
                    .Substitute(g, 9.8)
                    .Substitute(thA, Trig.ToRadians(20))
                    .Substitute(Trig.Pi, 3.14159)
                    .Substitute(vA, 11)
                    ==
                    0.72215756424454336);
            }
            #endregion

            #region PSE 5E EXAMPLE 4.5
            {
                // A stone is thrown from the top of a building upward at an
                // angle of 30.0° to the horizontal and with an initial speed of
                // 20.0 m/s, as shown in Figure 4.12. If the height of the building
                // is 45.0 m, (a) how long is it before the stone hits the ground?
                // (b) What is the speed of the stone just before it strikes the
                // ground?

                var thA = new Symbol("thA"); // angle at point A
                var vA = new Symbol("vA"); // velocity at point A

                var g = new Symbol("g"); // magnitude of gravity

                var _g = new Point(0, -g); // gravity vector

                var objA = new Obj()
                {
                    position = new Point(0, 0),
                    velocity = Point.FromAngle(thA, vA),
                    acceleration = _g,
                    time = new Integer(0)
                };

                var objB = new Obj()
                {
                    velocity = new Point(objA.velocity.x, 0),
                    acceleration = _g,
                };

                var timeB = Calc.Time(objA, objB);

                objB = objA.AtTime(timeB);

                var timeC = timeB * 2;

                var objC = objA.AtTime(timeC);

                var yD = new Symbol("yD");

                var objD = new Obj()
                {
                    position = new Point(null, yD),
                    velocity = new Point(objA.velocity.x, null),
                    acceleration = _g
                };

                var timeAD = Calc.Time(objA, objD, 1);

                objD = objA.AtTime(timeAD);

                // "How long is it before the stone hits the ground?".Disp();

                // "Symbolic answer:".Disp();

                AssertIsTrue(
                    timeAD
                    ==
                    -1 * (g ^ -1) * (-1 * Trig.Sin(thA) * vA + -1 * (((Trig.Sin(thA) ^ 2) * (vA ^ 2) + -2 * g * yD) ^ (new Integer(1) / 2))));

                // "Numeric answer:".Disp();

                AssertEqual(
                    (DoubleFloat)
                    timeAD
                        .Substitute(g, 9.8)
                        .Substitute(thA, (30).ToRadians())
                        .Substitute(Trig.Pi, 3.14159)
                        .Substitute(vA, 20)
                        .Substitute(yD, -45),
                    new DoubleFloat(4.21804787012706),
                    0.0001);

                // "What is the speed of the stone just before it strikes the ground?".Disp();

                // "Symbolic answer:".Disp();

                AssertIsTrue(
                    objD.velocity.Norm()
                    ==
                    (((Trig.Cos(thA) ^ 2) * (vA ^ 2) + (Trig.Sin(thA) ^ 2) * (vA ^ 2) + -2 * g * yD) ^ (new Integer(1) / 2)));

                // "Numeric answer:".Disp();

                AssertEqual(
                    (DoubleFloat)
                    objD.velocity.Norm()
                        .Substitute(g, 9.8)
                        .Substitute(thA, (30).ToRadians())
                        .Substitute(Trig.Pi, 3.14159)
                        .Substitute(vA, 20)
                        .Substitute(yD, -45),
                    new DoubleFloat(35.805027579936315),
                    0.1);
            }
            #endregion

            #region PSE 5E EXAMPLE 4.6
            {
                // An Alaskan rescue plane drops a package of emergency rations
                // to a stranded party of explorers, as shown in Figure
                // 4.13. If the plane is traveling horizontally at 40.0 m/s and is
                // 100 m above the ground, where does the package strike the
                // ground relative to the point at which it was released?

                var xA = new Symbol("xA");      // position.x at point A

                var yA = new Symbol("yA");      // position.y at point A

                var thA = new Symbol("thA");    // angle at point A

                var vA = new Symbol("vA");      // velocity at point A

                var g = new Symbol("g");        // magnitude of gravity

                var _g = new Point(0, -g);      // gravity vector

                var objA = new Obj()            // obj at the initial position
                {
                    position = new Point(xA, yA),
                    velocity = Point.FromAngle(thA, vA),
                    acceleration = _g,
                    time = 0
                };

                var objB = new Obj()            // obj at the final position
                {
                    position = new Point(null, 0),
                    velocity = new Point(objA.velocity.x, null),
                    acceleration = _g
                };

                var timeB = Calc.Time(objA, objB, 1);

                objB = objA.AtTime(timeB);

                //"Where does the package strike the ground relative to the point at which it was released?".Disp(); "".Disp();

                //"symbolic:".Disp();

                //objB.position.x.Disp(); "".Disp();

                AssertIsTrue(
                    objB.position.x
                    ==
                    xA - cos(thA) / g * vA * (-sin(thA) * vA - (((sin(thA) ^ 2) * (vA ^ 2) + 2 * g * yA) ^ new Integer(1) / 2)));

                //"numeric:".Disp();

                //objB.position.x
                //    .Substitute(xA, 0)
                //    .Substitute(yA, 100)
                //    .Substitute(vA, 40)
                //    .Substitute(thA, 0.0)
                //    .Substitute(g, 9.8)
                //    .Disp();

                AssertEqual(
                    objB.position.x
                        .Substitute(xA, 0)
                        .Substitute(yA, 100)
                        .Substitute(vA, 40)
                        .Substitute(thA, 0.0)
                        .Substitute(g, 9.8),
                    180.70158058105025);

                //"".Disp();

                //("What are the horizontal and vertical components " +
                // "of the velocity of the package just before it hits the ground?").Disp(); "".Disp();

                //"symbolic velocity.x:".Disp();

                //objB.velocity.x.Disp(); "".Disp();

                AssertIsTrue(objB.velocity.x == cos(thA) * vA);

                //"symbolic velocity.y:".Disp();

                //objB.velocity.y.Disp(); "".Disp();

                AssertIsTrue(
                    objB.velocity.y
                    ==
                    -1 * (((sin(thA) ^ 2) * (vA ^ 2) + 2 * g * yA) ^ (new Integer(1) / 2)));

                //"numeric velocity.x:".Disp();

                //objB.velocity.x
                //    .Substitute(xA, 0)
                //    .Substitute(yA, 100)
                //    .Substitute(vA, 40)
                //    .Substitute(thA, 0.0)
                //    .Substitute(g, 9.8)
                //    .Disp(); "".Disp();

                AssertEqual(
                    objB.velocity.x
                        .Substitute(xA, 0)
                        .Substitute(yA, 100)
                        .Substitute(vA, 40)
                        .Substitute(thA, 0.0)
                        .Substitute(g, 9.8),
                    40);

                //"numeric velocity.y:".Disp();

                //objB.velocity.y
                //    .Substitute(xA, 0)
                //    .Substitute(yA, 100)
                //    .Substitute(vA, 40)
                //    .Substitute(thA, 0.0)
                //    .Substitute(g, 9.8)
                //    .Disp(); "".Disp();

                AssertEqual(
                    objB.velocity.y
                        .Substitute(xA, 0)
                        .Substitute(yA, 100)
                        .Substitute(vA, 40)
                        .Substitute(thA, 0.0)
                        .Substitute(g, 9.8),
                    -44.271887242357316);
            }
            #endregion

            #region PSE 5E EXAMPLE 4.7

            {
                // A ski jumper leaves the ski track moving in the horizontal
                // direction with a speed of 25.0 m/s, as shown in Figure 4.14.
                // The landing incline below him falls off with a slope of 35.0°.
                // Where does he land on the incline?

                var thA = new Symbol("thA");    // angle at point A

                var vA = new Symbol("vA");      // velocity at point A

                var g = new Symbol("g");        // magnitude of gravity

                var _g = new Point(0, -g);      // gravity vector

                var th = new Symbol("th");      // angle of incline

                var objA = new Obj()
                {
                    position = new Point(0, 0),
                    velocity = Point.FromAngle(thA, vA),
                    acceleration = _g,
                    time = 0
                };

                Func<MathObject, MathObject> numeric = obj =>
                    obj
                        .Substitute(vA, 25)
                        .Substitute(thA, 0.0)
                        .Substitute(th, (-35).ToRadians())
                        .Substitute(Trig.Pi, 3.14159)
                        .Substitute(g, 9.8);

                var intersection = objA.ProjectileInclineIntersection(th);

                Action nl = () => "".Disp();

                // "Where does he land on the incline?".Disp(); nl();

                // "x position (symbolic):".Disp();

                // intersection.x.Disp(); nl();

                AssertIsTrue(
                    intersection.x
                    ==
                    -2 * (cos(th) ^ -1) * (cos(thA) ^ 2) * (g ^ -1) * (sin(th) + -1 * cos(th) * (cos(thA) ^ -1) * sin(thA)) * (vA ^ 2));

                //"y position (symbolic):".Disp();

                //intersection.y.Disp(); nl();

                AssertIsTrue(
                    intersection.y
                    ==
                    -2 * (cos(th) ^ -2) * (cos(thA) ^ 2) / g * sin(th) * (sin(th) + -1 * cos(th) * (cos(thA) ^ -1) * sin(thA)) * (vA ^ 2));

                //"x position (numeric):".Disp();

                //numeric(intersection.x).Disp(); nl();

                AssertEqual(numeric(intersection.x), 89.3120879153208);

                //"y position (numeric):".Disp();

                //numeric(intersection.y).Disp(); nl();

                AssertEqual(numeric(intersection.y), -62.536928534704884);

                var objB = new Obj()
                {
                    position = intersection,
                    acceleration = _g
                };

                //"Determine how long the jumper is airborne".Disp(); nl();

                //"symbolic:".Disp();

                var timeB = Calc.Time(objA, objB, 1);

                // timeB.Disp(); nl();

                Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

                AssertIsTrue(
                    timeB
                    ==
                    -1 / g *
                    (-sin(thA) * vA -
                        sqrt(
                            (sin(thA) ^ 2) * (vA ^ 2) + 4 * (cos(th) ^ -2) * (cos(thA) ^ 2) * sin(th) *
                            (sin(th) - cos(th) / cos(thA) * sin(thA)) *
                            (vA ^ 2))));

                //"numeric:".Disp();

                //numeric(timeB).Disp(); nl();

                AssertEqual(numeric(timeB), 3.5724835166128317);

                objB = objA.AtTime(timeB);

                //"Determine his vertical component of velocity just before he lands".Disp();
                //nl();

                //"symbolic:".Disp();

                //objB.velocity.y.Disp(); nl();

                AssertIsTrue(
                    objB.velocity.y
                    ==
                    -sqrt(
                        (sin(thA) ^ 2) * (vA ^ 2)
                        +
                        4 * (cos(th) ^ -2) * (cos(thA) ^ 2) * sin(th) *
                        (sin(th) - cos(th) * (cos(thA) ^ -1) * sin(thA)) *
                        (vA ^ 2)));

                //"numeric:".Disp();

                //numeric(objB.velocity.y).Disp();

                AssertEqual(
                    numeric(objB.velocity.y),
                    -35.010338462805755);
            }

            #endregion

            #region PSE 5E PROBLEM 4.11

            {
                // One strategy in a snowball fight is to throw a first snowball at a
                // high angle over level ground. While your opponent is watching the
                // first one, you throw a second one at a low angle and timed to arrive
                // at your opponent before or at the same time as the first one. Assume
                // both snowballs are thrown with a speed of 25.0 m/s. The first one is
                // thrown at an angle of 70.0° with respect to the horizontal.
                //
                // (a) At what angle should the second (low-angle) snowball be thrown
                // if it is to land at the same point as the first?
                //
                // (b) How many seconds later should the second snowball be thrown if it
                // is to land at the same time as the first?

                var xA = new Symbol("xA");      // position.x at point A
                var yA = new Symbol("yA");      // position.y at point A
                var th1A = new Symbol("th1A");  // angle of snowball 1 at point A
                var vA = new Symbol("vA");      // velocity at point A

                var g = new Symbol("g");        // magnitude of gravity
                var _g = new Point(0, -g);      // gravity vector

                //Func<MathObject, MathObject> numeric = obj =>
                //    obj
                //        .Substitute(xA, 0)
                //        .Substitute(xB, 1.4)
                //        .Substitute(yA, 0.86)
                //        .Substitute(g, 9.8)
                //        .Substitute(Trig.Pi, 3.14159);

                var obj1A = new Obj()           // snowball 1 at initial point
                {
                    position = new Point(xA, yA),
                    velocity = Point.FromAngle(th1A, vA),
                    acceleration = _g,
                    time = 0
                };

                var obj1B = new Obj()            // snowball 1 at final point
                {
                    position = new Point(null, 0),
                    velocity = new Point(obj1A.velocity.x, null),
                    acceleration = _g
                };

                var time1B = Calc.Time(obj1A, obj1B, 1);

                obj1B = obj1A.AtTime(time1B);

                var obj2A = new Obj()           // snowball 2 at initial point
                {
                    position = obj1A.position,
                    speed = vA,
                    acceleration = _g
                };

                var obj2B = new Obj()           // snowball 2 at final point
                {
                    position = obj1B.position,
                    acceleration = _g
                };

                //Calc.InitialAngle(obj2A, obj2B, 1, 0)
                //    .Substitute(yA, 0)
                //    .Substitute(th1A, (70).ToRadians())
                //    .Substitute(vA, 25)
                //    .Substitute(Trig.Pi, 3.14159)
                //    .Substitute(g, 9.8)
                //    .ToDegrees()
                //    .Substitute(Trig.Pi, 3.14159)
                //    .Disp();

                var th2 = Calc.InitialAngle(obj2A, obj2B, 0, 0);

                //("At what angle should the second (low-angle) snowball " +
                //"be thrown if it is to land at the same point as the first?").Disp();

                //"".Disp();

                //"symbolic:".Disp();

                //th2.Disp(); "".Disp();

                //"numeric:".Disp();

                AssertEqual(
                    th2
                        .ToDegrees()
                        .Substitute(yA, 0)
                        .Substitute(th1A, (70).ToRadians())
                        .Substitute(vA, 25)
                        .Substitute(g, 9.8)
                        .Substitute(Trig.Pi, Math.PI),
                    20.000000000000007);

                //"".Disp();

                obj2A.velocity = Point.FromAngle(th2, vA);

                var time2B = Calc.Time(obj2A, obj2B, 1);

                //("How many seconds later should the second snowball be thrown if it " +
                //"is to land at the same time as the first?").Disp();

                //"".Disp();

                //"symbolic:".Disp();

                //(time1B - time2B).Disp(); "".Disp();

                //"numeric:".Disp();

                //(time1B - time2B)
                //    .Substitute(yA, 0)
                //    .Substitute(th1A, (70).ToRadians())
                //    .Substitute(vA, 25)
                //    .Substitute(Trig.Pi, 3.14159)
                //    .Substitute(g, 9.8)
                //    .Disp();

                AssertEqual(
                    (time1B - time2B)
                        .Substitute(yA, 0)
                        .Substitute(th1A, (70).ToRadians())
                        .Substitute(vA, 25)
                        .Substitute(Trig.Pi, 3.14159)
                        .Substitute(g, 9.8),
                    3.0493426265020469);

                //Console.ReadLine();
            }

            #endregion

            #region PSE 5E PROBLEM 4.17

            {
                // A cannon with a muzzle speed of 1 000 m/s is used to
                // start an avalanche on a mountain slope. The target is
                // 2 000 m from the cannon horizontally and 800 m above
                // the cannon. At what angle, above the horizontal, should
                // the cannon be fired?

                var xA = new Symbol("xA");      // position.x at point A
                var yA = new Symbol("yA");      // position.y at point A
                var thA = new Symbol("thA");  // angle of snowball 1 at point A
                var vA = new Symbol("vA");      // velocity at point A

                var xB = new Symbol("xB");      // position.x at point A
                var yB = new Symbol("yB");      // position.y at point A

                var g = new Symbol("g");        // magnitude of gravity
                var _g = new Point(0, -g);      // gravity vector

                var objA = new Obj()
                {
                    position = new Point(xA, yA),
                    speed = vA,
                    acceleration = _g,
                    time = 0
                };

                var objB = new Obj()
                {
                    position = new Point(xB, yB),
                    acceleration = _g
                };

                //"At what angle, above the horizontal, should the cannon be fired?".Disp();

                AssertEqual(
                    Calc.InitialAngle(objA, objB)
                        .ToDegrees()
                        .Substitute(xA, 0)
                        .Substitute(yA, 0)
                        .Substitute(xB, 2000.0)
                        .Substitute(yB, 800)
                        .Substitute(vA, 1000)
                        .Substitute(g, 9.8)
                        .Substitute(Trig.Pi, Math.PI),
                    22.365163229244317);

                //Calc.InitialAngle(objA, objB)
                //    .ToDegrees()
                //    .Substitute(xA, 0)
                //    .Substitute(yA, 0)
                //    .Substitute(xB, 2000.0)
                //    .Substitute(yB, 800)
                //    .Substitute(vA, 1000)
                //    .Substitute(g, 9.8)
                //    .Substitute(Trig.Pi, Math.PI)
                //    .Disp();
            }

            #endregion

            #region PSE 5E PROBLEM 4.24
            {
                // A bag of cement of weight 325 N hangs from three
                // wires as shown in Figure P5.24. Two of the wires make
                // angles th1 = 60.0° and th2 = 25.0° with the horizontal. If
                // the system is in equilibrium, find the tensions
                // T1, T2, and T3 in the wires.

                var F1 = new Symbol("F1");
                var F2 = new Symbol("F2");
                var F3 = new Symbol("F3");

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2");
                var th3 = new Symbol("th3");

                var _F1 = new Point() { angle = th1 };
                var _F2 = new Point() { angle = th2 };
                var _F3 = new Point() { magnitude = F3, angle = th3 };

                var m = new Symbol("m");

                var obj = new Obj();

                obj.acceleration.x = 0;
                obj.acceleration.y = 0;

                obj.mass = m;

                obj.forces.Add(_F1);
                obj.forces.Add(_F2);
                obj.forces.Add(_F3);

                //"F1 magnitude, symbolic:".Disp(); "".Disp();

                //obj.ForceMagnitude(_F1).Disp(); "".Disp();

                //"F1 magnitude, numeric:".Disp(); "".Disp();

                //obj.ForceMagnitude(_F1)
                //    .Substitute(F3, 325)
                //    .Substitute(th1, (180 - 60).ToRadians())
                //    .Substitute(th2, (25).ToRadians())
                //    .Substitute(th3, (270).ToRadians())
                //    .Substitute(Trig.Pi, Math.PI)
                //    .Disp();

                AssertEqual(
                    obj.ForceMagnitude(_F1)
                        .Substitute(F3, 325)
                        .Substitute(th1, (180 - 60).ToRadians())
                        .Substitute(th2, (25).ToRadians())
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(Trig.Pi, Math.PI),
                    295.67516405290525);

                // "".Disp();

                //"F3 magnitude, numeric:".Disp(); "".Disp();

                //obj.ForceMagnitude(_F2)
                //    .Substitute(F3, 325)
                //    .Substitute(th1, (180 - 60).ToRadians())
                //    .Substitute(th2, (25).ToRadians())
                //    .Substitute(th3, (270).ToRadians())
                //    .Substitute(Trig.Pi, Math.PI)
                //    .Disp();

                AssertEqual(
                    obj.ForceMagnitude(_F2)
                        .Substitute(F3, 325)
                        .Substitute(th1, (180 - 60).ToRadians())
                        .Substitute(th2, (25).ToRadians())
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(Trig.Pi, Math.PI),
                    163.12072360079395);
            }
            #endregion

            #region PSE 5E PROBLEM 5.26
            {
                // You are a judge in a children’s kite-flying contest, and
                // two children will win prizes for the kites that pull most
                // strongly and least strongly on their strings. To measure
                // string tensions, you borrow a weight hanger, some slotted
                // weights, and a protractor from your physics teacher
                // and use the following protocol, illustrated in Figure
                // P5.26: Wait for a child to get her kite well-controlled,
                // hook the hanger onto the kite string about 30 cm from
                // her hand, pile on weights until that section of string is
                // horizontal, record the mass required, and record the
                // angle between the horizontal and the string running up
                // to the kite. (a) Explain how this method works. As you
                // construct your explanation, imagine that the children’s
                // parents ask you about your method, that they might
                // make false assumptions about your ability without concrete
                // evidence, and that your explanation is an opportunity to
                // give them confidence in your evaluation tech-nique.
                // (b) Find the string tension if the mass required
                // to make the string horizontal is 132 g and the angle of
                // the kite string is 46.3°.

                var F1 = new Symbol("F1");
                var F2 = new Symbol("F2");
                var F3 = new Symbol("F3");

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2");
                var th3 = new Symbol("th3");

                var _F1 = new Point() { angle = th1 };
                var _F2 = new Point() { angle = th2 };
                var _F3 = new Point() { magnitude = F3, angle = th3 };

                var m = new Symbol("m");

                var obj = new Obj();

                obj.acceleration.x = 0;
                obj.acceleration.y = 0;

                obj.mass = m;

                obj.forces.Add(_F1);
                obj.forces.Add(_F2);
                obj.forces.Add(_F3);

                //"Tension in line to kite:".Disp(); "".Disp();

                //obj.ForceMagnitude(_F2)
                //    .Substitute(th1, (180).ToRadians())
                //    .Substitute(th2, (46.3 * Math.PI / 180))
                //    .Substitute(th3, (270).ToRadians())
                //    .Substitute(F3, 0.132 * 9.8)
                //    .Substitute(Trig.Pi, Math.PI)
                //    .Disp();

                AssertEqual(
                    obj.ForceMagnitude(_F2)
                        .Substitute(th1, (180).ToRadians())
                        .Substitute(th2, (46.3 * Math.PI / 180))
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(F3, 0.132 * 9.8)
                        .Substitute(Trig.Pi, Math.PI),
                    1.7892929261294661);

                //Console.ReadLine();
            }
            #endregion

            #region PSE 5E PROBLEM 5.28
            {
                // A fire helicopter carries a 620-kg bucket of water at the
                // end of a cable 20.0 m long. As the aircraft flies back
                // from a fire at a constant speed of 40.0 m/s, the cable
                // makes an angle of 40.0° with respect to the vertical.
                // (a) Determine the force of air resistance on the bucket.
                // (b) After filling the bucket with sea water, the pilot re-
                // turns to the fire at the same speed with the bucket now
                // making an angle of 7.00° with the vertical. What is the
                // mass of the water in the bucket?

                var F1 = new Symbol("F1"); // force of air resistance
                var F2 = new Symbol("F2"); // force of cable
                var F3 = new Symbol("F3"); // force of gravity

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2");
                var th3 = new Symbol("th3");

                var _F1 = new Point() { angle = th1 };
                var _F2 = new Point() { angle = th2 };
                var _F3 = new Point() { magnitude = F3, angle = th3 };

                var m = new Symbol("m");

                var obj = new Obj();

                obj.acceleration.x = 0;
                obj.acceleration.y = 0;

                obj.mass = m;

                obj.forces.Add(_F1);
                obj.forces.Add(_F2);
                obj.forces.Add(_F3);

                //"Force of air resistance on the bucket:".Disp(); "".Disp();

                var FAir =
                    obj.ForceMagnitude(_F1)
                        .Substitute(F3, 620 * 9.8)
                        .Substitute(th1, (180).ToRadians())
                        .Substitute(th2, (90 - 40).ToRadians())
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(Trig.Pi, Math.PI);

                AssertEqual(
                    obj.ForceMagnitude(_F1)
                        .Substitute(F3, 620 * 9.8)
                        .Substitute(th1, (180).ToRadians())
                        .Substitute(th2, (90 - 40).ToRadians())
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(Trig.Pi, Math.PI),
                    5098.3693590331513);

                //"".Disp();

                _F1.magnitude = FAir;

                _F3.magnitude = null;

                var FBucketWithWater =
                    obj.ForceMagnitude(_F3)
                        .Substitute(th1, (180).ToRadians())
                        .Substitute(th2, (90 - 7).ToRadians())
                        .Substitute(th3, (270).ToRadians())
                        .Substitute(Trig.Pi, Math.PI);

                //"What is the mass of the water in the bucket?".Disp(); "".Disp();

                //(FBucketWithWater / 9.8 - 620).Disp();

                AssertEqual(
                    (FBucketWithWater / 9.8 - 620),
                    3617.0292120139611);
            }
            #endregion

            #region PSE 5E PROBLEM 5.30
            {
                // A simple accelerometer is constructed by suspending a
                // mass m from a string of length L that is tied to the top
                // of a cart. As the cart is accelerated the string-mass
                // system makes a constant angle th with the vertical.
                // (a) Assuming that the string mass is negligible compared
                // with m, derive an expression for the cart’s acceleration
                // in terms of and show that it is independent of
                // the mass mand the length L.
                // (b) Determine the acceleration of the cart when th = 23.0°.

                var F1 = new Symbol("F1"); // force of string
                var F2 = new Symbol("F2"); // force of gravity

                var th1 = new Symbol("th1");
                var th2 = new Symbol("th2"); ;

                var _F1 = new Point() { angle = th1 };
                var _F2 = new Point() { angle = th2, magnitude = F2 };

                var m = new Symbol("m");

                var g = new Symbol("g");

                var obj = new Obj() { mass = m };

                obj.acceleration.y = 0;

                obj.forces.Add(_F1);
                obj.forces.Add(_F2);

                _F1.magnitude = obj.ForceMagnitude(_F1);

                //("Derive an expression for the cart’s acceleration in terms " +
                //"of and show that it is independent of the mass mand the length L:").Disp();

                //"".Disp();

                //obj.AccelerationX()
                //    .Substitute(F2, m * g)
                //    .Substitute(Trig.Cos(th2), 0)
                //    .Substitute(Trig.Sin(th2), -1)
                //    .Disp();

                //"".Disp();

                //"Determine the acceleration of the cart when th = 23.0°".Disp(); "".Disp();

                //obj.AccelerationX()
                //    .Substitute(F2, m * g)
                //    .Substitute(Trig.Cos(th2), 0)
                //    .Substitute(Trig.Sin(th2), -1)
                //    .Substitute(th1, (90 - 23).ToRadians())
                //    .Substitute(Trig.Pi, Math.PI)
                //    .Substitute(g, 9.8)
                //    .Disp();

                AssertEqual(
                    obj.AccelerationX()
                        .Substitute(F2, m * g)
                        .Substitute(Trig.Cos(th2), 0)
                        .Substitute(Trig.Sin(th2), -1)
                        .Substitute(th1, (90 - 23).ToRadians())
                        .Substitute(Trig.Pi, Math.PI)
                        .Substitute(g, 9.8),
                    4.1598531988541261);
            }
            #endregion

            #region PSE 5E PROBLEM 5.31
            {
                // Two people pull as hard as they can on ropes attached
                // to a boat that has a mass of 200 kg. If they pull in the
                // same direction, the boat has an acceleration of
                // 1.52 m/s^2 to the right. If they pull in opposite directions,
                // the boat has an acceleration of 0.518 m/s^2
                // to the left. What is the force exerted by each person on the
                // boat? (Disregard any other forces on the boat.)

                // Trig.Cos(new DoubleFloat(Math.PI)).Disp();

                var m = new Symbol("m");

                var aAx = new Symbol("aAx");
                var aBx = new Symbol("aBx");

                var objA = new Obj() { mass = m };

                objA.acceleration.x = aAx;

                var _F1A = new Point() { angle = 0 };
                var _F2A = new Point() { angle = 0 };

                objA.forces.Add(_F1A);
                objA.forces.Add(_F2A);

                var objB = new Obj() { mass = m };

                objB.acceleration.x = aBx;

                var _F1B = new Point() { angle = 0 };
                var _F2B = new Point() { angle = new DoubleFloat(Math.PI) };

                objB.forces.Add(_F1B);
                objB.forces.Add(_F2B);

                //"force 1 magnitude (symbolic):".Disp(); "".Disp();

                //Calc.ForceMagnitude(objA, objB, _F1A, _F1B)
                //    .Substitute(Trig.Cos(0), 1)
                //    .Disp();

                //"force 1 magnitude (numeric):".Disp(); "".Disp();

                //Calc.ForceMagnitude(objA, objB, _F1A, _F1B)
                //    .Substitute(Trig.Cos(0), 1)
                //    .Substitute(m, 200)
                //    .Substitute(aAx, 1.52)
                //    .Substitute(aBx, -0.518)
                //    .Disp();

                AssertEqual(
                    Calc.ForceMagnitude(objA, objB, _F1A, _F1B)
                        .Substitute(Trig.Cos(0), 1)
                        .Substitute(m, 200)
                        .Substitute(aAx, 1.52)
                        .Substitute(aBx, -0.518),
                    100.19999999999999);

                //"".Disp();

                //"force 2 magnitude (symbolic):".Disp(); "".Disp();

                //Calc.ForceMagnitude(objA, objB, _F2A, _F2B)
                //    .Substitute(Trig.Cos(0), 1)
                //    .Disp();

                //"force 2 magnitude (numeric):".Disp(); "".Disp();

                //Calc.ForceMagnitude(objA, objB, _F2A, _F2B)
                //    .Substitute(Trig.Cos(0), 1)
                //    .Substitute(m, 200)
                //    .Substitute(aAx, 1.52)
                //    .Substitute(aBx, -0.518)
                //    .Disp();

                //"".Disp();

                AssertEqual(
                    Calc.ForceMagnitude(objA, objB, _F2A, _F2B)
                        .Substitute(Trig.Cos(0), 1)
                        .Substitute(m, 200)
                        .Substitute(aAx, 1.52)
                        .Substitute(aBx, -0.518),
                    203.8);

            }
            #endregion

            Console.WriteLine("Testing complete");

            Console.ReadLine();
        }
Ejemplo n.º 52
0
        public void ExecuteTest4()
        {
            var exp = new And(new Bool(true), new Bool(true));

            Assert.Equal(true, exp.Execute());
        }
Ejemplo n.º 53
0
        public void ResultTypeNumberNumberTest()
        {
            var exp = new And(new Number(2), new Number(4));

            Assert.Equal(ExpressionResultType.Number, exp.ResultType);
        }
Ejemplo n.º 54
0
	public void And(INode node)
	{
		And newRoot = new And(root,node);
		root = newRoot;
	}