def main():
    # Parameter estimation using timeseries data

    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']

    # Data, includes multiple sensors for ca and cc
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data_timeseries.csv'))
    data = pd.read_csv(file_name)

    # Group time series data into experiments, return the mean value for sv and caf
    # Returns a list of dictionaries
    data_ts = parmest.group_data(data, 'experiment', ['sv', 'caf'])

    def SSE_timeseries(model, data):
        expr = 0
        for val in data['ca']:
            expr = expr + ((float(val) - model.ca)**2) * (1 / len(data['ca']))
        for val in data['cb']:
            expr = expr + ((float(val) - model.cb)**2) * (1 / len(data['cb']))
        for val in data['cc']:
            expr = expr + ((float(val) - model.cc)**2) * (1 / len(data['cc']))
        for val in data['cd']:
            expr = expr + ((float(val) - model.cd)**2) * (1 / len(data['cd']))
        return expr

    pest = parmest.Estimator(reactor_design_model, data_ts, theta_names,
                             SSE_timeseries)
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
Exemple #2
0
    def test_propagate_uncertainty_error(self):
        '''
        It tests a TypeError when the modle_uncertian of function propagate_uncertainty is neither python function nor Pyomo ConcreteModel
        '''
        from idaes.apps.uncertainty_propagation.examples.rooney_biegler import rooney_biegler_model
        variable_name = ['asymptote', 'rate_constant']
        data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                                  [5, 15.6], [7, 19.8]],
                            columns=['hour', 'y'])

        def SSE(model, data):
            expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                       for i in data.index)
            return expr

        parmest_class = parmest.Estimator(rooney_biegler_model, data,
                                          variable_name, SSE)
        obj, theta, cov = parmest_class.theta_est(calc_cov=True)
        model_uncertain = ConcreteModel()
        model_uncertain.asymptote = Var(initialize=15)
        model_uncertain.rate_constant = Var(initialize=0.5)
        model_uncertain.obj = Objective(
            expr=model_uncertain.asymptote *
            (1 - exp(-model_uncertain.rate_constant * 10)),
            sense=minimize)
        with pytest.raises(TypeError):
            propagate_results = propagate_uncertainty(1, theta, cov,
                                                      variable_name)
Exemple #3
0
def main():
    # Vars to estimate
    theta_names = ['asymptote', 'rate_constant']

    # Data
    data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                              [5, 15.6], [7, 19.8]],
                        columns=['hour', 'y'])

    # Sum of squared error function
    def SSE(model, data):
        expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                   for i in data.index)
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE)

    # Parameter estimation
    obj, theta = pest.theta_est()

    # Find the objective value at each theta estimate
    asym = np.arange(10, 30, 2)
    rate = np.arange(0, 1.5, 0.1)
    theta_vals = pd.DataFrame(list(product(asym, rate)),
                              columns=['asymptote', 'rate_constant'])
    obj_at_theta = pest.objective_at_theta(theta_vals)

    # Run the likelihood ratio test
    LR = pest.likelihood_ratio_test(obj_at_theta, obj, [0.8, 0.85, 0.9, 0.95])

    # Plot results
    parmest.graphics.pairwise_plot(
        LR, theta, 0.8, title='LR results within 80% confidence region')
Exemple #4
0
def main():
    # Parameter estimation using multisensor data

    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']

    # Data, includes multiple sensors for ca and cc
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data_multisensor.csv'))
    data = pd.read_csv(file_name)

    # Sum of squared error function
    def SSE_multisensor(model, data):
        expr = ((float(data['ca1']) - model.ca)**2)*(1/3) + \
               ((float(data['ca2']) - model.ca)**2)*(1/3) + \
               ((float(data['ca3']) - model.ca)**2)*(1/3) + \
                (float(data['cb'])  - model.cb)**2 + \
               ((float(data['cc1']) - model.cc)**2)*(1/2) + \
               ((float(data['cc2']) - model.cc)**2)*(1/2) + \
                (float(data['cd'])  - model.cd)**2
        return expr

    pest = parmest.Estimator(reactor_design_model, data, theta_names,
                             SSE_multisensor)
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
Exemple #5
0
def main():
    # Vars to estimate
    theta_names = ['k1', 'k2', 'E1', 'E2']

    # Data, list of json file names
    data = []
    file_dirname = dirname(abspath(str(__file__)))
    for exp_num in range(10):
        file_name = abspath(
            join(file_dirname, 'exp' + str(exp_num + 1) + '.out'))
        data.append(file_name)

    # Note, the model already includes a 'SecondStageCost' expression
    # for sum of squared error that will be used in parameter estimation

    pest = parmest.Estimator(generate_model, data, theta_names)

    ### Parameter estimation with bootstrap resampling
    bootstrap_theta = pest.theta_est_bootstrap(100)
    bootstrap_theta.to_csv('bootstrap_theta.csv')

    ### Compute objective at theta for likelihood ratio test
    k1 = np.arange(4, 24, 3)
    k2 = np.arange(40, 160, 40)
    E1 = np.arange(29000, 32000, 500)
    E2 = np.arange(38000, 42000, 500)
    theta_vals = pd.DataFrame(list(product(k1, k2, E1, E2)),
                              columns=theta_names)

    obj_at_theta = pest.objective_at_theta(theta_vals)
    obj_at_theta.to_csv('obj_at_theta.csv')
