示例#1
0
    def test_vector_fitting(self):
        """
        Test the behavior in the presence of bounds or constraints: `Fit` should
        select `ConstrainedNumericalLeastSquares` when bounds or constraints are
        provided, or for vector models in general. For scalar models, use
        `NumericalLeastSquares`.
        """
        a, b, c = parameters('a, b, c')
        a_i, b_i, c_i = variables('a_i, b_i, c_i')

        model = {a_i: a, b_i: b, c_i: c}

        xdata = np.array([
            [10.1, 9., 10.5, 11.2, 9.5, 9.6, 10.],
            [102.1, 101., 100.4, 100.8, 99.2, 100., 100.8],
            [71.6, 73.2, 69.5, 70.2, 70.8, 70.6, 70.1],
        ])

        # Make a new scalar model.
        scalar_model = {a_i: a + b}
        simple_fit = Fit(
            model=scalar_model,
            a_i=xdata[0],
        )
        self.assertIsInstance(simple_fit.fit, NumericalLeastSquares)

        constrained_fit = Fit(model=scalar_model,
                              a_i=xdata[0],
                              constraints=[Equality(a + b, 110)])
        self.assertIsInstance(constrained_fit.fit,
                              ConstrainedNumericalLeastSquares)

        a.min = 0
        a.max = 25
        a.value = 10
        b.min = 80
        b.max = 120
        b.value = 100
        bound_fit = Fit(
            model=scalar_model,
            a_i=xdata[0],
        )
        self.assertIsInstance(bound_fit.fit, ConstrainedNumericalLeastSquares)

        # Repeat all of the above for the Vector model
        simple_fit = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=xdata[2],
        )
        self.assertIsInstance(simple_fit.fit, ConstrainedNumericalLeastSquares)

        constrained_fit = Fit(model=model,
                              a_i=xdata[0],
                              b_i=xdata[1],
                              c_i=xdata[2],
                              constraints=[Equality(a + b + c, 180)])
        self.assertIsInstance(constrained_fit.fit,
                              ConstrainedNumericalLeastSquares)

        a.min = 0
        a.max = 25
        a.value = 10
        b.min = 80
        b.max = 120
        b.value = 100
        bound_fit = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=xdata[2],
        )
        self.assertIsInstance(bound_fit.fit, ConstrainedNumericalLeastSquares)

        fit_result = bound_fit.execute()
        self.assertAlmostEqual(fit_result.value(a), np.mean(xdata[0]), 6)
        self.assertAlmostEqual(fit_result.value(b), np.mean(xdata[1]), 6)
        self.assertAlmostEqual(fit_result.value(c), np.mean(xdata[2]), 6)
示例#2
0
def test_vector_fitting():
    """
    Test the behavior in the presence of bounds or constraints: `Fit` should
    select `ConstrainedNumericalLeastSquares` when bounds or constraints are
    provided, or for vector models in general. For scalar models, use
    `NumericalLeastSquares`.
    """
    a, b = parameters('a, b')
    a_i, = variables('a_i')

    xdata = np.array([
        [10.1, 9., 10.5, 11.2, 9.5, 9.6, 10.],
        [102.1, 101., 100.4, 100.8, 99.2, 100., 100.8],
        [71.6, 73.2, 69.5, 70.2, 70.8, 70.6, 70.1],
    ])

    # Make a new scalar model.
    scalar_model = {a_i: a + b}
    simple_fit = Fit(model=scalar_model, a_i=xdata[0], minimizer=MINPACK)
    assert isinstance(simple_fit.minimizer, MINPACK)

    constrained_fit = Fit(model=scalar_model,
                          a_i=xdata[0],
                          constraints=[Equality(a + b, 110)])
    assert isinstance(constrained_fit.minimizer, SLSQP)

    a.min = 0
    a.max = 25
    a.value = 10
    b.min = 80
    b.max = 120
    b.value = 100
    bound_fit = Fit(
        model=scalar_model,
        a_i=xdata[0],
    )
    assert isinstance(bound_fit.minimizer, LBFGSB)

    # Repeat all of the above for the Vector model
    a, b, c = parameters('a, b, c')
    a_i, b_i, c_i = variables('a_i, b_i, c_i')

    model = {a_i: a, b_i: b, c_i: c}

    simple_fit = Fit(
        model=model,
        a_i=xdata[0],
        b_i=xdata[1],
        c_i=xdata[2],
    )
    assert isinstance(simple_fit.minimizer, BFGS)

    constrained_fit = Fit(model=model,
                          a_i=xdata[0],
                          b_i=xdata[1],
                          c_i=xdata[2],
                          constraints=[Equality(a + b + c, 180)])
    assert isinstance(constrained_fit.minimizer, SLSQP)

    a.min = 0
    a.max = 25
    a.value = 10
    b.min = 80
    b.max = 120
    b.value = 100
    bound_fit = Fit(
        model=model,
        a_i=xdata[0],
        b_i=xdata[1],
        c_i=xdata[2],
    )
    assert isinstance(bound_fit.minimizer, LBFGSB)

    fit_result = bound_fit.execute()
    assert fit_result.value(a) == pytest.approx(np.mean(xdata[0]), rel=1e-6)
    assert fit_result.value(b) == pytest.approx(np.mean(xdata[1]), rel=1e-6)
    assert fit_result.value(c) == pytest.approx(np.mean(xdata[2]), rel=1e-6)
