Esempio n. 1
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4 = _makeArgs(4)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation (v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Set the values of the variables.
        # The equation should evaluate to (1+3)*(4-2) = 8
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)

        # now get the args
        args = visitors.getArgs(mult)
        self.assertEqual(4, len(args))
        self.assertTrue(v1 in args)
        self.assertTrue(v2 in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)

        return
Esempio n. 2
0
    def testRegisterOperator(self):
        """Try to use an operator without arguments in an equation."""

        factory = builder.EquationFactory()
        v1, v2, v3, v4 = _makeArgs(4)

        op = literals.AdditionOperator()

        op.addLiteral(v1)
        op.addLiteral(v2)

        factory.registerArgument("v3", v3)
        factory.registerArgument("v4", v4)
        factory.registerOperator("op", op)

        # Build an equation where op is treated as a terminal node
        eq = factory.makeEquation("op")
        self.assertAlmostEqual(3, eq())

        eq = factory.makeEquation("v3*op")
        self.assertAlmostEqual(9, eq())

        # Now use the op like a function
        eq = factory.makeEquation("op(v3, v4)")
        self.assertAlmostEqual(7, eq())

        # Make sure we can still access op as itself.
        eq = factory.makeEquation("op")
        self.assertAlmostEqual(3, eq())

        self.assertTrue(noObserversInGlobalBuilders())
        return
Esempio n. 3
0
    def testRegisterOperator(self):
        """Try to use an operator without arguments in an equation."""

        factory = builder.EquationFactory()
        v1, v2, v3, v4 = _makeArgs(4)

        op = literals.AdditionOperator()

        op.addLiteral(v1)
        op.addLiteral(v2)

        factory.registerArgument("v3", v3)
        factory.registerArgument("v4", v4)
        factory.registerOperator("op", op)

        # Build an equation where op is treated as a terminal node
        eq = factory.makeEquation("op")
        self.assertAlmostEqual(3, eq())

        eq = factory.makeEquation("v3*op")
        self.assertAlmostEqual(9, eq())

        # Now use the op like a function
        eq = factory.makeEquation("op(v3, v4)")
        self.assertAlmostEqual(7, eq())

        # Make sure we can still access op as itself.
        eq = factory.makeEquation("op")
        self.assertAlmostEqual(3, eq())

        self.assertTrue(noObserversInGlobalBuilders())
        return
Esempio n. 4
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4 = _makeArgs(4)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation (v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Set the values of the variables.
        # The equation should evaluate to (1+3)*(4-2) = 8
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)

        # now get the args
        args = visitors.getArgs(mult)
        self.assertEqual(4, len(args))
        self.assertTrue(v1 in args)
        self.assertTrue(v2 in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)

        return
Esempio n. 5
0
    def testSwapping(self):
        def g1(v1, v2, v3, v4):
            return (v1 + v2) * (v3 + v4)

        def g2(v1):
            return 0.5 * v1

        factory = builder.EquationFactory()
        v1, v2, v3, v4, v5 = _makeArgs(5)

        factory.registerArgument("v1", v1)
        factory.registerArgument("v2", v2)
        factory.registerArgument("v3", v3)
        factory.registerArgument("v4", v4)
        b = factory.registerFunction("g", g1, ["v1", "v2", "v3", "v4"])

        # Now associate args with the wrapped function
        op = b.literal
        self.assertTrue(op.operation == g1)
        self.assertTrue(v1 in op.args)
        self.assertTrue(v2 in op.args)
        self.assertTrue(v3 in op.args)
        self.assertTrue(v4 in op.args)
        self.assertAlmostEqual(21, op.value)

        eq1 = factory.makeEquation("g")
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(21, eq1())

        # Swap out an argument by registering it under a taken name
        b = factory.registerArgument("v4", v5)
        self.assertTrue(factory.builders["v4"] is b)
        self.assertTrue(b.literal is v5)
        self.assertTrue(op._value is None)
        self.assertTrue(op.args == [v1, v2, v3, v5])
        self.assertAlmostEqual(24, eq1())

        # Now swap out the function
        b = factory.registerFunction("g", g2, ["v1"])
        op = b.literal
        self.assertTrue(op.operation == g2)
        self.assertTrue(v1 in op.args)
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(0.5, op.value)
        self.assertAlmostEqual(0.5, eq1())

        # Make an equation
        eqeq = factory.makeEquation("v1 + v2")
        # Register this "g"
        b = factory.registerFunction("g", eqeq, eqeq.argdict.keys())
        op = b.literal
        self.assertTrue(v1 in op.args)
        self.assertTrue(v2 in op.args)
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(3, op.value)
        self.assertAlmostEqual(3, eq1())

        self.assertTrue(noObserversInGlobalBuilders())
        return