Exemple #6
0
def main():
    # Vars to estimate
    theta_names = ['asymptote', 'rate_constant']

    # Data
    data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                              [5, 15.6], [7, 19.8]],
                        columns=['hour', 'y'])

    # Sum of squared error function
    def SSE(model, data):
        expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                   for i in data.index)
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE)

    # Parameter estimation and covariance
    n = 6  # total number of data points used in the objective (y in 6 scenarios)
    obj, theta, cov = pest.theta_est(calc_cov=True, cov_n=n)

    # Plot theta estimates using a multivariate Gaussian distribution
    parmest.graphics.pairwise_plot(
        (theta, cov, 100),
        theta_star=theta,
        alpha=0.8,
        distributions=['MVN'],
        title='Theta estimates within 80% confidence region')

    # Assert statements compare parameter estimation (theta) to an expected value
    relative_error = abs(theta['asymptote'] - 19.1426) / 19.1426
    assert relative_error < 0.01
    relative_error = abs(theta['rate_constant'] - 0.5311) / 0.5311
    assert relative_error < 0.01
Exemple #7
0
    def setUp(self):
        from pyomo.contrib.parmest.examples.rooney_biegler.rooney_biegler import rooney_biegler_model

        # Note, the data used in this test has been corrected to use data.loc[5,'hour'] = 7 (instead of 6)
        data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                                  [5, 15.6], [7, 19.8]],
                            columns=['hour', 'y'])

        theta_names = ['asymptote', 'rate_constant']

        def SSE(model, data):
            expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                       for i in data.index)
            return expr

        solver_options = {
            'tol': 1e-8,
        }

        self.data = data
        self.pest = parmest.Estimator(rooney_biegler_model,
                                      data,
                                      theta_names,
                                      SSE,
                                      solver_options=solver_options)
Exemple #8
0
def main():
    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']

    # Data
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data.csv'))
    data = pd.read_csv(file_name)

    # Sum of squared error function
    def SSE(model, data):
        expr = (float(data['ca']) - model.ca)**2 + \
               (float(data['cb']) - model.cb)**2 + \
               (float(data['cc']) - model.cc)**2 + \
               (float(data['cd']) - model.cd)**2
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(reactor_design_model, data, theta_names, SSE)

    # Parameter estimation
    obj, theta = pest.theta_est()

    # Parameter estimation with bootstrap resampling
    bootstrap_theta = pest.theta_est_bootstrap(50)

    # Plot results
    parmest.graphics.pairwise_plot(bootstrap_theta, title='Bootstrap theta')
    parmest.graphics.pairwise_plot(
        bootstrap_theta,
        theta,
        0.8, ['MVN', 'KDE', 'Rect'],
        title='Bootstrap theta with confidence regions')
Exemple #9
0
def main():
    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']

    # Data
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data.csv'))
    data = pd.read_csv(file_name)

    # Sum of squared error function
    def SSE(model, data):
        expr = (float(data['ca']) - model.ca)**2 + \
               (float(data['cb']) - model.cb)**2 + \
               (float(data['cc']) - model.cc)**2 + \
               (float(data['cd']) - model.cd)**2
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(reactor_design_model, data, theta_names, SSE)

    # Parameter estimation
    obj, theta = pest.theta_est()

    # Assert statements compare parameter estimation (theta) to an expected value
    k1_expected = 5.0 / 6.0
    k2_expected = 5.0 / 3.0
    k3_expected = 1.0 / 6000.0
    relative_error = abs(theta['k1'] - k1_expected) / k1_expected
    assert relative_error < 0.05
    relative_error = abs(theta['k2'] - k2_expected) / k2_expected
    assert relative_error < 0.05
    relative_error = abs(theta['k3'] - k3_expected) / k3_expected
    assert relative_error < 0.05
Exemple #10
0
def main():
    # Vars to estimate
    theta_names = ['asymptote', 'rate_constant']

    # Data
    data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                              [5, 15.6], [7, 19.8]],
                        columns=['hour', 'y'])

    # Sum of squared error function
    def SSE(model, data):
        expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                   for i in data.index)
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE)

    # Parameter estimation
    obj, theta = pest.theta_est()

    # Parameter estimation with bootstrap resampling
    bootstrap_theta = pest.theta_est_bootstrap(50, seed=4581)

    # Plot results
    parmest.graphics.pairwise_plot(bootstrap_theta, title='Bootstrap theta')
    parmest.graphics.pairwise_plot(
        bootstrap_theta,
        theta,
        0.8, ['MVN', 'KDE', 'Rect'],
        title='Bootstrap theta with confidence regions')
Exemple #11
0
def main(dirname):
    """ dirname gives the location of the experiment input files"""
    # Semibatch Vars to estimate in parmest
    theta_names = ['k1', 'k2', 'E1', 'E2']

    # Semibatch data: list of dictionaries
    data = []
    for exp_num in range(10):
        fname = os.path.join(dirname, 'exp' + str(exp_num + 1) + '.out')
        with open(fname, 'r') as infile:
            d = json.load(infile)
            data.append(d)

    pest = parmest.Estimator(generate_model, data, theta_names)

    scenmaker = sc.ScenarioCreator(pest, "ipopt")

    ofile = "delme_exp.csv"
    print("Make one scenario per experiment and write to {}".format(ofile))
    experimentscens = sc.ScenarioSet("Experiments")
    scenmaker.ScenariosFromExperiments(experimentscens)
    ###experimentscens.write_csv(ofile)

    numtomake = 3
    print("\nUse the bootstrap to make {} scenarios and print.".format(
        numtomake))
    bootscens = sc.ScenarioSet("Bootstrap")
    scenmaker.ScenariosFromBoostrap(bootscens, numtomake)
    for s in bootscens.ScensIterator():
        print("{}, {}".format(s.name, s.probability))
        for n, v in s.ThetaVals.items():
            print("   {}={}".format(n, v))
