def test_derivative_elimination(self): """ Test that state derivatives are not eliminated even if causalized in torn blocks. """ cost_ref = 88.740458 u_norm_ref = 4.242559212 op_manual = self.op_der_loop_manual op_automatic = self.op_der_loop_automatic # Eliminate blt_op_manual = BLTOptimizationProblem(op_manual) blt_op_automatic = BLTOptimizationProblem(op_automatic) # Check remaining variables var_manual = sorted([ var.getName() for var in blt_op_manual.getVariables(blt_op_manual.REAL_ALGEBRAIC) if not var.isAlias() ]) var_automatic = sorted([ var.getName() for var in blt_op_automatic.getVariables( blt_op_automatic.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_manual) == 2 assert len(var_automatic) == 1 # Optimize and check result res_manual = blt_op_manual.optimize() res_automatic = blt_op_automatic.optimize() assert_results(res_manual, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_automatic, cost_ref, u_norm_ref, u_norm_rtol=1e-2)
def test_automatic_tearing(self): """ Test consistency between with and without automatic tearing. """ cost_ref = 1.06183273 u_norm_ref = 0.398219663 # Perform elimination blt_op_automatic = BLTOptimizationProblem(self.op_illust_automatic) blt_op_manual = BLTOptimizationProblem(self.op_illust_manual) # Check remaining variables var_automatic = sorted([ var.getName() for var in blt_op_automatic.getVariables( blt_op_automatic.REAL_ALGEBRAIC) if not var.isAlias() ]) var_manual = sorted([ var.getName() for var in blt_op_manual.getVariables(blt_op_manual.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_automatic) == 3 assert len(var_manual) == 4 # Optimize and check result res_automatic = blt_op_automatic.optimize() res_manual = blt_op_manual.optimize() assert_results(res_automatic, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_manual, cost_ref, u_norm_ref, u_norm_rtol=1e-2)
def test_closed_form(self): """ Test creation of closed form expressions when not using tearing. """ # Perform elimination elim_opts = EliminationOptions() elim_opts['inline_solved'] = True elim_opts['closed_form'] = True blt_op = BLTOptimizationProblem(self.op_illust_manual, elim_opts) for res in blt_op.getDaeResidual(): if 'y1)*y2)*' in res.getRepresentation(): residual = res.getRepresentation() N.testing.assert_string_equal(residual, "SX(((((2*y1)*y2)*sqrt(y5))-sqrt(x1)))")
def test_ineliminable(self): """ Test ineliminable variables for both manual and automatic tearing. """ cost_ref = 1.08181340 u_norm_ref = 0.399868319 # Mark bounded varible as ineliminable elim_opts = EliminationOptions() elim_opts['ineliminable'] = ['y1'] # Manual tearing op_manual = self.op_illust_manual_bound op_manual.getVariable('y3').setTearing(True) for eq in op_manual.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(True) blt_op_manual = BLTOptimizationProblem(op_manual, elim_opts) # Automatic and manual tearing op_hybrid = self.op_illust_automatic_bound op_hybrid.getVariable('y1').setTearing(False) for eq in op_hybrid.getDaeEquations(): if '(y1*y4)+sqrt(y3)' in eq.getResidual().getRepresentation(): eq.setTearing(False) blt_op_hybrid = BLTOptimizationProblem(op_hybrid, elim_opts) # Check remaining variables var_manual = sorted([ var.getName() for var in blt_op_manual.getVariables(blt_op_manual.REAL_ALGEBRAIC) if not var.isAlias() ]) var_hybrid = sorted([ var.getName() for var in blt_op_hybrid.getVariables(blt_op_hybrid.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_manual) == 3 assert len(var_hybrid) == 3 # Optimize and check result res_manual = blt_op_manual.optimize() res_hybrid = blt_op_hybrid.optimize() assert_results(res_manual, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_hybrid, cost_ref, u_norm_ref, u_norm_rtol=1e-2) # Reset tearing choices op_manual.getVariable('y3').setTearing(False) for eq in op_manual.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(False) op_hybrid.getVariable('y1').setTearing(True) for eq in op_hybrid.getDaeEquations(): if '(y1*y4)+sqrt(y3)' in eq.getResidual().getRepresentation(): eq.setTearing(True)
def test_linear_tearing(self): """ Test solution of torn linear blocks both symbolically with SX and numerically with MX. Numerical part of the test has been disabled, see #5208. """ cost_ref = 2.5843277 u_norm_ref = 0.647282415 # Select linear solver nonlinear_opts = EliminationOptions() nonlinear_opts['solve_blocks'] = False symbolic_opts = EliminationOptions() symbolic_opts['solve_blocks'] = True symbolic_opts['solve_torn_linear_blocks'] = True symbolic_opts['linear_solver'] = "symbolicqr" numeric_opts = EliminationOptions() numeric_opts['solve_blocks'] = True numeric_opts['solve_torn_linear_blocks'] = True numeric_opts['linear_solver'] = "lapackqr" numeric_op_opts = {'expand_to_sx': 'no'} # Eliminate op = self.op_loop_automatic blt_op_nonlinear = BLTOptimizationProblem(op, nonlinear_opts) blt_op_symbolic = BLTOptimizationProblem(op, symbolic_opts) #~ blt_op_numeric = BLTOptimizationProblem(op, numeric_opts) # Check remaining variables var_nonlinear = sorted([ var.getName() for var in blt_op_nonlinear.getVariables( blt_op_nonlinear.REAL_ALGEBRAIC) if not var.isAlias() ]) var_symbolic = sorted([ var.getName() for var in blt_op_symbolic.getVariables( blt_op_symbolic.REAL_ALGEBRAIC) if not var.isAlias() ]) #~ var_numeric = sorted([var.getName() for var in blt_op_numeric.getVariables(blt_op_numeric.REAL_ALGEBRAIC) #~ if not var.isAlias()]) assert len(var_nonlinear) == 1 assert len(var_symbolic) == 0 #~ assert len(var_numeric) == 0 # Optimize and check result res_nonlinear = blt_op_nonlinear.optimize() res_symbolic = blt_op_symbolic.optimize() #~ res_numeric = blt_op_numeric.optimize(options=numeric_op_opts) assert_results(res_nonlinear, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_symbolic, cost_ref, u_norm_ref, u_norm_rtol=1e-2)
def test_constraint_and_objective(self): """ Test eliminating variables occurring in constraints and objective. """ cost_ref = 1.08181340 u_norm_ref = 0.399868319 # Mark bounded varible as ineliminable for reference inelim_opts = EliminationOptions() inelim_opts['ineliminable'] = ['y1'] elim_opts = EliminationOptions() # Manual tearing op = self.op_illust_manual_constraint op.getVariable('y3').setTearing(True) for eq in op.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(True) blt_op_inelim = BLTOptimizationProblem(op, inelim_opts) blt_op_elim = BLTOptimizationProblem(op, elim_opts) # Check remaining variables var_inelim = sorted([ var.getName() for var in blt_op_inelim.getVariables(blt_op_inelim.REAL_ALGEBRAIC) if not var.isAlias() ]) var_elim = sorted([ var.getName() for var in blt_op_elim.getVariables(blt_op_elim.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_inelim) == 3 assert len(var_elim) == 2 # Optimize and check result res_inelim = blt_op_inelim.optimize() res_elim = blt_op_elim.optimize() assert_results(res_inelim, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_elim, cost_ref, u_norm_ref, u_norm_rtol=1e-2) # Reset tearing choices op.getVariable('y3').setTearing(False) for eq in op.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(False)
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 test_sparsity_preservation(self): """ Test sparsity preservation for both LMFI and Markowitz. """ cost_ref = 1.06183273 u_norm_ref = 0.398219663 # Specify sparsity preservation elim_opts_lmfi = EliminationOptions() elim_opts_lmfi['dense_tol'] = 2 elim_opts_lmfi['dense_measure'] = "lmfi" elim_opts_mrkwtz = EliminationOptions() elim_opts_mrkwtz['dense_tol'] = 4 elim_opts_mrkwtz['dense_measure'] = "Markowitz" elim_opts_mrkwtz2 = EliminationOptions() elim_opts_mrkwtz2['dense_tol'] = 2 elim_opts_mrkwtz2['dense_measure'] = "Markowitz" # Manual tearing op = self.op_illust_manual op.getVariable('y3').setTearing(True) for eq in op.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(True) blt_op_lmfi = BLTOptimizationProblem(op, elim_opts_lmfi) blt_op_mrkwtz = BLTOptimizationProblem(op, elim_opts_mrkwtz) blt_op_mrkwtz2 = BLTOptimizationProblem(op, elim_opts_mrkwtz2) # Check remaining variables var_lmfi = sorted([ var.getName() for var in blt_op_lmfi.getVariables(blt_op_lmfi.REAL_ALGEBRAIC) if not var.isAlias() ]) var_mrkwtz = sorted([ var.getName() for var in blt_op_mrkwtz.getVariables(blt_op_mrkwtz.REAL_ALGEBRAIC) if not var.isAlias() ]) var_mrkwtz2 = sorted([ var.getName() for var in blt_op_mrkwtz2.getVariables( blt_op_mrkwtz.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_lmfi) == 3 assert len(var_mrkwtz) == 3 assert len(var_mrkwtz2) == 4 # Optimize and check result res_lmfi = blt_op_lmfi.optimize() res_mrkwtz = blt_op_mrkwtz.optimize() res_mrkwtz2 = blt_op_mrkwtz2.optimize() assert_results(res_lmfi, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_mrkwtz, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_mrkwtz2, cost_ref, u_norm_ref, u_norm_rtol=1e-2) # Reset tearing choices op.getVariable('y3').setTearing(False) for eq in op.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(False)
def test_hybrid_tearing(self): """ Test consistency between manual and automatic tearing as well as the combination of both. """ cost_ref = 1.06183273 u_norm_ref = 0.398219663 # Automatic tearing blt_op_automatic = BLTOptimizationProblem(self.op_illust_automatic) # Manual tearing op_manual = self.op_illust_manual op_manual.getVariable('y3').setTearing(True) for eq in op_manual.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(True) blt_op_manual = BLTOptimizationProblem(op_manual) # Automatic and manual tearing op_hybrid = self.op_illust_automatic op_hybrid.getVariable('y1').setTearing(False) for eq in op_hybrid.getDaeEquations(): if '(y1*y4)+sqrt(y3)' in eq.getResidual().getRepresentation(): eq.setTearing(False) blt_op_hybrid = BLTOptimizationProblem(op_hybrid) # Check remaining variables var_automatic = sorted([ var.getName() for var in blt_op_automatic.getVariables( blt_op_automatic.REAL_ALGEBRAIC) if not var.isAlias() ]) var_manual = sorted([ var.getName() for var in blt_op_manual.getVariables(blt_op_manual.REAL_ALGEBRAIC) if not var.isAlias() ]) var_hybrid = sorted([ var.getName() for var in blt_op_hybrid.getVariables(blt_op_hybrid.REAL_ALGEBRAIC) if not var.isAlias() ]) assert len(var_automatic) == 3 assert len(var_manual) == 2 assert len(var_hybrid) == 2 # Optimize and check result res_automatic = blt_op_automatic.optimize() res_manual = blt_op_manual.optimize() res_hybrid = blt_op_hybrid.optimize() assert_results(res_automatic, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_manual, cost_ref, u_norm_ref, u_norm_rtol=1e-2) assert_results(res_hybrid, cost_ref, u_norm_ref, u_norm_rtol=1e-2) # Reset tearing choices op_manual.getVariable('y3').setTearing(False) for eq in op_manual.getDaeEquations(): if 'y1)*y2)*y4)' in eq.getResidual().getRepresentation(): eq.setTearing(False) op_hybrid.getVariable('y1').setTearing(True) for eq in op_hybrid.getDaeEquations(): if '(y1*y4)+sqrt(y3)' in eq.getResidual().getRepresentation(): eq.setTearing(True)
def run_demo(with_plots=True): """ This example solves the optimization problem from pyjmi.examples.ccpp using the Python-based symbolic elimination. """ # Load initial gues init_path = os.path.join(get_files_path(), "ccpp_init.txt") init_res = LocalDAECollocationAlgResult( result_data=ResultDymolaTextual(init_path)) # Compile model class_name = "CombinedCycleStartup.Startup6" file_paths = (os.path.join(get_files_path(), "CombinedCycle.mo"), os.path.join(get_files_path(), "CombinedCycleStartup.mop")) compiler_options = {'equation_sorting': True, 'automatic_tearing': True} op = transfer_optimization_problem("CombinedCycleStartup.Startup6", file_paths, compiler_options) # Set elimination options elim_opts = EliminationOptions() elim_opts['ineliminable'] = ['plant.sigma'] if with_plots: elim_opts['draw_blt'] = True # Eliminate algebraic variables op = BLTOptimizationProblem(op, elim_opts) # Set collocation options opt_opts = op.optimize_options() opt_opts['init_traj'] = init_res opt_opts['nominal_traj'] = init_res # Solve the optimal control problem opt_res = op.optimize(options=opt_opts) # Extract variable profiles opt_plant_p = opt_res['plant.p'] opt_plant_sigma = opt_res['plant.sigma'] opt_plant_load = opt_res['plant.load'] opt_time = opt_res['time'] # Plot the optimized trajectories if with_plots: plt.close(2) plt.figure(2) plt.subplot(3, 1, 1) plt.plot(opt_time, opt_plant_p * 1e-6) plt.ylabel('evaporator pressure [MPa]') plt.grid(True) plt.title('Optimized trajectories') plt.subplot(3, 1, 2) plt.plot(opt_time, opt_plant_sigma * 1e-6) plt.grid(True) plt.ylabel('turbine thermal stress [MPa]') plt.subplot(3, 1, 3) plt.plot(opt_time, opt_plant_load) plt.grid(True) plt.ylabel('input load [1]') plt.xlabel('time [s]') # Verify solution for testing purposes try: import casadi except: pass else: cost = float(opt_res.solver.solver_object.getOutput('f')) N.testing.assert_allclose(cost, 17492.465548193624, rtol=1e-5)
def run_demo(with_plots=True): """ Demonstrate symbolic elimination. """ # Compile and load optimization problem file_path = os.path.join(get_files_path(), "JMExamples_opt.mop") compiler_options = {'equation_sorting': True, 'automatic_tearing': True} op = transfer_optimization_problem("JMExamples_opt.EliminationExample", file_path, compiler_options) # Set up and perform elimination elim_opts = EliminationOptions() elim_opts['ineliminable'] = [ 'y1' ] # Provide list of variable names to not eliminate # Variables with any of the following properties are recommended to mark as ineliminable: # Potentially active bounds # Occurring in the objective or constraints # Numerically unstable pivots (difficult to predict) if with_plots: elim_opts['draw_blt'] = True elim_opts['draw_blt_strings'] = True op = BLTOptimizationProblem(op, elim_opts) # Optimize and extract solution res = op.optimize() x1 = res['x1'] x2 = res['x2'] y1 = res['y1'] u = res['u'] time = res['time'] # Plot if with_plots: plt.figure(1) plt.clf() plt.subplot(4, 1, 1) plt.plot(time, x1) plt.grid() plt.ylabel('x1') plt.subplot(4, 1, 2) plt.plot(time, x2) plt.grid() plt.ylabel('x2') plt.subplot(4, 1, 3) plt.plot(time, y1) plt.grid() plt.ylabel('y1') plt.subplot(4, 1, 4) plt.plot(time, u) plt.grid() plt.ylabel('u') plt.xlabel('time') plt.show() # Verify solution for testing purposes try: import casadi except: pass else: cost = float(res.solver.solver_object.getOutput('f')) N.testing.assert_allclose(cost, 1.0818134, rtol=1e-4)
def run_demo(with_plots=True, use_ma57=True): """ This example is based on a single-track model of a car with tire dynamics. The optimization problem is to minimize the duration of a 90-degree turn with actuators on the steer angle and front and rear wheel torques. This example also demonstrates the usage of blocking factors, to enforce piecewise constant inputs. This example needs one of the linear solvers MA27 or MA57 to work. The precense of MA27 or MA57 is not detected in the example, so if only MA57 is present, then True must be passed in the use_ma57 argument. """ # Set up optimization mop_path = os.path.join(get_files_path(), "vehicle_turn.mop") op = transfer_optimization_problem('Turn', mop_path) opts = op.optimize_options() opts['IPOPT_options']['linear_solver'] = "ma57" if use_ma57 else "ma27" opts['IPOPT_options']['tol'] = 1e-9 opts['n_e'] = 60 # Set blocking factors factors = { 'delta_u': opts['n_e'] / 2 * [2], 'Twf_u': opts['n_e'] / 4 * [4], 'Twr_u': opts['n_e'] / 4 * [4] } rad2deg = 180. / (2 * N.pi) du_bounds = {'delta_u': 2. / rad2deg} bf = BlockingFactors(factors, du_bounds=du_bounds) opts['blocking_factors'] = bf # Use Dymola simulation result as initial guess init_path = os.path.join(get_files_path(), "vehicle_turn_dymola.txt") init_guess = ResultDymolaTextual(init_path) opts['init_traj'] = init_guess # Symbolic elimination op = BLTOptimizationProblem(op) # Solve optimization problem res = op.optimize(options=opts) # Extract solution time = res['time'] X = res['car.X'] Y = res['car.Y'] delta = res['delta_u'] Twf = res['Twf_u'] Twr = res['Twr_u'] Ri = op.get('Ri') Ro = op.get('Ro') # Verify result N.testing.assert_allclose(time[-1], 4.0118, rtol=5e-3) # Plot solution if with_plots: # Plot road plt.close(1) plt.figure(1) plt.plot(X, Y, 'b') xi = N.linspace(0., Ri, 100) xo = N.linspace(0., Ro, 100) yi = (Ri**8 - xi**8)**(1. / 8.) yo = (Ro**8 - xo**8)**(1. / 8.) plt.plot(xi, yi, 'r--') plt.plot(xo, yo, 'r--') plt.xlabel('X [m]') plt.ylabel('Y [m]') plt.legend(['position', 'road'], loc=3) # Plot inputs plt.close(2) plt.figure(2) plt.plot(time, delta * rad2deg, drawstyle='steps-post') plt.plot(time, Twf * 1e-3, drawstyle='steps-post') plt.plot(time, Twr * 1e-3, drawstyle='steps-post') plt.xlabel('time [s]') plt.legend(['delta [deg]', 'Twf [kN]', 'Twr [kN]'], loc=4) plt.show()
def run_demo(with_plots=True): """ This example is based on the multibody mechanics double pendulum example from the Modelica Standard Library (MSL). The MSL example has been modified by adding a torque on the first revolute joint of the pendulum as a top-level input. The considered optimization problem is to invert both pendulum bodies with bounded torque. This example needs linear solver MA27 to work. """ # Simulate system with linear state feedback to generate initial guess file_paths = (os.path.join(get_files_path(), "DoublePendulum.mo"), os.path.join(get_files_path(), "DoublePendulum.mop")) comp_opts = {'inline_functions': 'all', 'dynamic_states': False, 'expose_temp_vars_in_fmu': True, 'equation_sorting': True, 'automatic_tearing': True} init_fmu = load_fmu(compile_fmu("DoublePendulum.Feedback", file_paths, compiler_options=comp_opts)) init_res = init_fmu.simulate(final_time=3., options={'CVode_options': {'rtol': 1e-10}}) # Set up optimization op = transfer_optimization_problem('Opt', file_paths, compiler_options=comp_opts) opts = op.optimize_options() opts['IPOPT_options']['linear_solver'] = "ma27" opts['n_e'] = 100 opts['init_traj'] = init_res opts['nominal_traj'] = init_res # Symbolic elimination op = BLTOptimizationProblem(op) # Solve optimization problem res = op.optimize(options=opts) # Extract solution time = res['time'] phi1 = res['pendulum.revolute1.phi'] phi2 = res['pendulum.revolute2.phi'] u = res['u'] # Verify solution for testing purposes try: import casadi except: pass else: cost = float(res.solver.solver_object.output(casadi.NLP_SOLVER_F)) N.testing.assert_allclose(cost, 9.632883808252522, rtol=5e-3) # Plot solution if with_plots: plt.close(1) plt.figure(1) plt.subplot(2, 1, 1) plt.plot(time, phi1, 'b') plt.plot(time, phi2, 'r') plt.legend(['$\phi_1$', '$\phi_2$']) plt.ylabel('$\phi$') plt.xlabel('$t$') plt.grid() plt.subplot(2, 1, 2) plt.plot(time, u) plt.ylabel('$u$') plt.xlabel('$t$') plt.grid() plt.show()