예제 #1
0
def run_process(f, pipe):
    xbar = Parameter(n, value=np.zeros(n))
    u = Parameter(n, value=np.zeros(n))
    f += (rho/2)*sum_squares(x - xbar + u)
    prox = Problem(Minimize(f))
    # ADMM loop.
    while True:
        prox.solve()
        pipe.send(x.value)
        xbar.value = pipe.recv()
        u.value += x.value - xbar.value
예제 #2
0
    def test_warm_start(self):
        """Test warm start.
        """
        m = 200
        n = 100
        np.random.seed(1)
        A = np.random.randn(m, n)
        b = Parameter(m)

        # Construct the problem.
        x = Variable(n)
        prob = Problem(Minimize(sum_squares(A * x - b)))

        b.value = np.random.randn(m)
        result = prob.solve(warm_start=False)
        result2 = prob.solve(warm_start=True)
        self.assertAlmostEqual(result, result2)
        b.value = np.random.randn(m)
        result = prob.solve(warm_start=True)
        result2 = prob.solve(warm_start=False)
        self.assertAlmostEqual(result, result2)
        pass
예제 #3
0
    def test_parametric(self):
        """Test solve parametric problem vs full problem"""
        x = Variable()
        a = 10
        #  b_vec = [-10, -2., 2., 3., 10.]
        b_vec = [-10, -2.]

        for solver in self.solvers:

            print(solver)
            # Solve from scratch with no parameters
            x_full = []
            obj_full = []
            for b in b_vec:
                obj = Minimize(a * (x ** 2) + b * x)
                constraints = [0 <= x, x <= 1]
                prob = Problem(obj, constraints)
                prob.solve(solver=solver)
                x_full += [x.value]
                obj_full += [prob.value]

            # Solve parametric
            x_param = []
            obj_param = []
            b = Parameter()
            obj = Minimize(a * (x ** 2) + b * x)
            constraints = [0 <= x, x <= 1]
            prob = Problem(obj, constraints)
            for b_value in b_vec:
                b.value = b_value
                prob.solve(solver=solver)
                x_param += [x.value]
                obj_param += [prob.value]

            print(x_full)
            print(x_param)
            for i in range(len(b_vec)):
                self.assertItemsAlmostEqual(x_full[i], x_param[i], places=3)
                self.assertAlmostEqual(obj_full[i], obj_param[i])
예제 #4
0
	def test_lasso(self):
		# Solve the following consensus problem using ADMM:
		# Minimize sum_squares(A*x - b) + gamma*norm(x,1)
		
		# Problem data.
		m = 100
		n = 75
		np.random.seed(1)
		A = np.random.randn(m,n)
		b = np.random.randn(m)
		
		# Separate penalty from regularizer.
		x = Variable(n)
		gamma = Parameter(nonneg = True)
		funcs = [sum_squares(A*x - b), gamma*norm(x,1)]
		p_list = [Problem(Minimize(f)) for f in funcs]
		probs = Problems(p_list)
		
		# Solve via consensus.
		gamma.value = 1.0
		probs.solve(method = "consensus", rho_init = 1.0, max_iter = 50)
		print("Objective:", probs.value)
		print("Solution:", x.value)
예제 #5
0
                        u[:, k] <= umax]  # input interval constraint
    objective += quad_form(x[:, Np] - xref, QN)
    prob = Problem(Minimize(objective), constraints)

    # Simulate in closed loop
    len_sim = 15  # simulation length (s)
    nsim = int(len_sim / Ts)  # simulation length(timesteps)
    xsim = np.zeros((nsim, nx))
    usim = np.zeros((nsim, nu))
    tsol = np.zeros((nsim, 1))
    tsim = np.arange(0, nsim) * Ts

    #    uminus1_val = uinit  # initial previous measured input is the input at time instant -1.
    time_start = time.time()
    for i in range(nsim):
        x_init.value = x0  # set value to the x_init cvx parameter to x0

        time_start = time.time()
        prob.solve(solver=OSQP, warm_start=True)
        tsol[i] = 1000 * (time.time() - time_start)

        uMPC = u[:, 0].value
        usim[i, :] = uMPC
        x0 = Ad.dot(x0) + Bd.dot(uMPC)
        xsim[i, :] = x0