Exemple #12
0
    def setUp(self):
        from pyomo.contrib.parmest.examples.reactor_design.reactor_design import reactor_design_model
          
        # Data from the design 
        data = pd.DataFrame(data=[[1.05, 10000, 3458.4, 1060.8, 1683.9, 1898.5],
                                  [1.10, 10000, 3535.1, 1064.8, 1613.3, 1893.4],
                                  [1.15, 10000, 3609.1, 1067.8, 1547.5, 1887.8],
                                  [1.20, 10000, 3680.7, 1070.0, 1486.1, 1881.6],
                                  [1.25, 10000, 3750.0, 1071.4, 1428.6, 1875.0],
                                  [1.30, 10000, 3817.1, 1072.2, 1374.6, 1868.0],
                                  [1.35, 10000, 3882.2, 1072.4, 1324.0, 1860.7],
                                  [1.40, 10000, 3945.4, 1072.1, 1276.3, 1853.1],
                                  [1.45, 10000, 4006.7, 1071.3, 1231.4, 1845.3],
                                  [1.50, 10000, 4066.4, 1070.1, 1189.0, 1837.3],
                                  [1.55, 10000, 4124.4, 1068.5, 1148.9, 1829.1],
                                  [1.60, 10000, 4180.9, 1066.5, 1111.0, 1820.8],
                                  [1.65, 10000, 4235.9, 1064.3, 1075.0, 1812.4],
                                  [1.70, 10000, 4289.5, 1061.8, 1040.9, 1803.9],
                                  [1.75, 10000, 4341.8, 1059.0, 1008.5, 1795.3],
                                  [1.80, 10000, 4392.8, 1056.0,  977.7, 1786.7],
                                  [1.85, 10000, 4442.6, 1052.8,  948.4, 1778.1],
                                  [1.90, 10000, 4491.3, 1049.4,  920.5, 1769.4],
                                  [1.95, 10000, 4538.8, 1045.8,  893.9, 1760.8]], 
                          columns=['sv', 'caf', 'ca', 'cb', 'cc', 'cd'])

        theta_names = ['k1', 'k2', 'k3']
        
        def SSE(model, data): 
            expr = (float(data['ca']) - model.ca)**2 + \
                   (float(data['cb']) - model.cb)**2 + \
                   (float(data['cc']) - model.cc)**2 + \
                   (float(data['cd']) - model.cd)**2
            return expr
        
        self.pest = parmest.Estimator(reactor_design_model, data, theta_names, SSE)
Exemple #13
0
 def setUp(self):
     from pyomo.contrib.parmest.examples.rooney_biegler.rooney_biegler import rooney_biegler_model
        
     data = pd.DataFrame(data=[[1,8.3],[2,10.3],[3,19.0],
                               [4,16.0],[5,15.6],[6,19.8]], columns=['hour', 'y'])
     
     theta_names = ['asymptote', 'rate_constant']
     
     def SSE(model, data):  
         expr = sum((data.y[i] - model.response_function[data.hour[i]])**2 for i in data.index)
         return expr
     
     self.pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE)
Exemple #14
0
def main():
    # Generate data
    data = generate_data()
    data_std = data.std()

    # Define sum of squared error objective function for data rec
    def SSE(model, data):
        expr = ((float(data['ca']) - model.ca)/float(data_std['ca']))**2 + \
               ((float(data['cb']) - model.cb)/float(data_std['cb']))**2 + \
               ((float(data['cc']) - model.cc)/float(data_std['cc']))**2 + \
               ((float(data['cd']) - model.cd)/float(data_std['cd']))**2
        return expr

    ### Data reconciliation
    theta_names = []  # no variables to estimate, use initialized values

    pest = parmest.Estimator(reactor_design_model_for_datarec, data,
                             theta_names, SSE)

    obj, theta, data_rec = pest.theta_est(
        return_values=['ca', 'cb', 'cc', 'cd', 'caf'])
    print(obj)
    print(theta)

    parmest.graphics.grouped_boxplot(data[['ca', 'cb', 'cc', 'cd']],
                                     data_rec[['ca', 'cb', 'cc', 'cd']],
                                     group_names=['Data', 'Data Rec'])

    ### Parameter estimation using reconciled data
    theta_names = ['k1', 'k2', 'k3']
    data_rec['sv'] = data['sv']

    pest = parmest.Estimator(reactor_design_model, data_rec, theta_names, SSE)
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)

    theta_real = {'k1': 5.0 / 6.0, 'k2': 5.0 / 3.0, 'k3': 1.0 / 6000.0}
    print(theta_real)