Esempio n. 6
0
    def testSwapping(self):

        def g1(v1, v2, v3, v4):
            return (v1 + v2) * (v3 + v4)
        def g2(v1):
            return 0.5*v1

        factory = builder.EquationFactory()
        v1, v2, v3, v4, v5 = _makeArgs(5)

        factory.registerArgument("v1", v1)
        factory.registerArgument("v2", v2)
        factory.registerArgument("v3", v3)
        factory.registerArgument("v4", v4)
        b = factory.registerFunction("g", g1, ["v1", "v2", "v3", "v4"])

        # Now associate args with the wrapped function
        op = b.literal
        self.assertTrue(op.operation == g1)
        self.assertTrue(v1 in op.args)
        self.assertTrue(v2 in op.args)
        self.assertTrue(v3 in op.args)
        self.assertTrue(v4 in op.args)
        self.assertAlmostEqual(21, op.value)

        eq1 = factory.makeEquation("g")
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(21, eq1())

        # Swap out an argument by registering it under a taken name
        b = factory.registerArgument("v4", v5)
        self.assertTrue(factory.builders["v4"] is b)
        self.assertTrue(b.literal is v5)
        self.assertTrue(op._value is None)
        self.assertTrue(op.args == [v1, v2, v3, v5])
        self.assertAlmostEqual(24, eq1())

        # Now swap out the function
        b = factory.registerFunction("g", g2, ["v1"])
        op = b.literal
        self.assertTrue(op.operation == g2)
        self.assertTrue(v1 in op.args)
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(0.5, op.value)
        self.assertAlmostEqual(0.5, eq1())

        # Make an equation
        eqeq = factory.makeEquation("v1 + v2")
        # Register this "g"
        b = factory.registerFunction("g", eqeq, eqeq.argdict.keys())
        op = b.literal
        self.assertTrue(v1 in op.args)
        self.assertTrue(v2 in op.args)
        self.assertTrue(eq1.root is op)
        self.assertAlmostEqual(3, op.value)
        self.assertAlmostEqual(3, eq1())

        self.assertTrue(noObserversInGlobalBuilders())
        return
Esempio n. 7
0
    def testArg(self):
        """Test just an Argument equation."""
        # Make some variables
        v1 = _makeArgs(1)[0]

        args = visitors.getArgs(v1)

        self.assertEqual(1, len(args))
        self.assertTrue(args[0] is v1)
        return
Esempio n. 8
0
    def testArg(self):
        """Test just an Argument equation."""
        # Make some variables
        v1 = _makeArgs(1)[0]

        args = visitors.getArgs(v1)

        self.assertEqual(1, len(args))
        self.assertTrue(args[0] is v1)
        return
Esempio n. 9
0
def makeLazyEquation():
    """Make a lazy equation and see how fast it is."""

    # Make some variables
    v1, v2, v3, v4, v5, v6, v7 = _makeArgs(7)

    # Make some operations
    mult = literals.MultiplicationOperator()
    plus = literals.AdditionOperator()
    minus = literals.SubtractionOperator()
    pow = literals.ExponentiationOperator()
    exp = literals.ExponentiationOperator()
    mult2 = literals.MultiplicationOperator()

    # Create the equation ((v1+v2)*(v3-v4))**v5 * v6^v7
    plus.addLiteral(v1)
    plus.addLiteral(v2)
    minus.addLiteral(v3)
    minus.addLiteral(v4)
    mult.addLiteral(plus)
    mult.addLiteral(minus)
    pow.addLiteral(mult)
    pow.addLiteral(v5)
    exp.addLiteral(v6)
    exp.addLiteral(v7)
    mult2.addLiteral(pow)
    mult2.addLiteral(exp)

    v2.setValue(x)
    v3.setValue(50*x)
    v5.setValue(2.11)
    v6.setValue(numpy.e)

    evaluator = visitors.Evaluator()

    def _f(a, b, c, d, e):
        v1.setValue(a)
        v4.setValue(b)
        v5.setValue(c)
        v6.setValue(d)
        v7.setValue(e)
        mult2.identify(evaluator)
        evaluator.clicker.click()
        return evaluator.value

    return _f