#        uminus1_val = uMPC # or a measurement if the input is affected by noise
    time_sim = time.time() - time_start

    # In[Plot time traces]
    fig, axes = plt.subplots(3, 1, figsize=(10, 10))
예제 #6
0
# with a (non-convex) cardinality constraint.

# Generate data.
np.random.seed(1)
N = 50
M = 40
n = 10
data = []
for i in range(N):
    data += [(1, np.random.normal(1.0, 2.0, (n, 1)))]
for i in range(M):
    data += [(-1, np.random.normal(-1.0, 2.0, (n, 1)))]

# Construct problem.
gamma = Parameter(nonneg=True)
gamma.value = 0.1
# 'a' is a variable constrained to have at most 6 non-zero entries.
a = Card(n, k=6)
b = Variable()

slack = [pos(1 - label*(sample.T*a - b)) for (label, sample) in data]
objective = Minimize(norm(a, 2) + gamma*sum(slack))
p = Problem(objective)
# Extensions can attach new solve methods to the CVXPY Problem class.
p.solve(method="admm")

# Count misclassifications.
error = 0
for label, sample in data:
    if not label*(a.value.T*sample - b.value)[0] >= 0:
        error += 1
예제 #7
0
L = Parameter(n)
U = Parameter(n)
f = lambda x: sum_squares(A*x - b)
prob = Problem(Minimize(f(x)),
               [L <= x, x <= U])

visited = 0
best_solution = numpy.inf
best_x = 0
nodes = PriorityQueue()
nodes.put((numpy.inf, 0, -numpy.ones(n), numpy.ones(n), 0))
while not nodes.empty():
    visited += 1
    # Evaluate the node with the lowest lower bound.
    _, _, L_val, U_val, idx = nodes.get()
    L.value = L_val
    U.value = U_val
    lower_bound = prob.solve()
    upper_bound = f(numpy.sign(x.value)).value
    best_solution = min(best_solution, upper_bound)
    if upper_bound == best_solution:
        best_x = numpy.sign(x.value)
    # Add new nodes if not at a leaf and the branch cannot be pruned.
    if idx < n and lower_bound < best_solution:
        for i in [-1, 1]:
            L_val[idx] = U_val[idx] = i
            nodes.put((lower_bound, i, L_val.copy(), U_val.copy(), idx + 1))

print("Nodes visited: %s out of %s" % (visited, 2**(n+1)-1))
print("Optimal solution:", best_solution)
print(best_x)
예제 #8
0
    # Simulate in closed loop
    nsim = int(len_sim / Ts)  # simulation length(timesteps)
    xsim = np.zeros((nsim, nx))
    ysim = np.zeros((nsim, ny))
    gsim = np.zeros((nsim, ng))
    tsol = np.zeros((nsim, 1))
    tsim = np.arange(0, nsim) * Ts

    gMPC = ginit  # initial previous measured input is the input at time instant -1.
    time_start = time.time()
    for i in range(nsim):

        yold = Cd @ x0 + Dd @ gMPC
        ysim[i, :] = yold

        x_init.value = x0  # set value to the x_init cvx parameter to x0
        gminus1.value = gMPC
        yminus1.value = yold
        r.value = np.array(2 * [1.0])  # Reference output

        time_start = time.time()
        prob.solve(solver=OSQP, warm_start=True)
        tsol[i] = 1000 * (time.time() - time_start)

        gMPC = g[:, 0].value
        gsim[i, :] = gMPC
        x0 = Ad.dot(x0) + Bd.dot(gMPC)
        xsim[i, :] = x0

    time_sim = time.time() - time_start