Exemple #15
0
def main():
    # Data from Table 5.2 in  Y. Bard, "Nonlinear Parameter Estimation", (pg. 124)
    data = [{'experiment': 1, 'x1': 0.1, 'x2': 100, 'y': 0.98},
            {'experiment': 2, 'x1': 0.2, 'x2': 100, 'y': 0.983},
            {'experiment': 3, 'x1': 0.3, 'x2': 100, 'y': 0.955},
            {'experiment': 4, 'x1': 0.4, 'x2': 100, 'y': 0.979},
            {'experiment': 5, 'x1': 0.5, 'x2': 100, 'y': 0.993},
            {'experiment': 6, 'x1': 0.05, 'x2': 200, 'y': 0.626},
            {'experiment': 7, 'x1': 0.1, 'x2': 200, 'y': 0.544},
            {'experiment': 8, 'x1': 0.15, 'x2': 200, 'y': 0.455},
            {'experiment': 9, 'x1': 0.2, 'x2': 200, 'y': 0.225},
            {'experiment': 10, 'x1': 0.25, 'x2': 200, 'y': 0.167},
            {'experiment': 11, 'x1': 0.02, 'x2': 300, 'y': 0.566},
            {'experiment': 12, 'x1': 0.04, 'x2': 300, 'y': 0.317},
            {'experiment': 13, 'x1': 0.06, 'x2': 300, 'y': 0.034},
            {'experiment': 14, 'x1': 0.08, 'x2': 300, 'y': 0.016},
            {'experiment': 15, 'x1': 0.1, 'x2': 300, 'y': 0.006}]

    # =======================================================================
    # Parameter estimation without covariance estimate
    # Only estimate the parameter k[1]. The parameter k[2] will remain fixed
    # at its initial value
    theta_names = ['k[1]']
    pest = parmest.Estimator(simple_reaction_model, data, theta_names)
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
    print()
    
    #=======================================================================
    # Estimate both k1 and k2 and compute the covariance matrix
    theta_names = ['k']
    pest = parmest.Estimator(simple_reaction_model, data, theta_names)
    n = 15 # total number of data points used in the objective (y in 15 scenarios)
    obj, theta, cov = pest.theta_est(calc_cov=True, cov_n=n)
    print(obj)
    print(theta)
    print(cov)
Exemple #16
0
    def make_model(self, theta_names):

        data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                                  [5, 15.6], [7, 19.8]],
                            columns=['hour', 'y'])

        def rooney_biegler_model_alternate(data):
            ''' Alternate model definition used in a unit test
            Here, the fitted parameters are defined as a single variable over a set
            A bit silly for this specific example
            '''

            model = pyo.ConcreteModel()

            model.var_names = pyo.Set(
                initialize=['asymptote', 'rate_constant'])

            model.theta = pyo.Var(model.var_names,
                                  initialize={
                                      'asymptote': 15,
                                      'rate_constant': 0.5
                                  })
            model.theta[
                'asymptote'].fixed = True  # parmest will unfix theta variables, even when they are indexed
            model.theta['rate_constant'].fixed = True

            def response_rule(m, h):
                expr = m.theta['asymptote'] * (
                    1 - pyo.exp(-m.theta['rate_constant'] * h))
                return expr

            model.response_function = pyo.Expression(data.hour,
                                                     rule=response_rule)

            def SSE_rule(m):
                return sum((data.y[i] - m.response_function[data.hour[i]])**2
                           for i in data.index)

            model.SSE = pyo.Objective(rule=SSE_rule, sense=pyo.minimize)

            return model

        def SSE(model, data):
            expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                       for i in data.index)
            return expr

        return parmest.Estimator(rooney_biegler_model_alternate, data,
                                 theta_names, SSE)
Exemple #17
0
    def setUp(self):
        import pyomo.contrib.parmest.examples.semibatch.semibatch as sb
        import json

        # Vars to estimate in parmest
        theta_names = ['k1', 'k2', 'E1', 'E2']

        self.fbase = os.path.join(testdir,"..","examples","semibatch")
        # Data, list of dictionaries
        data = [] 
        for exp_num in range(10):
            fname = "exp"+str(exp_num+1)+".out"
            fullname = os.path.join(self.fbase, fname)
            with open(fullname,'r') as infile:
                d = json.load(infile)
                data.append(d)

        # Note, the model already includes a 'SecondStageCost' expression 
        # for the sum of squared error that will be used in parameter estimation

        self.pest = parmest.Estimator(sb.generate_model, data, theta_names)
Exemple #18
0
    def test_propagate_uncertainty(self):
        '''
        It tests the function propagate_uncertainty with rooney & biegler's model.
        '''
        from idaes.apps.uncertainty_propagation.examples.rooney_biegler import rooney_biegler_model
        variable_name = ['asymptote', 'rate_constant']
        data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0],
                                  [5, 15.6], [7, 19.8]],
                            columns=['hour', 'y'])

        def SSE(model, data):
            expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
                       for i in data.index)
            return expr

        parmest_class = parmest.Estimator(rooney_biegler_model, data,
                                          variable_name, SSE)
        obj, theta, cov = parmest_class.theta_est(calc_cov=True)
        model_uncertain = ConcreteModel()
        model_uncertain.asymptote = Var(initialize=15)
        model_uncertain.rate_constant = Var(initialize=0.5)
        model_uncertain.obj = Objective(
            expr=model_uncertain.asymptote *
            (1 - exp(-model_uncertain.rate_constant * 10)),
            sense=minimize)

        propagate_results = propagate_uncertainty(model_uncertain, theta, cov,
                                                  variable_name)

        np.testing.assert_array_almost_equal(
            propagate_results.gradient_f,
            [0.9950625870024135, 0.9451480001755206])
        assert list(propagate_results.gradient_c) == []
        np.testing.assert_array_almost_equal(propagate_results.dsdp.toarray(),
                                             [[1., 0.], [0., 1.]])
        assert list(propagate_results.propagation_c) == []
        assert propagate_results.propagation_f == pytest.approx(
            5.45439337747349)