Esempio n. 10
0
def makeLazyEquation():
    """Make a lazy equation and see how fast it is."""

    # Make some variables
    v1, v2, v3, v4, v5, v6, v7 = _makeArgs(7)

    # Make some operations
    mult = literals.MultiplicationOperator()
    plus = literals.AdditionOperator()
    minus = literals.SubtractionOperator()
    pow = literals.ExponentiationOperator()
    exp = literals.ExponentiationOperator()
    mult2 = literals.MultiplicationOperator()

    # Create the equation ((v1+v2)*(v3-v4))**v5 * v6^v7
    plus.addLiteral(v1)
    plus.addLiteral(v2)
    minus.addLiteral(v3)
    minus.addLiteral(v4)
    mult.addLiteral(plus)
    mult.addLiteral(minus)
    pow.addLiteral(mult)
    pow.addLiteral(v5)
    exp.addLiteral(v6)
    exp.addLiteral(v7)
    mult2.addLiteral(pow)
    mult2.addLiteral(exp)

    v2.setValue(x)
    v3.setValue(50 * x)
    v5.setValue(2.11)
    v6.setValue(numpy.e)

    evaluator = visitors.Evaluator()

    def _f(a, b, c, d, e):
        v1.setValue(a)
        v4.setValue(b)
        v5.setValue(c)
        v6.setValue(d)
        v7.setValue(e)
        mult2.identify(evaluator)
        evaluator.clicker.click()
        return evaluator.value

    return _f
Esempio n. 11
0
    def testRegisterArg(self):

        factory = builder.EquationFactory()

        v1 = _makeArgs(1)[0]

        b1 = factory.registerArgument("v1", v1)
        self.assertTrue(factory.builders["v1"] is b1)
        self.assertTrue(b1.literal is v1)

        eq = factory.makeEquation("v1")

        self.assertTrue(v1 is eq.args[0])
        self.assertEquals(1, len(eq.args))

        # Try to parse an equation with buildargs turned off
        self.assertRaises(ValueError, factory.makeEquation, "v1 + v2", False)

        # Make sure we can still use constants
        eq = factory.makeEquation("v1 + 2", False)
        self.assertTrue(v1 is eq.args[0])
        self.assertEquals(1, len(eq.args))
        return
Esempio n. 12
0
    def testRegisterArg(self):

        factory = builder.EquationFactory()

        v1 = _makeArgs(1)[0]

        b1 = factory.registerArgument("v1", v1)
        self.assertTrue(factory.builders["v1"] is b1)
        self.assertTrue(b1.literal is v1)

        eq = factory.makeEquation("v1")

        self.assertTrue(v1 is eq.args[0])
        self.assertEquals(1, len(eq.args))

        # Try to parse an equation with buildargs turned off
        self.assertRaises(ValueError, factory.makeEquation, "v1 + v2", False)

        # Make sure we can still use constants
        eq = factory.makeEquation("v1 + 2", False)
        self.assertTrue(v1 is eq.args[0])
        self.assertEquals(1, len(eq.args))
        return
Esempio n. 13
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4, v5 = _makeArgs(5)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation (v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Set the values of the variables.
        # The equation should evaluate to (1+3)*(4-2) = 8
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)
        v5.setValue(5)

        # Evaluate
        self.assertEqual(8, mult.value)

        # Now swap an argument
        visitors.swap(mult, v2, v5)

        # Check that the operator value is invalidated
        self.assertTrue(mult._value is None)
        self.assertFalse(v2.hasObserver(minus._flush))
        self.assertTrue(v5.hasObserver(minus._flush))

        # now get the args
        args = visitors.getArgs(mult)
        self.assertEqual(4, len(args))
        self.assertTrue(v1 in args)
        self.assertTrue(v2 not in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)
        self.assertTrue(v5 in args)

        # Re-evaluate (1+3)*(4-5) = -4
        self.assertEqual(-4, mult.value)

        # Swap out the "-" operator
        plus2 = literals.AdditionOperator()
        visitors.swap(mult, minus, plus2)
        self.assertTrue(mult._value is None)
        self.assertFalse(minus.hasObserver(mult._flush))
        self.assertTrue(plus2.hasObserver(mult._flush))

        # plus2 has no arguments yet. Verify this.
        self.assertRaises(ValueError, mult.getValue)
        # Add the arguments to plus2.
        plus2.addLiteral(v4)
        plus2.addLiteral(v5)

        # Re-evaluate (1+3)*(4+5) = 36
        self.assertEqual(36, mult.value)

        return