示例#3
0
    def test_vector_constrained_fitting(self):
        """
        Tests `Fit` with vector models. The
        classical example of fitting measurements of the angles of a triangle is
        taken. In this case we know they should add up to 180 degrees, so this
        can be added as a constraint. Additionally, not even all three angles
        have to be provided with measurement data since the constrained means
        the angles are not independent.
        """
        a, b, c = parameters('a, b, c')
        a_i, b_i, c_i = variables('a_i, b_i, c_i')

        model = {a_i: a, b_i: b, c_i: c}

        xdata = np.array([
            [10.1, 9., 10.5, 11.2, 9.5, 9.6, 10.],
            [102.1, 101., 100.4, 100.8, 99.2, 100., 100.8],
            [71.6, 73.2, 69.5, 70.2, 70.8, 70.6, 70.1],
        ])

        fit_none = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=None,
        )
        fit = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=xdata[2],
        )
        fit_std = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=xdata[2],
            minimizer = MINPACK
        )
        fit_constrained = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=xdata[2],
            constraints=[Equality(a + b + c, 180)]
        )
        fit_none_result = fit_none.execute()
        fit_new_result = fit.execute()
        std_result = fit_std.execute()
        constr_result = fit_constrained.execute()

        # The total of averages should equal the total of the params by definition
        mean_total = np.mean(np.sum(xdata, axis=0))
        params_tot = std_result.value(a) + std_result.value(b) + std_result.value(c)
        self.assertAlmostEqual(mean_total / params_tot, 1.0, 4)

        # The total after constraining to 180 should be exactly 180.
        params_tot = constr_result.value(a) + constr_result.value(b) + constr_result.value(c)
        self.assertIsInstance(fit_constrained.minimizer, SLSQP)
        self.assertAlmostEqual(180.0, params_tot, 4)

        # The standard method and the Constrained object called without constraints
        # should behave roughly the same.
        self.assertAlmostEqual(fit_new_result.value(a), std_result.value(a), 4)
        self.assertAlmostEqual(fit_new_result.value(b), std_result.value(b), 4)
        self.assertAlmostEqual(fit_new_result.value(c), std_result.value(c), 4)

        # When fitting with a dataset set to None, for this example the value of c
        # should be unaffected.
        self.assertAlmostEqual(fit_none_result.value(a), std_result.value(a), 4)
        self.assertAlmostEqual(fit_none_result.value(b), std_result.value(b), 4)
        self.assertAlmostEqual(fit_none_result.value(c), c.value)

        fit_none_constr = Fit(
            model=model,
            a_i=xdata[0],
            b_i=xdata[1],
            c_i=None,
            constraints=[Equality(a + b + c, 180)]
        )
        none_constr_result = fit_none_constr.execute()
        params_tot = none_constr_result.value(a) + none_constr_result.value(b) + none_constr_result.value(c)
        self.assertAlmostEqual(180.0, params_tot, 4)