def main():

    # Vars to estimate
    theta_names = ['k1', 'k2', 'E1', 'E2']

    # Data, list of dictionaries
    data = []
    file_dirname = dirname(abspath(str(__file__)))
    for exp_num in range(10):
        file_name = abspath(
            join(file_dirname, 'exp' + str(exp_num + 1) + '.out'))
        with open(file_name, 'r') as infile:
            d = json.load(infile)
            data.append(d)

    # Note, the model already includes a 'SecondStageCost' expression
    # for sum of squared error that will be used in parameter estimation

    pest = parmest.Estimator(generate_model, data, theta_names)

    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
Exemple #20
0
def main():
    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']

    # Data
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data.csv'))
    data = pd.read_csv(file_name)

    # Sum of squared error function
    def SSE(model, data):
        expr = (float(data['ca']) - model.ca)**2 + \
               (float(data['cb']) - model.cb)**2 + \
               (float(data['cc']) - model.cc)**2 + \
               (float(data['cd']) - model.cd)**2
        return expr

    # Create an instance of the parmest estimator
    pest = parmest.Estimator(reactor_design_model, data, theta_names, SSE)

    # Parameter estimation
    obj, theta = pest.theta_est()

    # Find the objective value at each theta estimate
    k1 = [0.8, 0.85, 0.9]
    k2 = [1.6, 1.65, 1.7]
    k3 = [0.00016, 0.000165, 0.00017]
    theta_vals = pd.DataFrame(list(product(k1, k2, k3)),
                              columns=['k1', 'k2', 'k3'])
    obj_at_theta = pest.objective_at_theta(theta_vals)

    # Run the likelihood ratio test
    LR = pest.likelihood_ratio_test(obj_at_theta, obj, [0.8, 0.85, 0.9, 0.95])

    # Plot results
    parmest.graphics.pairwise_plot(
        LR, theta, 0.9, title='LR results within 90% confidence region')
Exemple #21
0
    def setUp(self):
        def ABC_model(data):

            ca_meas = data['ca']
            cb_meas = data['cb']
            cc_meas = data['cc']

            if isinstance(data, pd.DataFrame):
                meas_t = data.index  # time index
            else:  # dictionary
                meas_t = list(ca_meas.keys())  # nested dictionary

            ca0 = 1.0
            cb0 = 0.0
            cc0 = 0.0

            m = pyo.ConcreteModel()

            m.k1 = pyo.Var(initialize=0.5, bounds=(1e-4, 10))
            m.k2 = pyo.Var(initialize=3.0, bounds=(1e-4, 10))

            m.time = dae.ContinuousSet(bounds=(0.0, 5.0), initialize=meas_t)

            # initialization and bounds
            m.ca = pyo.Var(m.time, initialize=ca0, bounds=(-1e-3, ca0 + 1e-3))
            m.cb = pyo.Var(m.time, initialize=cb0, bounds=(-1e-3, ca0 + 1e-3))
            m.cc = pyo.Var(m.time, initialize=cc0, bounds=(-1e-3, ca0 + 1e-3))

            m.dca = dae.DerivativeVar(m.ca, wrt=m.time)
            m.dcb = dae.DerivativeVar(m.cb, wrt=m.time)
            m.dcc = dae.DerivativeVar(m.cc, wrt=m.time)

            def _dcarate(m, t):
                if t == 0:
                    return pyo.Constraint.Skip
                else:
                    return m.dca[t] == -m.k1 * m.ca[t]

            m.dcarate = pyo.Constraint(m.time, rule=_dcarate)

            def _dcbrate(m, t):
                if t == 0:
                    return pyo.Constraint.Skip
                else:
                    return m.dcb[t] == m.k1 * m.ca[t] - m.k2 * m.cb[t]

            m.dcbrate = pyo.Constraint(m.time, rule=_dcbrate)

            def _dccrate(m, t):
                if t == 0:
                    return pyo.Constraint.Skip
                else:
                    return m.dcc[t] == m.k2 * m.cb[t]

            m.dccrate = pyo.Constraint(m.time, rule=_dccrate)

            def ComputeFirstStageCost_rule(m):
                return 0

            m.FirstStageCost = pyo.Expression(rule=ComputeFirstStageCost_rule)

            def ComputeSecondStageCost_rule(m):
                return sum(
                    (m.ca[t] - ca_meas[t])**2 + (m.cb[t] - cb_meas[t])**2 +
                    (m.cc[t] - cc_meas[t])**2 for t in meas_t)

            m.SecondStageCost = pyo.Expression(
                rule=ComputeSecondStageCost_rule)

            def total_cost_rule(model):
                return model.FirstStageCost + model.SecondStageCost

            m.Total_Cost_Objective = pyo.Objective(rule=total_cost_rule,
                                                   sense=pyo.minimize)

            disc = pyo.TransformationFactory('dae.collocation')
            disc.apply_to(m, nfe=20, ncp=2)

            return m

        # This example tests data formatted in 3 ways
        # Each format holds 1 scenario
        # 1. dataframe with time index
        # 2. nested dictionary {ca: {t, val pairs}, ... }
        data = [[0.000, 0.957, -0.031, -0.015], [0.263, 0.557, 0.330, 0.044],
                [0.526, 0.342, 0.512, 0.156], [0.789, 0.224, 0.499, 0.310],
                [1.053, 0.123, 0.428, 0.454], [1.316, 0.079, 0.396, 0.556],
                [1.579, 0.035, 0.303, 0.651], [1.842, 0.029, 0.287, 0.658],
                [2.105, 0.025, 0.221, 0.750], [2.368, 0.017, 0.148, 0.854],
                [2.632, -0.002, 0.182, 0.845], [2.895, 0.009, 0.116, 0.893],
                [3.158, -0.023, 0.079, 0.942], [3.421, 0.006, 0.078, 0.899],
                [3.684, 0.016, 0.059, 0.942], [3.947, 0.014, 0.036, 0.991],
                [4.211, -0.009, 0.014, 0.988], [4.474, -0.030, 0.036, 0.941],
                [4.737, 0.004, 0.036, 0.971], [5.000, -0.024, 0.028, 0.985]]
        data = pd.DataFrame(data, columns=['t', 'ca', 'cb', 'cc'])
        data_df = data.set_index('t')
        data_dict = {
            'ca': {k: v
                   for (k, v) in zip(data.t, data.ca)},
            'cb': {k: v
                   for (k, v) in zip(data.t, data.cb)},
            'cc': {k: v
                   for (k, v) in zip(data.t, data.cc)}
        }

        theta_names = ['k1', 'k2']

        self.pest_df = parmest.Estimator(ABC_model, [data_df], theta_names)
        self.pest_dict = parmest.Estimator(ABC_model, [data_dict], theta_names)

        # Create an instance of the model
        self.m_df = ABC_model(data_df)
        self.m_dict = ABC_model(data_dict)
        return (float(data['y']) - m.y) ** 2
    model.SecondStageCost = Expression(rule=AllMeasurements)

    def total_cost_rule(m):
        return m.FirstStageCost + m.SecondStageCost
    model.Total_Cost_Objective = Objective(rule=total_cost_rule,
                                           sense=minimize)

    return model