Esempio n. 14
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4, c = _makeArgs(5)
        c.name = "c"
        c.const = True

        # Make some operations
        mult = literals.MultiplicationOperator()
        root = mult2 = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation c*(v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)
        mult2.addLiteral(mult)
        mult2.addLiteral(c)

        # Set the values of the variables.
        # The equation should evaluate to 2.5*(1+3)*(4-2) = 20
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)
        c.setValue(2.5)

        # Make an equation and test
        eq = Equation("eq", mult2)

        self.assertTrue(eq._value is None)
        args = eq.args
        self.assertTrue(v1 in args)
        self.assertTrue(v2 in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)
        self.assertTrue(c not in args)
        self.assertTrue(root is eq.root)

        self.assertTrue(v1 is eq.v1)
        self.assertTrue(v2 is eq.v2)
        self.assertTrue(v3 is eq.v3)
        self.assertTrue(v4 is eq.v4)

        self.assertEqual(20, eq()) # 20 = 2.5*(1+3)*(4-2)
        self.assertEqual(20, eq.getValue()) # same as above
        self.assertEqual(20, eq.value) # same as above
        self.assertEqual(25, eq(v1=2)) # 25 = 2.5*(2+3)*(4-2)
        self.assertEqual(50, eq(v2=0)) # 50 = 2.5*(2+3)*(4-0)
        self.assertEqual(30, eq(v3=1)) # 30 = 2.5*(2+1)*(4-0)
        self.assertEqual(0, eq(v4=0)) # 20 = 2.5*(2+1)*(0-0)

        # Try some swapping
        eq.swap(v4, v1)
        self.assertTrue(eq._value is None)
        self.assertEqual(15, eq()) # 15 = 2.5*(2+1)*(2-0)
        args = eq.args
        self.assertTrue(v4 not in args)

        # Try to create a dependency loop
        self.assertRaises(ValueError, eq.swap, v1, eq.root)
        self.assertRaises(ValueError, eq.swap, v1, plus)
        self.assertRaises(ValueError, eq.swap, v1, minus)
        self.assertRaises(ValueError, eq.swap, v1, mult)
        self.assertRaises(ValueError, eq.swap, v1, root)

        # Swap the root
        eq.swap(eq.root, v1)
        self.assertTrue(eq._value is None)
        self.assertEqual(v1.value, eq())

        return
Esempio n. 15
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4, v5 = _makeArgs(5)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation (v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Set the values of the variables.
        # The equation should evaluate to (1+3)*(4-2) = 8
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)
        v5.setValue(5)

        # Evaluate
        self.assertEqual(8, mult.value)

        # Now swap an argument
        visitors.swap(mult, v2, v5)

        # Check that the operator value is invalidated
        self.assertTrue(mult._value is None)
        self.assertFalse(v2.hasObserver(minus._flush))
        self.assertTrue(v5.hasObserver(minus._flush))

        # now get the args
        args = visitors.getArgs(mult)
        self.assertEqual(4, len(args))
        self.assertTrue(v1 in args)
        self.assertTrue(v2 not in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)
        self.assertTrue(v5 in args)

        # Re-evaluate (1+3)*(4-5) = -4
        self.assertEqual(-4, mult.value)

        # Swap out the "-" operator
        plus2 = literals.AdditionOperator()
        visitors.swap(mult, minus, plus2)
        self.assertTrue(mult._value is None)
        self.assertFalse(minus.hasObserver(mult._flush))
        self.assertTrue(plus2.hasObserver(mult._flush))

        # plus2 has no arguments yet. Verify this.
        self.assertRaises(ValueError, mult.getValue)
        # Add the arguments to plus2.
        plus2.addLiteral(v4)
        plus2.addLiteral(v5)

        # Re-evaluate (1+3)*(4+5) = 36
        self.assertEqual(36, mult.value)

        return
Esempio n. 16
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4 = _makeArgs(4)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Let's hobble the plus operator
        plus.name = None
        plus.symbol = None
        plus.operation = None

        # Partially define the equation (v1+v3)*(v4-v2). Let's only give one
        # variable to the '-' operation.
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Now validate
        validator = visitors.Validator()
        mult.identify(validator)
        self.assertEqual(4, len(validator.errors))

        # Fix the equation
        minus.addLiteral(v3)
        validator.reset()
        mult.identify(validator)
        self.assertEqual(3, len(validator.errors))

        # Fix the name of plus
        plus.name = "add"
        validator.reset()
        mult.identify(validator)
        self.assertEqual(2, len(validator.errors))

        # Fix the symbol of plus
        plus.symbol = "+"
        validator.reset()
        mult.identify(validator)
        self.assertEqual(1, len(validator.errors))

        # Fix the operation of plus
        import numpy
        plus.operation = numpy.add
        validator.reset()
        mult.identify(validator)
        self.assertEqual(0, len(validator.errors))

        # Add another literal to minus
        minus.addLiteral(v1)
        validator.reset()
        mult.identify(validator)
        self.assertEqual(1, len(validator.errors))

        return