예제 #9
0
    y_sim = np.zeros((n_sim, ny))
    g_sim = np.zeros((n_sim, ng))
    t_MPC = np.zeros((n_sim, 1))
    t_sim = np.arange(0, n_sim) * Ts

    g_step_old = gm1  # initial previous measured input is the input at time instant -1.
    x_step = x0
    y_step_old = y0
    time_start = time.time()
    for i in range(n_sim):

        x_sim[i, :] = x_step

        # MPC Control law computation
        time_start = time.time()
        x_init.value = x_step  # set value to the x_init cvx parameter to x0
        gminus1.value = g_step_old
        yminus1.value = y_step_old
        r.value = np.array(2 * [1.0])  # Reference output
        prob.solve(solver=OSQP, warm_start=True)
        g_step = g[:, 0].value
        time_MPC = 1000 * (time.time() - time_start)
        t_MPC[i] = time_MPC  # MPC control law computation time

        y_step = Cd @ x_step + Dd @ g_step
        y_sim[i, :] = y_step
        g_sim[i, :] = g_step

        # System update
        x_step = Ad @ x_step + Bd @ g_step
        y_step_old = y_step  # like an additional state
    prob = Problem(Minimize(objective), constraints)

    # Simulate in closed loop
    nsim = int(len_sim/Ts)  # simulation length(timesteps)
    xsim = np.zeros((nsim, nx))
    ysim = np.zeros((nsim, ny))
    usim = np.zeros((nsim, nu))
    tsol = np.zeros((nsim, 1))
    tsim = np.arange(0, nsim)*Ts

    uMPC = ginit  # initial previous measured input is the input at time instant -1.
    time_start = time.time()
    for i in range(nsim):

        ysim[i, :] = Cd @ x0
        x_init.value = x0  # set value to the x_init cvx parameter to x0
        uminus1.value = uMPC

        time_start = time.time()
        prob.solve(solver=OSQP, warm_start=True)
        tsol[i] = 1000*(time.time() - time_start)

        uMPC = u[:, 0].value
        usim[i, :] = uMPC
        x0 = Ad.dot(x0) + Bd.dot(uMPC)
        xsim[i, :] = x0

    time_sim = time.time() - time_start

    # In[Plot time traces]
    fig, axes = plt.subplots(3, 1, figsize=(10, 10))
예제 #11
0
def calculate_portfolio(cvxtype, returns_function, long_only, exp_return, 
                        selected_solver, max_pos_size, ticker_list):
    assert cvxtype in ['minimize_risk','maximize_return']
    
    """ Variables:
        mu is the vector of expected returns.
        sigma is the covariance matrix.
        gamma is a Parameter that trades off risk and return.
        x is a vector of stock holdings as fractions of total assets.
    """
    
    gamma = Parameter(nonneg=True)
    gamma.value = 1
    returns, stocks, betas = returns_function
        
    cov_mat = returns.cov()
    Sigma = cov_mat.values # np.asarray(cov_mat.values) 
    w = Variable(len(cov_mat))  # #number of stocks for portfolio weights
    risk = quad_form(w, Sigma)  #expected_variance => w.T*C*w =  quad_form(w, C)
    # num_stocks = len(cov_mat)
    
    if cvxtype == 'minimize_risk': # Minimize portfolio risk / portfolio variance
        if long_only == True:
            prob = Problem(Minimize(risk), [sum(w) == 1, w > 0 ])  # Long only
        else:
            prob = Problem(Minimize(risk), [sum(w) == 1]) # Long / short 
    
    elif cvxtype == 'maximize_return': # Maximize portfolio return given required level of risk
        #mu  #Expected return for each instrument
        #expected_return = mu*x
        #risk = quad_form(x, sigma)
        #objective = Maximize(expected_return - gamma*risk)
        #p = Problem(objective, [sum_entries(x) == 1])
        #result = p.solve()

        mu = np.array([exp_return]*len(cov_mat)) # mu is the vector of expected returns.
        expected_return = np.reshape(mu,(-1,1)).T * w  # w is a vector of stock holdings as fractions of total assets.   
        objective = Maximize(expected_return - gamma*risk) # Maximize(expected_return - expected_variance)
        if long_only == True:
            constraints = [sum(w) == 1, w > 0]
        else: 
            #constraints=[sum_entries(w) == 1,w <= max_pos_size, w >= -max_pos_size]
            constraints=[sum(w) == 1]
        prob = Problem(objective, constraints)

    prob.solve(solver=selected_solver)
    
    weights = []

    for weight in w.value:
        weights.append(float(weight))
        
    if cvxtype == 'maximize_return':
        optimal_weights = {"Optimal expected return":expected_return.value,
                        "Optimal portfolio weights":np.round(weights,2),
                        "tickers": ticker_list,
                        "Optimal risk": risk.value*100
                        }
        
    elif cvxtype == 'minimize_risk':
        optimal_weights = {"Optimal portfolio weights":np.round(weights,2),
                        "tickers": ticker_list,
                        "Optimal risk": risk.value*100
                        }   
    return optimal_weights