if __name__ == "__main__":

    # =======================================================================
    # Parameter estimation without covariance estimate
    # Only estimate the parameter k[1]. The parameter k[2] will remain fixed
    # at its initial value
    theta_names = ['k[1]']
    pest = parmest.Estimator(simple_reaction_model, data, theta_names)
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
    print()
    #=======================================================================
    # Estimate both k1 and k2 and compute the covariance matrix
    theta_names = ['k']
    pest = parmest.Estimator(simple_reaction_model, data, theta_names)
    obj, theta, cov = pest.theta_est(calc_cov=True)
    print(obj)
    print(theta)
    print(cov)
Exemple #23
0
def main():
    
    # Vars to estimate
    theta_names = ['k1', 'k2', 'k3']
    
    # Data
    file_dirname = dirname(abspath(str(__file__)))
    file_name = abspath(join(file_dirname, 'reactor_data.csv'))
    data = pd.read_csv(file_name) 
    
    # Create more data for the example
    N = 50
    df_std = data.std().to_frame().transpose()
    df_rand = pd.DataFrame(np.random.normal(size=N))
    df_sample = data.sample(N, replace=True).reset_index(drop=True)
    data = df_sample + df_rand.dot(df_std)/10
    
    # Sum of squared error function
    def SSE(model, data): 
        expr = (float(data['ca']) - model.ca)**2 + \
               (float(data['cb']) - model.cb)**2 + \
               (float(data['cc']) - model.cc)**2 + \
               (float(data['cd']) - model.cd)**2
        return expr
    
    # Create an instance of the parmest estimator
    pest = parmest.Estimator(reactor_design_model, data, theta_names, SSE)
    
    # Parameter estimation
    obj, theta = pest.theta_est()
    print(obj)
    print(theta)
    
    ### Parameter estimation with 'leave-N-out'
    # Example use case: For each combination of data where one data point is left 
    # out, estimate theta
    lNo_theta = pest.theta_est_leaveNout(1) 
    print(lNo_theta.head())
    
    parmest.graphics.pairwise_plot(lNo_theta, theta)
    
    ### Leave one out/boostrap analysis
    # Example use case: leave 25 data points out, run 20 bootstrap samples with the 
    # remaining points, determine if the theta estimate using the points left out 
    # is inside or outside an alpha region based on the bootstrap samples, repeat 
    # 5 times. Results are stored as a list of tuples, see API docs for information.
    lNo = 25
    lNo_samples = 5
    bootstrap_samples = 20
    dist = 'MVN'
    alphas = [0.7, 0.8, 0.9]
    
    results = pest.leaveNout_bootstrap_test(lNo, lNo_samples, bootstrap_samples, 
                                                dist, alphas, seed=524)
    
    # Plot results for a single value of alpha
    alpha = 0.8
    for i in range(lNo_samples):
        theta_est_N = results[i][1]
        bootstrap_results = results[i][2]
        parmest.graphics.pairwise_plot(bootstrap_results, theta_est_N, alpha, ['MVN'],
                              title= 'Alpha: '+ str(alpha) + ', '+ \
                              str(theta_est_N.loc[0,alpha]))
        
    # Extract the percent of points that are within the alpha region
    r = [results[i][1].loc[0,alpha] for i in range(lNo_samples)]
    percent_true = sum(r)/len(r)
    print(percent_true)