Esempio n. 17
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4 = _makeArgs(4)

        # Make some operations
        mult = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Let's hobble the plus operator
        plus.name = None
        plus.symbol = None
        plus.operation = None

        # Partially define the equation (v1+v3)*(v4-v2). Let's only give one
        # variable to the '-' operation.
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        mult.addLiteral(plus)
        mult.addLiteral(minus)

        # Now validate
        validator = visitors.Validator()
        mult.identify(validator)
        self.assertEqual(4, len(validator.errors))

        # Fix the equation
        minus.addLiteral(v3)
        validator.reset()
        mult.identify(validator)
        self.assertEqual(3, len(validator.errors))

        # Fix the name of plus
        plus.name = "add"
        validator.reset()
        mult.identify(validator)
        self.assertEqual(2, len(validator.errors))

        # Fix the symbol of plus
        plus.symbol = "+"
        validator.reset()
        mult.identify(validator)
        self.assertEqual(1, len(validator.errors))

        # Fix the operation of plus
        import numpy
        plus.operation = numpy.add
        validator.reset()
        mult.identify(validator)
        self.assertEqual(0, len(validator.errors))

        # Add another literal to minus
        minus.addLiteral(v1)
        validator.reset()
        mult.identify(validator)
        self.assertEqual(1, len(validator.errors))

        return
Esempio n. 18
0
    def testSimpleFunction(self):
        """Test a simple function."""

        # Make some variables
        v1, v2, v3, v4, c = _makeArgs(5)
        c.name = "c"
        c.const = True

        # Make some operations
        mult = literals.MultiplicationOperator()
        root = mult2 = literals.MultiplicationOperator()
        plus = literals.AdditionOperator()
        minus = literals.SubtractionOperator()

        # Create the equation c*(v1+v3)*(v4-v2)
        plus.addLiteral(v1)
        plus.addLiteral(v3)
        minus.addLiteral(v4)
        minus.addLiteral(v2)
        mult.addLiteral(plus)
        mult.addLiteral(minus)
        mult2.addLiteral(mult)
        mult2.addLiteral(c)

        # Set the values of the variables.
        # The equation should evaluate to 2.5*(1+3)*(4-2) = 20
        v1.setValue(1)
        v2.setValue(2)
        v3.setValue(3)
        v4.setValue(4)
        c.setValue(2.5)

        # Make an equation and test
        eq = Equation("eq", mult2)

        self.assertTrue(eq._value is None)
        args = eq.args
        self.assertTrue(v1 in args)
        self.assertTrue(v2 in args)
        self.assertTrue(v3 in args)
        self.assertTrue(v4 in args)
        self.assertTrue(c not in args)
        self.assertTrue(root is eq.root)

        self.assertTrue(v1 is eq.v1)
        self.assertTrue(v2 is eq.v2)
        self.assertTrue(v3 is eq.v3)
        self.assertTrue(v4 is eq.v4)

        self.assertEqual(20, eq())  # 20 = 2.5*(1+3)*(4-2)
        self.assertEqual(20, eq.getValue())  # same as above
        self.assertEqual(20, eq.value)  # same as above
        self.assertEqual(25, eq(v1=2))  # 25 = 2.5*(2+3)*(4-2)
        self.assertEqual(50, eq(v2=0))  # 50 = 2.5*(2+3)*(4-0)
        self.assertEqual(30, eq(v3=1))  # 30 = 2.5*(2+1)*(4-0)
        self.assertEqual(0, eq(v4=0))  # 20 = 2.5*(2+1)*(0-0)

        # Try some swapping
        eq.swap(v4, v1)
        self.assertTrue(eq._value is None)
        self.assertEqual(15, eq())  # 15 = 2.5*(2+1)*(2-0)
        args = eq.args
        self.assertTrue(v4 not in args)

        # Try to create a dependency loop
        self.assertRaises(ValueError, eq.swap, v1, eq.root)
        self.assertRaises(ValueError, eq.swap, v1, plus)
        self.assertRaises(ValueError, eq.swap, v1, minus)
        self.assertRaises(ValueError, eq.swap, v1, mult)
        self.assertRaises(ValueError, eq.swap, v1, root)

        # Swap the root
        eq.swap(eq.root, v1)
        self.assertTrue(eq._value is None)
        self.assertEqual(v1.value, eq())

        self.assertTrue(noObserversInGlobalBuilders())
        return