예제 #12
0
def main():
    class MyParser(argparse.ArgumentParser):
        def error(self, message):
            sys.stderr.write('error: %s\n' % message)
            self.print_help()
            sys.exit(2)

    parser = MyParser()
    parser.add_argument("-f",
                        "--file",
                        dest="filename",
                        help="data file in CSV format",
                        metavar="FILENAME")

    parser.add_argument("-o",
                        "--output",
                        dest="output",
                        help="output in CSV format",
                        metavar="OUTPUT")

    parser.add_argument("-ofig",
                        "--outfigures",
                        dest="outfigures",
                        help="output plots in PDF format",
                        metavar="OUTFIGURES")

    parser.add_argument("-t",
                        "--threshold",
                        dest="threshold",
                        help="threshold distance",
                        metavar="THRESHOLD")

    parser.add_argument("-r",
                        "--regularization",
                        dest="regularization",
                        help="tv, tviso, divergence, tvtrace",
                        metavar="REGULARIZATION")

    parser.add_argument("-n",
                        "--nsolutions",
                        dest="nsolutions",
                        help="number of solutions",
                        metavar="NSOLUTIONS")

    parser.add_argument("-s",
                        "--solver",
                        dest="solver",
                        help="solver (cvxopt, ecos)",
                        metavar="SOLVER")

    results = parser.parse_args()

    figure_outfile = "figureoutput.pdf" if results.outfigures is None else results.outfigures
    csv_outfile = "fittedout.csv" if results.output is None else results.output
    CUTOFF = 16 if results.threshold is None else float(results.threshold)
    REGULARIZATION = "tvnorm" if results.regularization is None else results.regularization
    N_SOLUTIONS = 10 if results.nsolutions is None else int(
        float(results.nsolutions))

    coords, deflection, boundary = read_data(results.filename)

    # let's see if we have gridded data. If we do, then use the implicit data grid for all computations
    x_obs_positions = sorted(set(coords[:, 0]))
    y_obs_positions = sorted(set(coords[:, 1]))

    dx = abs(x_obs_positions[1] - x_obs_positions[0])
    dy = abs(y_obs_positions[1] - y_obs_positions[0])

    N = len(x_obs_positions)
    M = len(y_obs_positions)

    boundary2d = boundary.reshape((N, M))
    mask = np.zeros(boundary2d.shape)
    for r in range(boundary2d.shape[1]):
        pts = np.where(boundary2d[:, r] == 1)
        if (len(pts[0]) > 0):
            mini = (min(min(pts)))
            maxi = max(max(pts))
            mask[mini:maxi, r] = 1

    distances2d = -ndimage.distance_transform_edt(
        mask) + ndimage.distance_transform_edt(1 - mask)
    distances2d = distances2d.flatten()

    condition_inside = distances2d <= 0
    condition_outside = (distances2d > 0) * (distances2d <= CUTOFF)

    del distances2d, mask, boundary2d
    gc.collect()

    x_out = np.array(coords[condition_outside, 0] / dx, dtype=int)
    y_out = np.array(coords[condition_outside, 1] / dy, dtype=int)

    x_in = np.array(coords[condition_inside, 0] / dx, dtype=int)
    y_in = np.array(coords[condition_inside, 1] / dy, dtype=int)

    x_center = np.mean(x_in)
    y_center = np.mean(y_in)

    u_x_in = deflection[condition_inside]
    u_x_out = deflection[condition_outside]

    n_in = len(x_in)
    n_out = len(x_out)

    spacing = 1

    G_in_in_xx, G_in_in_xy, G_out_in_xx, G_out_in_xy, G_in_in_yy, G_in_in_yx, G_out_in_yy, G_out_in_yx, Dx, Dy = gen_matrices(
        x_in, y_in, x_out, y_out, dx * spacing, dy * spacing, loworder=True)

    print("Size of the problem is " + str(n_in + n_out))
    """
    Setting up the problem
    ======================
    We compute the coefficient matrices for the linear problem
    """
    """
    Setting up the optimization problem
    ===================================

    Define norms
    """

    gamma = Parameter(sign="positive", value=1)

    sigma_xz = Variable(n_in)
    sigma_yz = Variable(n_in)
    # predicted_in = A_in_in*sigma_xz + D_in_in*sigma_yz # add higher order terms
    predicted_in_x = G_in_in_xx * sigma_xz + G_in_in_xy * sigma_yz
    predicted_out_x = G_out_in_xx * sigma_xz + G_out_in_xy * sigma_yz
    predicted_in_y = G_in_in_yx * sigma_xz + G_in_in_yy * sigma_yz
    predicted_out_y = G_out_in_yx * sigma_xz + G_out_in_yy * sigma_yz
    gamma_vals = np.logspace(-3, 2, N_SOLUTIONS)

    error = sum_squares(u_x_in - predicted_in_x) + sum_squares(u_x_out -
                                                               predicted_out_x)

    if REGULARIZATION == "tvtrace":
        regularity_penalty = tvnorm_trace_2d(sigma_xz, sigma_yz, Dx, Dy)
    elif REGULARIZATION == "tviso":
        regularity_penalty = norm(Dx * sigma_xz / dx, 1) + norm(
            Dy * sigma_xz / dy, 1) + norm(Dx * sigma_yz / dx, 1) + norm(
                Dy * sigma_yz / dy, 1)
    elif REGULARIZATION == "tv":
        regularity_penalty = tvnorm2d(sigma_xz, Dx, Dy) + tvnorm2d(
            sigma_yz, Dx, Dy)
    elif REGULARIZATION == 'l2_grad':
        regularity_penalty = sum_squares(
            Dx * sigma_xz + Dx * sigma_yz) + sum_squares(Dy * sigma_xz +
                                                         Dy * sigma_yz)
    elif REGULARIZATION == 'l1':
        regularity_penalty = norm(sigma_xz + sigma_yz, p=1)
    elif REGULARIZATION == 'l2':
        regularity_penalty = sum_squares(sigma_xz +
                                         sigma_yz) + sum_squares(sigma_xz +
                                                                 sigma_yz)
    elif REGULARIZATION == 'det':
        gamma_vals = np.logspace(-8, -5, N_SOLUTIONS)
        regularity_penalty = sum_entries(-log2(sigma_xz) - log2(sigma_yz))
    else:
        print("Invalid regularization choice")
        sys.exit(0)

    forceconstraints = [
        sum_entries(sigma_xz) == 0,
        sum_entries(sigma_yz) == 0
    ]  # add torque-free constraint here
    net_torque = sum_entries(
        mul_elemwise(x_in - x_center, sigma_yz) -
        mul_elemwise(y_in - y_center, sigma_xz))

    torqueconstraints = [net_torque == 0]

    constraints = forceconstraints + torqueconstraints

    objective = Minimize(error + gamma * regularity_penalty)

    prob = Problem(objective, constraints)

    sq_penalty = []
    l1_penalty = []
    sigma_xz_values = []
    sigma_yz_values = []

    with PdfPages(figure_outfile) as pdf:
        for val in gamma_vals:
            gamma.value = val
            try:
                if results.solver is not None and results.solver == "ecos":
                    prob.solve(verbose=True,
                               max_iters=50,
                               warm_start=True,
                               solver=cvxpy.ECOS,
                               feastol=1e-6,
                               reltol=1e-5,
                               abstol=1e-6)
                elif results.solver is not None and results.solver == "cvxopt":
                    prob.solve(verbose=True,
                               max_iters=50,
                               warm_start=True,
                               solver=cvxpy.CVXOPT,
                               feastol=1e-6,
                               reltol=1e-5,
                               abstol=1e-6)
                else:
                    prob.solve(verbose=True,
                               max_iters=50,
                               warm_start=True,
                               feastol=1e-6,
                               reltol=1e-5,
                               abstol=1e-6)

            except cvxpy.SolverError:
                continue

            sq_penalty.append(error.value)
            l1_penalty.append(regularity_penalty.value)
            sigma_xz_values.append(sigma_xz.value)
            sigma_yz_values.append(sigma_yz.value)

            force = np.zeros_like(coords)
            force[condition_inside, 0] = sigma_xz.value.reshape((n_in, ))
            force[condition_inside, 1] = sigma_yz.value.reshape((n_in, ))

            u_x = np.zeros(coords.shape[0])
            u_x[condition_inside] = predicted_in_x.value
            u_x[condition_outside] = predicted_out_x.value

            maxmagnitude = np.max(np.abs(force))

            plt.rc('text', usetex=True)
            plt.rc('font', family='serif')
            plt.figure(figsize=(10, 10))

            x_min = min(coords[boundary == 1, 0])
            x_max = max(coords[boundary == 1, 0])
            y_min = min(coords[boundary == 1, 1])
            y_max = max(coords[boundary == 1, 1])

            pdf.attach_note("$\gamma$: " + str(val))

            plt.suptitle("$\gamma$: " + str(val) + "\n" + "mismatch: " +
                         str(error.value) + " penalty: " +
                         str(regularity_penalty.value))

            plt.subplot(221)
            plt.xlim((x_min - 40, x_max + 40))
            plt.ylim((y_min - 40, y_max + 40))
            plt.pcolormesh(x_obs_positions,
                           y_obs_positions,
                           force[:, 0].reshape(
                               (len(x_obs_positions),
                                len(y_obs_positions))).transpose(),
                           cmap='seismic_r',
                           vmax=maxmagnitude * .75,
                           vmin=-maxmagnitude * .8)
            plt.title("$\sigma_{xz}$")
            plt.colorbar()

            plt.subplot(222)
            plt.xlim((x_min - 40, x_max + 40))
            plt.ylim((y_min - 40, y_max + 40))
            plt.pcolormesh(x_obs_positions,
                           y_obs_positions,
                           force[:, 1].reshape(
                               (len(x_obs_positions),
                                len(y_obs_positions))).transpose(),
                           cmap='seismic_r',
                           vmax=maxmagnitude * .75,
                           vmin=-maxmagnitude * .8)
            plt.title("$\sigma_{yz}$")
            plt.colorbar()

            plt.subplot(223)
            plt.xlim((x_min - 40, x_max + 40))
            plt.ylim((y_min - 40, y_max + 40))
            plt.pcolormesh(x_obs_positions,
                           y_obs_positions,
                           u_x.reshape((len(x_obs_positions),
                                        len(y_obs_positions))).transpose(),
                           cmap='seismic_r')
            plt.title("$\hat{u}_x$")
            plt.colorbar()

            plt.subplot(224)
            plt.xlim((x_min - 40, x_max + 40))
            plt.ylim((y_min - 40, y_max + 40))
            plt.pcolormesh(x_obs_positions,
                           y_obs_positions, (deflection - u_x).reshape(
                               (len(x_obs_positions),
                                len(y_obs_positions))).transpose(),
                           cmap='seismic_r')
            plt.title("$u_x-\hat{u}_x$")
            plt.colorbar()
            pdf.savefig()
            #plt.show()
            plt.close()

        plt.plot(sq_penalty, l1_penalty)
        plt.xlabel("Mismatch", fontsize=16)
        plt.ylabel("Regularity", fontsize=16)
        plt.title('Trade-Off Curve', fontsize=16)

        l_curve_distances = np.abs((l1_penalty[-1]-l1_penalty[0])*sq_penalty -  \
            (sq_penalty[-1]-sq_penalty[0])*l1_penalty+sq_penalty[-1]*l1_penalty[0]-l1_penalty[-1]*sq_penalty[0])

        # Choose the optimal lambda value

        pdf.savefig()
        plt.close()

    input("Press Enter to continue...")