Exemple #24
0
def quantify_propagate_uncertainty(model_function,
                                   model_uncertain,
                                   data,
                                   theta_names,
                                   obj_function=None,
                                   tee=False,
                                   diagnostic_mode=False,
                                   solver_options=None):
    """This function calculates error propagation of the objective function and 
    constraints. The parmest uses 'model_function' to estimate uncertain 
    parameters. The uncertain parameters in 'model_uncertain' are fixed with 
    the estimated values. The function 'quantify_propagate_uncertainty' 
    calculates error propagation of objective function and constraints 
    in the 'model_uncertain'. 
    
    The following terms are used to define the output dimensions:
    Ncon   = number of constraints
    Nvar   = number of variables (Nx + Ntheta)
    Nx     = the number of decision (primal) variables
    Ntheta = number of uncertain parameters.

    Parameters
    ----------
    model_function : function
        A python Function that generates an instance of the Pyomo model using 
        'data' as the input argument
    model_uncertain : function or Pyomo ConcreteModel
        Function is a python/ Function that generates an instance of the 
        Pyomo model
    data : pandas DataFrame, list of dictionary, or list of json file names
        Data that is used to build an instance of the Pyomo model and build the 
        objective function
    theta_names : list of strings
        List of Var names to estimate
    obj_function : function, optional
        Function used to formulate parameter estimation objective, generally 
        sum of squared error between measurements and model variables, 
        by default None
    tee : bool, optional
        Indicates that ef solver output should be teed, by default False
    diagnostic_mode : bool, optional
        If True, print diagnostics from the solver, by default False
    solver_options : dict, optional
        Provides options to the solver (also the name of an attribute), 
        by default None

    Returns
    -------
    tuple
        results object containing the all information including
        
        - results.obj: float
            Real number. Objective function value for the given obj_function 
        - results.theta: dict 
            Size Ntheta python dictionary. Estimated parameters
        - results.theta_names: list
            Size Ntheta list. Names of parameters
        - results.cov: numpy.ndarray
            Ntheta by Ntheta matrix. Covariance of theta
        - results.gradient_f: numpy.ndarray
            Length Nvar array. Gradient vector of the objective function with 
            respect to the (decision variables, parameters) at the optimal 
            solution
        - results.gradient_c: scipy.sparse.csr.csr_matrix
            Ncon by Nvar size sparse matrix. Gradient vector of the constraints 
            with respect to the (decision variables, parameters) at the optimal 
            solution.
        - results.dsdp: scipy.sparse.csr.csr_matrix
            Ntheta by Nvar size sparse matrix. Gradient vector of the 
            (decision variables, parameters) with respect to paramerters 
            (=theta_name). number of rows = len(theta_name), 
            number of columns= len(col)
        - results.propagation_c: numpy.ndarray
            Length Ncon array. Error propagation in the constraints, 
            dc/dp*cov_p*dc/dp + (dc/dx*dx/dp)*cov_p*(dc/dx*dx/dp)
        - results.propagation_f: numpy.float64
            Real number. Error propagation in the objective function, 
            df/dp*cov_p*df/dp + (df/dx*dx/dp)*cov_p*(df/dx*dx/dp)
        - results.col: list
            Size Nvar. List of variable names. Note that variables names 
            includes both decision variable and uncertain parameter names. 
            The order can be mixed.
        - results.row: list
            Size Ncon+1. List of constraints and objective function names

    Raises
    ------
    TypeError
        When tee entry is not Boolean
    TypeError
        When diagnostic_mode entry is not Boolean
    TypeError
        When solver_options entry is not None and a Dictionary
    Warnings
        When an element of theta_names includes a space
    """

    if not isinstance(tee, bool):
        raise TypeError('tee  must be boolean.')
    if not isinstance(diagnostic_mode, bool):
        raise TypeError('diagnostic_mode  must be boolean.')
    if not solver_options == None:
        if not isinstance(solver_options, dict):
            raise TypeError('solver_options must be dictionary.')
    # Remove all "'" and " " in theta_names
    theta_names, var_dic, variable_clean = clean_variable_name(theta_names)
    parmest_class = parmest.Estimator(model_function, data, theta_names,
                                      obj_function, tee, diagnostic_mode,
                                      solver_options)
    obj, theta, cov = parmest_class.theta_est(calc_cov=True)
    # Convert theta keys to the original name
    # Revert theta_names to be original
    if variable_clean:
        theta_out = {}
        for i in var_dic.keys():
            theta_out[var_dic[i]] = theta[i]
        theta_names = [var_dic[v] for v in theta_names]
    else:
        theta_out = theta
    propagate_results = propagate_uncertainty(model_uncertain, theta, cov,
                                              theta_names, tee)

    Output = namedtuple('Output', [
        'obj', 'theta', 'theta_names', 'cov', 'gradient_f', 'gradient_c',
        'dsdp', 'propagation_c', 'propagation_f', 'col', 'row'
    ])
    results = Output(obj, theta_out, theta_names, cov,
                     propagate_results.gradient_f,
                     propagate_results.gradient_c, propagate_results.dsdp,
                     propagate_results.propagation_c,
                     propagate_results.propagation_f, propagate_results.col,
                     propagate_results.row)
    return results
Exemple #25
0
data = pd.read_excel('reactor_data_multisensor.xlsx')


# Sum of squared error function
def SSE_multisensor(model, data):
    expr = ((float(data['ca1']) - model.ca)**2)*(1/3) + \
           ((float(data['ca2']) - model.ca)**2)*(1/3) + \
           ((float(data['ca3']) - model.ca)**2)*(1/3) + \
            (float(data['cb'])  - model.cb)**2 + \
           ((float(data['cc1']) - model.cc)**2)*(1/2) + \
           ((float(data['cc2']) - model.cc)**2)*(1/2) + \
            (float(data['cd'])  - model.cd)**2
    return expr


pest = parmest.Estimator(reactor_design_model, data, theta_names,
                         SSE_multisensor)
obj, theta = pest.theta_est()
print(obj)
print(theta)

