def _create_external_data(self): '''Define external data inputs to optimization problem. ''' quad_pen = OrderedDict() N_mea = 0 if hasattr(self, 'measurement_variable_list'): for key in self.measurement_variable_list: df = self.Model.measurements[key]['Measured'].get_base_data( )[self.Model.start_time:self.Model.final_time].to_frame() df_simtime = self._add_simtime_column(df) mea_traj = np.vstack((df_simtime['SimTime'].get_values(), \ df_simtime[key].get_values())) quad_pen['mpc_model.' + key] = mea_traj N_mea = N_mea + 1 else: Q = None # Create objective error weights Q = np.diag(np.ones(N_mea)) # Eliminate inputs from optimization problem eliminated = {} i = 1 N_input = 0 if self._input_object != {}: for key in self._input_object[0]: input_traj = np.vstack((np.transpose(self._input_object[1][:,0]), \ np.transpose(self._input_object[1][:,i]))) eliminated[key] = input_traj N_input = N_input + 1 i = i + 1 # Create ExternalData structure self.external_data = ExternalData(Q=Q, quad_pen=quad_pen, eliminated=eliminated)
def _create_external_data(self): """ Creates an ExternalData object that is loaded into the optimization. The object eliminates the inputs defined when creating the GreyBox object as well as the inputs added for the measured data (if costType='integral'). """ dictionary = {} # add external data for measured variables if self.costType == "integral": for (name, data) in self.measurements.items(): dictionary[self.prefix+'measured_'+name] = np.vstack([self.time,data]) # add external data for inputs for (name, data) in self.inputs.items(): dictionary[name] = np.vstack([self.time,data]) #create mesurement_data object to load into the optimization measurement_data = ExternalData(dictionary) self.options['external_data'] = measurement_data
def _get_eliminated_data_object(u_0, process_noise_names, undefined_input_names, input_names): """ Creates a ExternalData object used to eliminate the input signals from the optimization by providing values for them. Parameters:: u_0 -- A dictionary on the form dict([('input1', u1),...,('inputN', uN)]), where 'inputX' is the name of the input and uX is the value of the input at time zero. N is the number of control signals and X goes from 1 to N. process_noise_names -- A list of names of all the process noise inputs. input_names -- A list of names of all the input signals who are not pure process noise inputs. Returns:: external_data -- A ExternalData object used to eliminate the inputs. """ eliminated = OrderedDict() #Eliminate process noise and undefined inputs for name in process_noise_names + undefined_input_names: data = N.vstack([0., 0.]) eliminated[name] = data #Eliminate inputs for name in input_names: data = N.vstack([0., u_0[name]]) eliminated[name] = data external_data = ExternalData(eliminated=eliminated) return external_data
def test_par_est(self): """ Test parameter estimation. """ cost_ref = 1.1109779e-2 u_norm_ref = 0.556018602 model = self.model_illust op = self.op_illust_est_automatic # Simulate with nominal parameters n_meas = 16 sim_res = model.simulate(input=('u', lambda t: -0.2 + N.sin(t)), final_time=4., options={ 'ncp': n_meas, 'CVode_options': { 'rtol': 1e-10 } }) # Assemble external data by adding noise to simulation Q = N.diag([1., 1.]) N.random.seed(1) t_meas = sim_res['time'] sigma = 0.05 x1_meas = sim_res['x1'] + sigma * N.random.randn(n_meas + 1) x2_meas = sim_res['x2'] + sigma * N.random.randn(n_meas + 1) u_meas = sim_res['u'] data_x1 = N.vstack([t_meas, x1_meas]) data_x2 = N.vstack([t_meas, x2_meas]) data_u1 = N.vstack([t_meas, u_meas]) quad_pen = OrderedDict() quad_pen['x1'] = data_x1 quad_pen['x2'] = data_x2 eliminated = OrderedDict() eliminated['u'] = data_u1 external_data = ExternalData(Q=Q, quad_pen=quad_pen, eliminated=eliminated) # Eliminate blt_op = BLTOptimizationProblem(op) # Check remaining variables alg_vars = sorted([ var.getName() for var in blt_op.getVariables(blt_op.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(alg_vars) == 3 # Set up options dae_opts = op.optimize_options() dae_opts['init_traj'] = sim_res dae_opts['nominal_traj'] = sim_res dae_opts['external_data'] = external_data blt_opts = blt_op.optimize_options() blt_opts['init_traj'] = sim_res blt_opts['nominal_traj'] = sim_res blt_opts['external_data'] = external_data # Optimize and check result res_dae = op.optimize(options=dae_opts) res_blt = blt_op.optimize(options=blt_opts) assert_results(res_dae, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_blt, cost_ref, u_norm_ref, u_norm_rtol=1e-2) N.testing.assert_allclose([res_dae['p1'][0], res_dae['p3'][0]], [2.022765, 0.992965], rtol=2e-3) N.testing.assert_allclose([res_blt['p1'][0], res_blt['p3'][0]], [2.022765, 0.992965], rtol=2e-3)
def run_demo(with_plots=True): """ This example demonstrates how to solve parameter estimation problmes. The system is tanks with connected inlets and outlets. The objective is to estimate the outlet area of two of the tanks based on measurement data. """ # Compile and load FMU, which is used for simulation file_path = os.path.join(get_files_path(), "QuadTankPack.mop") model = load_fmu(compile_fmu('QuadTankPack.QuadTank', file_path)) # Transfer problem to CasADi Interface, which is used for estimation op = transfer_optimization_problem("QuadTankPack.QuadTank_ParEstCasADi", file_path) # Set initial states in model, which are stored in the optimization problem x_0_names = ['x1_0', 'x2_0', 'x3_0', 'x4_0'] x_0_values = op.get(x_0_names) model.set(x_0_names, x_0_values) # Load measurement data from file data_path = os.path.join(get_files_path(), "qt_par_est_data.mat") data = loadmat(data_path, appendmat=False) # Extract data series t_meas = data['t'][6000::100, 0] - 60 y1_meas = data['y1_f'][6000::100, 0] / 100 y2_meas = data['y2_f'][6000::100, 0] / 100 y3_meas = data['y3_d'][6000::100, 0] / 100 y4_meas = data['y4_d'][6000::100, 0] / 100 u1 = data['u1_d'][6000::100, 0] u2 = data['u2_d'][6000::100, 0] # Plot measurements and inputs if with_plots: plt.close(1) plt.figure(1) plt.subplot(2, 2, 1) plt.plot(t_meas, y3_meas) plt.title('x3') plt.grid() plt.subplot(2, 2, 2) plt.plot(t_meas, y4_meas) plt.title('x4') plt.grid() plt.subplot(2, 2, 3) plt.plot(t_meas, y1_meas) plt.title('x1') plt.xlabel('t[s]') plt.grid() plt.subplot(2, 2, 4) plt.plot(t_meas, y2_meas) plt.title('x2') plt.xlabel('t[s]') plt.grid() plt.close(2) plt.figure(2) plt.subplot(2, 1, 1) plt.plot(t_meas, u1) plt.hold(True) plt.title('u1') plt.grid() plt.subplot(2, 1, 2) plt.plot(t_meas, u2) plt.title('u2') plt.xlabel('t[s]') plt.hold(True) plt.grid() # Build input trajectory matrix for use in simulation u = N.transpose(N.vstack([t_meas, u1, u2])) # Simulate model response with nominal parameter values res_sim = model.simulate(input=(['u1', 'u2'], u), start_time=0., final_time=60.) # Load simulation result x1_sim = res_sim['x1'] x2_sim = res_sim['x2'] x3_sim = res_sim['x3'] x4_sim = res_sim['x4'] t_sim = res_sim['time'] u1_sim = res_sim['u1'] u2_sim = res_sim['u2'] # Check simulation results for testing purposes assert N.abs(res_sim.final('x1') - 0.05642485) < 1e-3 assert N.abs(res_sim.final('x2') - 0.05510478) < 1e-3 assert N.abs(res_sim.final('x3') - 0.02736532) < 1e-3 assert N.abs(res_sim.final('x4') - 0.02789808) < 1e-3 assert N.abs(res_sim.final('u1') - 6.0) < 1e-3 assert N.abs(res_sim.final('u2') - 5.0) < 1e-3 # Plot simulation result if with_plots: plt.figure(1) plt.subplot(2, 2, 1) plt.plot(t_sim, x3_sim) plt.subplot(2, 2, 2) plt.plot(t_sim, x4_sim) plt.subplot(2, 2, 3) plt.plot(t_sim, x1_sim) plt.subplot(2, 2, 4) plt.plot(t_sim, x2_sim) plt.figure(2) plt.subplot(2, 1, 1) plt.plot(t_sim, u1_sim, 'r') plt.subplot(2, 1, 2) plt.plot(t_sim, u2_sim, 'r') # Create external data object for optimization Q = N.diag([1., 1., 10., 10.]) data_x1 = N.vstack([t_meas, y1_meas]) data_x2 = N.vstack([t_meas, y2_meas]) data_u1 = N.vstack([t_meas, u1]) data_u2 = N.vstack([t_meas, u2]) quad_pen = OrderedDict() quad_pen['x1'] = data_x1 quad_pen['x2'] = data_x2 quad_pen['u1'] = data_u1 quad_pen['u2'] = data_u2 external_data = ExternalData(Q=Q, quad_pen=quad_pen) # Set optimization options and optimize opts = op.optimize_options() opts['n_e'] = 60 # Number of collocation elements opts['external_data'] = external_data opts['init_traj'] = res_sim opts['nominal_traj'] = res_sim res = op.optimize(options=opts) # Solve estimation problem # Extract estimated values of parameters a1_opt = res.initial("a1") a2_opt = res.initial("a2") # Print and assert estimated parameter values print(('a1: ' + str(a1_opt*1e4) + 'cm^2')) print(('a2: ' + str(a2_opt*1e4) + 'cm^2')) a_ref = [0.02656702, 0.02713898] N.testing.assert_allclose(1e4 * N.array([a1_opt, a2_opt]), a_ref, rtol=1e-4) # Load state profiles x1_opt = res["x1"] x2_opt = res["x2"] x3_opt = res["x3"] x4_opt = res["x4"] u1_opt = res["u1"] u2_opt = res["u2"] t_opt = res["time"] # Plot estimated trajectories if with_plots: plt.figure(1) plt.subplot(2, 2, 1) plt.plot(t_opt, x3_opt, 'k') plt.subplot(2, 2, 2) plt.plot(t_opt, x4_opt, 'k') plt.subplot(2, 2, 3) plt.plot(t_opt, x1_opt, 'k') plt.subplot(2, 2, 4) plt.plot(t_opt, x2_opt, 'k') plt.figure(2) plt.subplot(2, 1, 1) plt.plot(t_opt, u1_opt, 'k') plt.subplot(2, 1, 2) plt.plot(t_opt, u2_opt, 'k') plt.show()
plt.subplot(212) plt.plot(t_sim, Ts_ext_sim - 273.15, 'r', label='Simulation') plt.hold(True) plt.show() '''Clearly, there is a mismatch in the response, which is why we need calibration by tuning some parameters. ''' # Create external data object for optimization Q = N.diag([1., 1.]) data_x1 = N.vstack([t_mea, Ts_ext_mea]) data_x2 = N.vstack([t_mea, Ts_int_mea]) quad_pen = OrderedDict() quad_pen['Ts_ext'] = data_x1 quad_pen['Ts_int'] = data_x2 external_data = ExternalData(Q=Q, quad_pen=quad_pen) # Set optimization options and optimize opts = op.optimize_options() opts['n_e'] = 60 # Number of collocation elements opts['external_data'] = external_data opts['init_traj'] = res_sim opts['nominal_traj'] = res_sim res = op.optimize(options=opts) # Solve estimation problem # Extract estimated values of parameters r_opt = N.zeros([n + 1, 1]) c_opt = N.zeros([n, 1]) for i in range(0, n): r_opt[i] = res.initial('r[' + str(i + 1) + ']') c_opt[i] = res.initial('c[' + str(i + 1) + ']')
def test_change_quad_pen_input(eliminate_algebraics=False): check_changed_input('Integrator', 'u', (lambda input:ExternalData(quad_pen=input, Q = N.atleast_2d(1))), eliminate_algebraics)
def test_change_constrained_input(eliminate_algebraics=False): check_changed_input('DisturbedIntegrator', 'w', (lambda input:ExternalData(constr_quad_pen=input, Q = N.atleast_2d(1))), eliminate_algebraics)
def test_change_eliminated_input(eliminate_algebraics=False, result_mode='collocation_points'): check_changed_input('DisturbedIntegrator', 'w', (lambda input:ExternalData(eliminated=input)), eliminate_algebraics, result_mode)
def _create_external_data(self): from pyjmi.optimization.casadi_collocation import ExternalData return ExternalData(eliminated=self.external)