예제 #13
0
        constraints += [umin <= u[:, k], u[:, k] <= umax]
    objective += quad_form(x[:, Np] - xref, QN)
    prob = Problem(Minimize(objective), constraints)

    # Simulate in closed loop
    # Simulate in closed loop
    len_sim = 15  # simulation length (s)
    nsim = int(len_sim / Ts)  # simulation length(timesteps)
    xsim = np.zeros((nsim, nx))
    usim = np.zeros((nsim, nu))
    tsim = np.arange(0, nsim) * Ts

    uminus1_val = uinit  # initial previous measured input is the input at time instant -1.
    time_start = time.time()
    for i in range(nsim):
        x_init.value = x0
        #uminus1.value = uminus1_val
        prob.solve(solver=OSQP, warm_start=True)
        uMPC = u[:, 0].value
        usim[i, :] = uMPC
        x0 = Ad.dot(x0) + Bd.dot(uMPC)
        xsim[i, :] = x0

        uminus1_val = uMPC  # or a measurement if the input is affected by noise
    time_sim = time.time() - time_start

    # In [1]
    import matplotlib.pyplot as plt
    fig, axes = plt.subplots(3, 1, figsize=(10, 10))
    axes[0].plot(tsim, xsim[:, 0], "k", label='p')
    axes[0].plot(tsim, xref[0] * np.ones(np.shape(tsim)), "r--", label="pref")