### Parameter estimation with bootstrap resampling

bootstrap_theta = pest.theta_est_bootstrap(50)
print(bootstrap_theta.head())

parmest.pairwise_plot(bootstrap_theta)
parmest.pairwise_plot(bootstrap_theta, theta, 0.8, ['MVN', 'KDE', 'Rect'])

### Likelihood ratio test

k1 = [0.83]
Exemple #26
0
# Data
data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0], [5, 15.6],
                          [6, 19.8]],
                    columns=['hour', 'y'])


# Sum of squared error function
def SSE(model, data):
    expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
               for i in data.index)
    return expr


solver_options = {"max_iter": 6000}  # not really needed in this case

pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE,
                         solver_options)
obj, theta = pest.theta_est()
print(obj)
print(theta)

### Parameter estimation with bootstrap resampling

bootstrap_theta = pest.theta_est_bootstrap(50, seed=4581)
print(bootstrap_theta.head())

parmest.pairwise_plot(bootstrap_theta, title='Bootstrap theta')
parmest.pairwise_plot(bootstrap_theta,
                      theta,
                      0.8, ['MVN', 'KDE', 'Rect'],
                      title='Bootstrap theta with confidence regions')
# Vars to estimate
theta_names = ['k1', 'k2', 'k3']

# Data, includes multiple sensors for ca and cc
data = pd.read_excel('reactor_data_timeseries.xlsx')

# Group time series data into experiments, return the mean value for sv and caf
# Returns a list of dictionaries
data_ts = parmest.group_data(data, 'experiment', ['sv', 'caf'])


def SSE_timeseries(model, data):
    expr = 0
    for val in data['ca']:
        expr = expr + ((float(val) - model.ca)**2) * (1 / len(data['ca']))
    for val in data['cb']:
        expr = expr + ((float(val) - model.cb)**2) * (1 / len(data['cb']))
    for val in data['cc']:
        expr = expr + ((float(val) - model.cc)**2) * (1 / len(data['cc']))
    for val in data['cd']:
        expr = expr + ((float(val) - model.cd)**2) * (1 / len(data['cd']))
    return expr


pest = parmest.Estimator(reactor_design_model, data_ts, theta_names,
                         SSE_timeseries)
obj, theta = pest.theta_est()
print(obj)
print(theta)
Exemple #28
0

# Define sum of squared error objective function for data rec
def SSE(model, data):
    expr = ((float(data['ca']) - model.ca)/float(data_std['ca']))**2 + \
           ((float(data['cb']) - model.cb)/float(data_std['cb']))**2 + \
           ((float(data['cc']) - model.cc)/float(data_std['cc']))**2 + \
           ((float(data['cd']) - model.cd)/float(data_std['cd']))**2
    return expr


### Data reconciliation

theta_names = []  # no variables to estimate, use initialized values

pest = parmest.Estimator(reactor_design_model_for_datarec, data, theta_names,
                         SSE)
obj, theta, data_rec = pest.theta_est(
    return_values=['ca', 'cb', 'cc', 'cd', 'caf'])
print(obj)
print(theta)

parmest.grouped_boxplot(data[['ca', 'cb', 'cc', 'cd']],
                        data_rec[['ca', 'cb', 'cc', 'cd']],
                        group_names=['Data', 'Data Rec'])

### Parameter estimation using reconciled data

theta_names = ['k1', 'k2', 'k3']
data_rec['sv'] = data['sv']

pest = parmest.Estimator(reactor_design_model, data_rec, theta_names, SSE)
theta_names = ['asymptote', 'rate_constant']

# Data
data = pd.DataFrame(data=[[1, 8.3], [2, 10.3], [3, 19.0], [4, 16.0], [5, 15.6],
                          [6, 19.8]],
                    columns=['hour', 'y'])


# Sum of squared error function
def SSE(model, data):
    expr = sum((data.y[i] - model.response_function[data.hour[i]])**2
               for i in data.index)
    return expr


pest = parmest.Estimator(rooney_biegler_model, data, theta_names, SSE)
obj, theta = pest.theta_est()
print(obj)
print(theta)

### Parameter estimation with bootstrap resampling

bootstrap_theta = pest.theta_est_bootstrap(50, seed=4581)
print(bootstrap_theta.head())

parmest.pairwise_plot(bootstrap_theta, theta, 0.8, ['MVN', 'KDE', 'Rect'])

### Likelihood ratio test

asym = np.arange(10, 30, 2)
rate = np.arange(0, 1.5, 0.1)
Exemple #30
0
# Vars to estimate
theta_names = ['k1', 'k2', 'E1', 'E2']

# Data, list of dictionaries
data = [] 
for exp_num in range(10):
    fname = 'exp'+str(exp_num+1)+'.out'
    with open(fname,'r') as infile:
        d = json.load(infile)
        data.append(d)

# Note, the model already includes a 'SecondStageCost' expression 
# for sum of squared error that will be used in parameter estimation
        
pest = parmest.Estimator(generate_model, data, theta_names)
obj, theta = pest.theta_est()
print(obj)
print(theta)

### Parameter estimation with bootstrap resampling

bootstrap_theta = pest.theta_est_bootstrap(50)
print(bootstrap_theta.head())

parmest.graphics.pairwise_plot(bootstrap_theta, title='Bootstrap theta estimates')
parmest.graphics.pairwise_plot(bootstrap_theta, theta, 0.8, ['MVN', 'KDE', 'Rect'], 
                      title='Bootstrap theta with confidence regions')

### Likelihood ratio test