示例#1
0
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)
示例#4
0
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)
示例#6
0
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)
示例#8
0
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()
示例#9
0
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))
示例#10
0
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)
示例#11
0
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)
示例#12
0
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()
示例#17
0
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)
示例#18
0
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)
示例#19
0
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)
示例#20
0
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)
示例#21
0
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)
示例#23
0
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)
示例#24
0
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)
示例#26
0
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)
示例#27
0
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)
示例#30
0
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)