def test_opti_poorly_scaled_constraints( constraint_jacobian_condition_number=1e10): # Constants a = 1 b = 100 # Set up an optimization environment opti = asb.Opti() # Define optimization variables x = opti.variable(init_guess=10) y = opti.variable(init_guess=10) c = np.sqrt(constraint_jacobian_condition_number) # Define constraints opti.subject_to([x * c <= 0.9 * c, y / c <= 0.9 / c]) # Define objective f = (a - x)**2 + b * (y - x**2)**2 opti.minimize(f) # Optimize sol = opti.solve() # Check assert sol.value(x) == pytest.approx(0.9, abs=1e-4) assert sol.value(y) == pytest.approx(0.81, abs=1e-4)
def test_fuselage_aerodynamics_optimization(): opti = asb.Opti() alpha = opti.variable(init_guess=0, lower_bound=0, upper_bound=30) beta = opti.variable(init_guess=0) fuselage = asb.Fuselage(xsecs=[ asb.FuselageXSec(xyz_c=[xi, 0, 0], radius=asb.Airfoil("naca0010").local_thickness( 0.8 * xi)) for xi in np.cosspace(0, 1, 20) ], ) aero = asb.AeroBuildup(airplane=asb.Airplane(fuselages=[fuselage]), op_point=asb.OperatingPoint(velocity=10, alpha=alpha, beta=beta)).run() opti.minimize(-aero["L"] / aero["D"]) sol = opti.solve(verbose=False) print(sol.value(alpha)) assert sol.value(alpha) > 10 and sol.value(alpha) < 20 assert sol.value(beta) == pytest.approx(0, abs=1e-3) opti.minimize(aero["D"]) sol = opti.solve(verbose=False) assert sol.value(alpha) == pytest.approx(0, abs=1e-2) assert sol.value(beta) == pytest.approx(0, abs=1e-2)
def test_rosenbrock_constrained(plot=False): opti = asb.Opti() x = opti.variable(init_guess=0) y = opti.variable(init_guess=0) r = opti.parameter() f = (1 - x)**2 + (y - x**2)**2 opti.minimize(f) con = x**2 + y**2 <= r dual = opti.subject_to(con) r_values = np.linspace(1, 3) sols = [opti.solve({r: r_value}) for r_value in r_values] fs = [sol.value(f) for sol in sols] duals = [ sol.value(dual) # Ensure the dual can be evaluated for sol in sols ] if plot: fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200) plt.plot(r_values, fs, label="$f$") plt.plot(r_values, duals, label=r"Dual var. ($\frac{df}{dr}$)") plt.legend() plt.xlabel("$r$") plt.show() assert dual is not None # The dual should be a real value assert r_values[0] == pytest.approx(1) assert duals[0] == pytest.approx(0.10898760051521068, abs=1e-6)
def test_normal_problem(): """ An engineering optimization problem to minimize drag on a rectangular wing using analytical relations. Lift is effectively fixed (fixed CL, flight speed, and density, with wing area constraint) """ opti = asb.Opti() chord = opti.variable(init_guess=1) span = opti.variable(init_guess=2) AR = span / chord Re = density * velocity * chord / viscosity CD_p = 1.328 * Re**-0.5 CD_i = CL**2 / (pi * AR) opti.subject_to(chord * span == 1) opti.minimize(CD_p + CD_i) sol = opti.solve() print(f"Chord = {sol.value(chord)}") print(f"Span = {sol.value(span)}") assert sol.value(chord) == pytest.approx(0.2288630528244024) assert sol.value(span) == pytest.approx(4.369425242121806)
def test_bounds(): opti = asb.Opti() x = opti.variable(init_guess=3, log_transform=True, lower_bound=7) opti.minimize(x) sol = opti.solve() assert sol.value(x) == pytest.approx(7)
def test_warm_start(): ### Set up an optimization problem opti = asb.Opti() x = opti.variable(init_guess=10) opti.minimize( x ** 4 ) ### Now, solve the optimization problem and print out how many iterations were needed to solve it. sol = opti.solve(verbose=False) n_iterations_1 = sol.stats()['iter_count'] print(f"First run: Solved in {n_iterations_1} iterations.") ### Then, set the initial guess of the Opti problem to the solution that was found. opti.set_initial_from_sol(sol) ### Then, re-solve the problem and print how many iterations were now needed. sol = opti.solve(verbose=False) n_iterations_2 = sol.stats()['iter_count'] print(f"Second run: Solved in {n_iterations_2} iterations.") ### Assert that fewer iterations were needed after a warm-start. assert n_iterations_2 < n_iterations_1
def test_save_and_load_opti_vectorized(tmp_path): temp_filename = tmp_path / "temp.json" ### Round 1 optimization: free optimization opti = asb.Opti( cache_filename=temp_filename, variable_categories_to_freeze=[], save_to_cache_on_solve=True, ) x = opti.variable(init_guess=0, n_vars=3, category="Cat 1") y = opti.variable(init_guess=0, n_vars=3, category="Cat 2") f = cas.sumsqr(x - 1) + cas.sumsqr(y - 2) opti.minimize(f) # Optimize, save to cache, print sol = opti.solve() opti.save_solution() for i in ["x", "y", "f"]: print(f"{i}: {sol.value(eval(i))}") # Test assert sol.value(x) == pytest.approx(1) assert sol.value(y) == pytest.approx(2) assert sol.value(f) == pytest.approx(0) ### Round 2 optimization: Cat 1 is fixed from before; slightly different objective now opti = asb.Opti( cache_filename=temp_filename, variable_categories_to_freeze=["Cat 1"], load_frozen_variables_from_cache=True, ) x = opti.variable(init_guess=0, n_vars=3, category="Cat 1") y = opti.variable(init_guess=0, n_vars=3, category="Cat 2") f = cas.sumsqr(x - 3) + cas.sumsqr(y - 4) opti.minimize(f) # Optimize, save to cache, print sol = opti.solve() for i in ["x", "y", "f"]: print(f"{i}: {sol.value(eval(i))}") # Test assert sol.value(x) == pytest.approx(1) assert sol.value(y) == pytest.approx(4) assert sol.value(f) == pytest.approx(12)
def test_opti_hanging_chain_with_callback(plot=False): N = 40 m = 40 / N D = 70 * N g = 9.81 L = 1 opti = asb.Opti() x = opti.variable(init_guess=np.linspace(-2, 2, N)) y = opti.variable( init_guess=1, n_vars=N, ) distance = np.sqrt( # Distance from one node to the next np.diff(x)**2 + np.diff(y)**2) potential_energy_spring = 0.5 * D * np.sum((distance - L / N)**2) potential_energy_gravity = g * m * np.sum(y) potential_energy = potential_energy_spring + potential_energy_gravity opti.minimize(potential_energy) # Add end point constraints opti.subject_to([x[0] == -2, y[0] == 1, x[-1] == 2, y[-1] == 1]) # Add a ground constraint opti.subject_to(y >= np.cos(0.1 * x) - 0.5) # Add a callback if plot: def my_callback(iter: int): plt.plot(opti.debug.value(x), opti.debug.value(y), ".-", label=f"Iter {iter}", zorder=3 + iter) fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200) x_ground = np.linspace(-2, 2, N) y_ground = np.cos(0.1 * x_ground) - 0.5 plt.plot(x_ground, y_ground, "--k", zorder=2) else: def my_callback(iter: int): print(f"Iter {iter}") print(f"\tx = {opti.debug.value(x)}") print(f"\ty = {opti.debug.value(y)}") sol = opti.solve(callback=my_callback) assert sol.value(potential_energy) == pytest.approx(626.462, abs=1e-3) if plot: plt.show()
def test_quadcopter_navigation(): opti = asb.Opti() N = 300 time_final = 1 time = np.linspace(0, time_final, N) left_thrust = opti.variable(init_guess=0.5, scale=1, n_vars=N, lower_bound=0, upper_bound=1) right_thrust = opti.variable(init_guess=0.5, scale=1, n_vars=N, lower_bound=0, upper_bound=1) mass = 0.1 dyn = asb.FreeBodyDynamics( opti_to_add_constraints_to=opti, time=time, xe=opti.variable(init_guess=np.linspace(0, 1, N)), ze=opti.variable(init_guess=np.linspace(0, -1, N)), u=opti.variable(init_guess=0, n_vars=N), w=opti.variable(init_guess=0, n_vars=N), theta=opti.variable(init_guess=np.linspace(np.pi / 2, np.pi / 2, N)), q=opti.variable(init_guess=0, n_vars=N), X=left_thrust + right_thrust, M=(right_thrust - left_thrust) * 0.1 / 2, mass=mass, Iyy=0.5 * mass * 0.1 ** 2, g=9.81, ) opti.subject_to([ # Starting state dyn.xe[0] == 0, dyn.ze[0] == 0, dyn.u[0] == 0, dyn.w[0] == 0, dyn.theta[0] == np.radians(90), dyn.q[0] == 0, ]) opti.subject_to([ # Final state dyn.xe[-1] == 1, dyn.ze[-1] == -1, dyn.u[-1] == 0, dyn.w[-1] == 0, dyn.theta[-1] == np.radians(90), dyn.q[-1] == 0, ]) effort = np.sum( # The average "effort per second", where effort is integrated as follows: np.trapz(left_thrust ** 2 + right_thrust ** 2) * np.diff(time) ) / time_final opti.minimize(effort) sol = opti.solve() dyn.substitute_solution(sol) assert sol.value(effort) == pytest.approx(0.714563, rel=0.01) print(sol.value(effort))
def guess(eta): opti = asb.Opti() coeffs = opti.variable(init_guess=np.zeros(degree + 1)) y_model = model(coeffs) error = loss(y_model, y_data) opti.minimize(error + eta * (degree + 1)) sol = opti.solve(verbose=False) return sol.value(error) + eta * (degree + 1)
def test_bounds(): opti = asb.Opti() x = opti.variable(init_guess=5, lower_bound=3) opti.minimize(x**2) sol = opti.solve() assert sol.value(x) == pytest.approx(3)
def test_rocket_control_problem(plot=False): ### Constants T = 100 d = 50 delta = 1e-3 f = 1000 c = np.ones(T) ### Optimization opti = asb.Opti() # set up an optimization environment x = opti.variable(init_guess=np.linspace(0, d, T)) # position v = opti.variable(init_guess=d / T, n_vars=T) # velocity a = opti.variable(init_guess=0, n_vars=T) # acceleration gamma = opti.variable(init_guess=0, n_vars=T) # instantaneous fuel consumption a_max = opti.variable(init_guess=0) # maximum acceleration opti.subject_to([ cas.diff(x) == v[:-1], # physics cas.diff(v) == a[:-1], # physics x[0] == 0, # boundary condition v[0] == 0, # boundary condition x[-1] == d, # boundary condition v[-1] == 0, # boundary condition gamma >= c * a, # lower bound on instantaneous fuel consumption gamma >= -c * a, # lower bound on instantaneous fuel consumption cas.sum1(gamma) <= f, # fuel consumption limit cas.diff(a) <= delta, # jerk limits cas.diff(a) >= -delta, # jerk limits a_max >= a, # lower bound on maximum acceleration a_max >= -a, # lower bound on maximum acceleration ]) opti.minimize(a_max) # minimize the peak acceleration sol = opti.solve() # solve assert sol.value(a_max) == pytest.approx( 0.02181991952, rel=1e-3) # solved externally with Julia JuMP if plot: import matplotlib.pyplot as plt import seaborn as sns sns.set(palette=sns.color_palette("husl")) fig, ax = plt.subplots(1, 1, figsize=(8, 6), dpi=200) for i, val, lab in zip(np.arange(3), [x, v, a], ["$x$", "$v$", "$a$"]): plt.subplot(3, 1, i + 1) plt.plot(sol.value(val), label=lab) plt.xlabel(r"Time [s]") plt.ylabel(lab) plt.legend() plt.suptitle(r"Rocket Trajectory") plt.tight_layout() plt.show()
def test_solve_actual_function(): opti = asb.Opti() x = opti.variable(init_guess=-6) opti.minimize(underlying_function(x)) sol = opti.solve() assert sol.value(x) == pytest.approx(4.85358, abs=1e-3)
def test_solve_interpolated_unbounded( interpolated_model=get_interpolated_model()): opti = asb.Opti() x = opti.variable(init_guess=-5) opti.minimize(interpolated_model(x)) sol = opti.solve() assert sol.value(x) == pytest.approx(4.85358, abs=0.1)
def test_vlm_optimization_operating_point(): opti = asb.Opti() alpha = opti.variable(init_guess=0, lower_bound=-30, upper_bound=30) LD = LD_from_alpha(alpha) opti.minimize(-LD) sol = opti.solve( verbose=True, # callback=lambda _: print(f"alpha = {opti.debug.value(alpha)}") ) print(sol.value(alpha), sol.value(LD)) assert sol.value(alpha) == pytest.approx(5.85, abs=0.1)
def test_simple_scalar_optimization(): opti = asb.Opti() mach = opti.variable(init_guess=0.8, ) CD_induced = 0.1 / mach CD_wave = transonic.approximate_CD_wave( mach=mach, mach_crit=0.7, CD_wave_at_fully_supersonic=1, ) CD = CD_induced + CD_wave opti.minimize(CD) sol = opti.solve()
def test_block_move_fixed_time(): opti = asb.Opti() n_timesteps = 300 time = np.linspace(0, 1, n_timesteps) dyn = asb.DynamicsPointMass1DHorizontal( mass_props=asb.MassProperties(mass=1), x_e=opti.variable(init_guess=np.linspace(0, 1, n_timesteps)), u_e=opti.variable(init_guess=1, n_vars=n_timesteps), ) u = opti.variable(init_guess=np.linspace(1, -1, n_timesteps)) dyn.add_force( Fx=u ) dyn.constrain_derivatives( opti=opti, time=time ) opti.subject_to([ dyn.x_e[0] == 0, dyn.x_e[-1] == 1, dyn.u_e[0] == 0, dyn.u_e[-1] == 0, ]) # effort = np.sum( # np.trapz(dyn.X ** 2) * np.diff(time) # ) effort = np.sum( # More sophisticated integral-of-squares integration (closed form correct) np.diff(time) / 3 * (u[:-1] ** 2 + u[:-1] * u[1:] + u[1:] ** 2) ) opti.minimize(effort) sol = opti.solve() dyn.substitute_solution(sol) assert dyn.x_e[0] == pytest.approx(0) assert dyn.x_e[-1] == pytest.approx(1) assert dyn.u_e[0] == pytest.approx(0) assert dyn.u_e[-1] == pytest.approx(0) assert np.max(dyn.u_e) == pytest.approx(1.5, abs=0.01) assert sol.value(u)[0] == pytest.approx(6, abs=0.05) assert sol.value(u)[-1] == pytest.approx(-6, abs=0.05)
def test_quadcopter_flip(): opti = asb.Opti() N = 300 time_final = opti.variable(init_guess=1, lower_bound=0) time = np.linspace(0, time_final, N) left_thrust = opti.variable(init_guess=0.7, scale=1, n_vars=N, lower_bound=0, upper_bound=1) right_thrust = opti.variable(init_guess=0.6, scale=1, n_vars=N, lower_bound=0, upper_bound=1) mass = 0.1 dyn = asb.FreeBodyDynamics( opti_to_add_constraints_to=opti, time=time, xe=opti.variable(init_guess=np.linspace(0, 1, N)), ze=opti.variable(init_guess=0, n_vars=N), u=opti.variable(init_guess=0, n_vars=N), w=opti.variable(init_guess=0, n_vars=N), theta=opti.variable(init_guess=np.linspace(np.pi / 2, np.pi / 2 - 2 * np.pi, N)), q=opti.variable(init_guess=0, n_vars=N), X=left_thrust + right_thrust, M=(right_thrust - left_thrust) * 0.1 / 2, mass=mass, Iyy=0.5 * mass * 0.1 ** 2, g=9.81, ) opti.subject_to([ # Starting state dyn.xe[0] == 0, dyn.ze[0] == 0, dyn.u[0] == 0, dyn.w[0] == 0, dyn.theta[0] == np.radians(90), dyn.q[0] == 0, ]) opti.subject_to([ # Final state dyn.xe[-1] == 1, dyn.ze[-1] == 0, dyn.u[-1] == 0, dyn.w[-1] == 0, dyn.theta[-1] == np.radians(90 - 360), dyn.q[-1] == 0, ]) opti.minimize(time_final) sol = opti.solve(verbose=False) dyn.substitute_solution(sol) assert sol.value(time_final) == pytest.approx(0.824, abs=0.01)
def obj(n): ''' minimizes objective (loss+regulaization) given n and eta n contains values (0 or 1) for each variable ''' opti = asb.Opti() coeffs = opti.variable(init_guess=np.zeros(degree + 1)) y_model = model(coeffs * n) error = loss(y_model, y_data) opti.minimize(error + eta * np.sum(n)) sol = opti.solve(verbose=False) return sol.value(error) + eta * np.sum(n), sol.value(coeffs)
def test_block_move_minimum_time(): opti = asb.Opti() n_timesteps = 300 time = np.linspace( 0, opti.variable(init_guess=1, lower_bound=0), n_timesteps, ) dyn = asb.DynamicsPointMass1DHorizontal( mass_props=asb.MassProperties(mass=1), x_e=opti.variable(init_guess=np.linspace(0, 1, n_timesteps)), u_e=opti.variable(init_guess=1, n_vars=n_timesteps), ) u = opti.variable(init_guess=np.linspace(1, -1, n_timesteps), lower_bound=-1, upper_bound=1) dyn.add_force( Fx=u ) dyn.constrain_derivatives( opti=opti, time=time ) opti.subject_to([ dyn.x_e[0] == 0, dyn.x_e[-1] == 1, dyn.u_e[0] == 0, dyn.u_e[-1] == 0, ]) opti.minimize( time[-1] ) sol = opti.solve() dyn.substitute_solution(sol) assert dyn.x_e[0] == pytest.approx(0) assert dyn.x_e[-1] == pytest.approx(1) assert dyn.u_e[0] == pytest.approx(0) assert dyn.u_e[-1] == pytest.approx(0) assert np.max(dyn.u_e) == pytest.approx(1, abs=0.01) assert sol.value(u)[0] == pytest.approx(1, abs=0.05) assert sol.value(u)[-1] == pytest.approx(-1, abs=0.05) assert np.mean(np.abs(sol.value(u))) == pytest.approx(1, abs=0.01)
def lower_bound(n): ''' finds a lower bound for instance n ''' opti = asb.Opti() coeffs = opti.variable(init_guess=np.zeros(degree + 1)) n_new = np.where(n == None, 1, n) n_new = np.array(n_new) y_model = model(coeffs * n_new) error = loss(y_model, y_data) opti.minimize(error + eta * np.sum(np.where(n == None, 0, n))) sol = opti.solve(verbose=False) return sol.value(error) + eta * np.sum(np.where(n == None, 0, n))
def test_non_log_transformed_solve(): """ This is how you would solve the problem without any kind of log-transformation, and honestly, probably how you should solve this problem. Yes, log-transforming things into a geometric program makes everything convex, which is nice - however, even non-transformed, the problem is unimodal so IPOPT will find the global minimum. Forgoing the log-transform also makes the backend math faster, so it's kind of a trade-off. I tend to lean towards not log-transforming things unless they'd really cause stuff to blow up (for example, if you have some dynamic system where F=ma and mass ever goes negative, things will explode, so I might log-transform mass). Anyway, this should solve and get the same solution as the other problem formulations in this test file. """ opti = asb.Opti() # initialize an optimization environment ### Variables A = opti.variable(init_guess=10) # aspect ratio S = opti.variable(init_guess=100) # total wing area [m^2] V = opti.variable(init_guess=100) # cruising speed [m/s] W = opti.variable(init_guess=8e3) # total aircraft weight [N] C_L = opti.variable(init_guess=1) # Lift coefficient of wing [-] ### Constraints # Aerodynamics model C_D_fuse = CDA0 / S Re = (rho / mu) * V * (S / A)**0.5 C_f = 0.074 / Re**0.2 C_D_wpar = k * C_f * S_wetratio C_D_ind = C_L**2 / (pi * A * e) C_D = C_D_fuse + C_D_wpar + C_D_ind q = 0.5 * rho * V**2 D = q * S * C_D L_cruise = q * S * C_L L_takeoff = 0.5 * rho * S * C_Lmax * V_min**2 # Wing weight model W_w_strc = W_W_coeff1 * (N_ult * A**1.5 * (W_0 * W * S)**0.5) / tau W_w_surf = W_W_coeff2 * S W_w = W_w_surf + W_w_strc # Other constraints opti.subject_to([W <= L_cruise, W <= L_takeoff, W == W_0 + W_w]) # Objective opti.minimize(D) sol = opti.solve() assert sol.value(D) == pytest.approx(303.1, abs=0.1)
def test_2D_rosenbrock(): # 2-dimensional rosenbrock opti = asb.Opti() # set up an optimization environment # Define optimization variables x = opti.variable(init_guess=1) y = opti.variable(init_guess=1) # Define objective f = (a - x)**2 + b * (y - x**2)**2 opti.minimize(f) # Optimize sol = opti.solve() for i in [x, y]: assert sol.value(i) == pytest.approx(1, abs=1e-4)
def test_opti(): opti = asb.Opti() # set up an optimization environment # Define optimization variables x = opti.variable() y = opti.variable() # Define objective f = (x - 1)**2 + (y - 1)**2 opti.minimize(f) # Optimize sol = opti.solve() for i in [x, y]: assert sol.value(i) == pytest.approx(1, abs=1e-4)
def test_geometric_program_solve(): """ This still solves the problem like a geometric program (at least in the sense that the variables are log-transformed; note that the constraints aren't so it's not a true geometric program), but it removes redundant variables where possible. Basically you only need to add design variables for implicit things like total aircraft weight; no need to add unnecessary variables for explicit things like wing weight. """ opti = asb.Opti() # initialize an optimization environment ### Variables A = opti.variable(init_guess=10, log_transform=True) # aspect ratio S = opti.variable(init_guess=100, log_transform=True) # total wing area [m^2] V = opti.variable(init_guess=100, log_transform=True) # cruising speed [m/s] W = opti.variable(init_guess=8e3, log_transform=True) # total aircraft weight [N] C_L = opti.variable(init_guess=1, log_transform=True) # Lift coefficient of wing [-] ### Constraints # Aerodynamics model C_D_fuse = CDA0 / S Re = (rho / mu) * V * (S / A)**0.5 C_f = 0.074 / Re**0.2 C_D_wpar = k * C_f * S_wetratio C_D_ind = C_L**2 / (pi * A * e) C_D = C_D_fuse + C_D_wpar + C_D_ind q = 0.5 * rho * V**2 D = q * S * C_D L_cruise = q * S * C_L L_takeoff = 0.5 * rho * S * C_Lmax * V_min**2 # Wing weight model W_w_strc = W_W_coeff1 * (N_ult * A**1.5 * (W_0 * W * S)**0.5) / tau W_w_surf = W_W_coeff2 * S W_w = W_w_surf + W_w_strc # Other constraints opti.subject_to([W <= L_cruise, W <= L_takeoff, W >= W_0 + W_w]) # Objective opti.minimize(D) sol = opti.solve() assert sol.value(D) == pytest.approx(303.1, abs=0.1)
def test_airplane_optimization(): def get_aero(alpha, taper_ratio): airplane = asb.Airplane(wings=[ asb.Wing(symmetric=True, xsecs=[ asb.WingXSec( xyz_le=[-0.25, 0, 0], chord=1, ), asb.WingXSec( xyz_le=[-0.25 * taper_ratio, 1, 0], chord=taper_ratio, ) ]) ]) op_point = asb.OperatingPoint( velocity=1, alpha=alpha, ) vlm = asb.VortexLatticeMethod( airplane, op_point, chordwise_resolution=6, spanwise_resolution=6, ) return vlm.run() # tr = np.linspace(0.01, 1) # aeros = np.vectorize(get_aero)(tr) # import matplotlib.pyplot as plt # import aerosandbox.tools.pretty_plots as p # fig, ax = plt.subplots() # plt.plot(tr, [a['CL'] / a['CD'] for a in aeros]) # p.show_plot() opti = asb.Opti() alpha = opti.variable(0, lower_bound=-90, upper_bound=90) taper_ratio = opti.variable(0.7, lower_bound=0.0001, upper_bound=1) aero = get_aero(alpha, taper_ratio) CD0 = 0.01 LD = aero["CL"] / (aero["CD"] + CD0) opti.minimize(-LD) sol = opti.solve() assert sol.value(alpha) == pytest.approx(5.5, abs=1)
def test_2D_rosenbrock_frozen(): opti = asb.Opti() # set up an optimization environment # Define optimization variables x = opti.variable(init_guess=1) y = opti.variable(init_guess=0, freeze=True) # Define objective f = (a - x)**2 + b * (y - x**2)**2 opti.minimize(f) # Optimize sol = opti.solve() assert sol.value(x) == pytest.approx(0.161, abs=1e-3) assert sol.value(y) == pytest.approx(0, abs=1e-3) assert sol.value(f) == pytest.approx(0.771, abs=1e-3)
def test_save_opti(tmp_path): temp_filename = tmp_path / "temp.json" opti = asb.Opti(cache_filename=temp_filename) # set up an optimization environment # Define optimization variables x = opti.variable(init_guess=0) y = opti.variable(init_guess=0) # Define objective f = (x - 1) ** 2 + (y - 1) ** 2 opti.minimize(f) # Optimize sol = opti.solve() opti.save_solution()
def test_opti_hanging_chain_with_callback(): N = 40 m = 40 / N D = 70 * N g = 9.81 L = 1 opti = asb.Opti() x = opti.variable(n_vars=N, init_guess=cas.linspace(-2, 2, N)) y = opti.variable(n_vars=N, init_guess=1) distance = cas.sqrt( # Distance from one node to the next cas.diff(x)**2 + cas.diff(y)**2) potential_energy_spring = 0.5 * D * cas.sumsqr(distance - L / N) potential_energy_gravity = g * m * cas.sum1(y) potential_energy = potential_energy_spring + potential_energy_gravity opti.minimize(potential_energy) # Add end point constraints opti.subject_to([x[0] == -2, y[0] == 1, x[-1] == 2, y[-1] == 1]) # Add a ground constraint opti.subject_to(y >= cas.cos(0.1 * x) - 0.5) # Add a callback def plot(iter: int): plt.plot(opti.debug.value(x), opti.debug.value(y), ".-", label=f"Iter {iter}") fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200) sol = opti.solve(callback=plot) plt.legend() plt.show() assert sol.value(potential_energy) == pytest.approx(626.462, abs=1e-3)
def test_ND_rosenbrock_constrained(N=10): # N-dimensional rosenbrock # Problem is unimodal for N=2, N=3, and N>=8. Bimodal for 4<=N<=7. Global min is always a vector of ones. opti = asb.Opti() # set up an optimization environment x = opti.variable(N, init_guess=1) # vector of variables objective = 0 for i in range(N - 1): objective += 100 * (x[i + 1] - x[i]**2)**2 + (1 - x[i])**2 opti.subject_to(x >= 0) # Keeps design space unimodal for all N. opti.minimize(objective) sol = opti.solve() # solve for i in range(N): assert sol.value(x[i]) == pytest.approx(1, abs=1e-4)