Esempio n. 1
0
    def constrain(self, par, con, ns={}):
        """Constrain a parameter to an equation.

        Note that only one constraint can exist on a Parameter at a time.

        par     --  The name of a Parameter or a Parameter to constrain.
        con     --  A string representation of the constraint equation or a
                    Parameter to constrain to.  A constraint equation must
                    consist of numpy operators and "known" Parameters.
                    Parameters are known if they are in the ns argument, or if
                    they are managed by this object.
        ns      --  A dictionary of Parameters, indexed by name, that are used
                    in the parameter, but not part of this object (default {}).

        Raises ValueError if ns uses a name that is already used for a
        variable.
        Raises ValueError if par is a string but not part of this object or in
        ns.
        Raises ValueError if par is marked as constant.
        """
        if isinstance(par, basestring):
            name = par
            par = self.get(name)
            if par is None:
                par = ns.get(name)

        if par is None:
            raise ValueError("The parameter cannot be found")

        if par.const:
            raise ValueError("The parameter '%s' is constant" % par)

        if isinstance(con, basestring):
            eqstr = con
            eq = equationFromString(con, self._eqfactory, ns)
        else:
            eq = Equation(root=con)
            eqstr = con.name

        eq.name = "_constraint_%s" % par.name

        # Make and store the constraint
        con = Constraint()
        con.constrain(par, eq)
        # Store the equation string so it can be shown later.
        con.eqstr = eqstr
        self._constraints[par] = con

        # Our configuration changed
        self._updateConfiguration()

        return
Esempio n. 2
0
    def constrain(self, par, con, ns={}):
        """Constrain a parameter to an equation.

        Note that only one constraint can exist on a Parameter at a time.

        par     --  The name of a Parameter or a Parameter to constrain.
        con     --  A string representation of the constraint equation or a
                    Parameter to constrain to.  A constraint equation must
                    consist of numpy operators and "known" Parameters.
                    Parameters are known if they are in the ns argument, or if
                    they are managed by this object.
        ns      --  A dictionary of Parameters, indexed by name, that are used
                    in the parameter, but not part of this object (default {}).

        Raises ValueError if ns uses a name that is already used for a
        variable.
        Raises ValueError if par is a string but not part of this object or in
        ns.
        Raises ValueError if par is marked as constant.
        """
        if isinstance(par, basestring):
            name = par
            par = self.get(name)
            if par is None:
                par = ns.get(name)

        if par is None:
            raise ValueError("The parameter cannot be found")

        if par.const:
            raise ValueError("The parameter '%s' is constant" % par)

        if isinstance(con, basestring):
            eqstr = con
            eq = equationFromString(con, self._eqfactory, ns)
        else:
            eq = Equation(root=con)
            eqstr = con.name

        eq.name = "_constraint_%s" % par.name

        # Make and store the constraint
        con = Constraint()
        con.constrain(par, eq)
        # Store the equation string so it can be shown later.
        con.eqstr = eqstr
        self._constraints[par] = con

        # Our configuration changed
        self._updateConfiguration()

        return
Esempio n. 3
0
    def restrain(self, res, lb=-inf, ub=inf, sig=1, scaled=False, ns={}):
        """Restrain an expression to specified bounds

        res     --  An equation string or Parameter to restrain.
        lb      --  The lower bound on the restraint evaluation (default -inf).
        ub      --  The lower bound on the restraint evaluation (default inf).
        sig     --  The uncertainty on the bounds (default 1).
        scaled  --  A flag indicating if the restraint is scaled (multiplied)
                    by the unrestrained point-average chi^2 (chi^2/numpoints)
                    (default False).
        ns      --  A dictionary of Parameters, indexed by name, that are used
                    in the equation string, but not part of the RecipeOrganizer
                    (default {}).

        The penalty is calculated as
        (max(0, lb - val, val - ub)/sig)**2
        and val is the value of the calculated equation.  This is multipled by
        the average chi^2 if scaled is True.

        Raises ValueError if ns uses a name that is already used for a
        Parameter.
        Raises ValueError if res depends on a Parameter that is not part of
        the RecipeOrganizer and that is not defined in ns.

        Returns the Restraint object for use with the 'unrestrain' method.
        """

        if isinstance(res, basestring):
            eqstr = res
            eq = equationFromString(res, self._eqfactory, ns)
        else:
            eq = Equation(root=res)
            eqstr = res.name

        # Make and store the restraint
        res = Restraint(eq, lb, ub, sig, scaled)
        res.eqstr = eqstr
        self.addRestraint(res)
        return res
Esempio n. 4
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
Esempio n. 5
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