-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark_IPOPT.py
More file actions
196 lines (157 loc) · 5.8 KB
/
Copy pathbenchmark_IPOPT.py
File metadata and controls
196 lines (157 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import casadi as cs
import numpy as np
import utils.initialization as initialization
import utils.create_nlp as create_nlp
import Tkinter_plots.nlp_callback as cb
from utils.get_problem import get_problem, get_oed_problem
import timeit
import os
import argparse
parser = argparse.ArgumentParser(
description="Defines the problem name and algorithmic settings."
)
parser.add_argument('-n', "--problem_name", default="Bioreactor",
help="Name of the problem to be solved.")
parser.add_argument('-hess', "--exact_hessian", default="n",
help="Indicates whether to use the exact Hessian (y/n).")
parser.add_argument('-cond', "--auto_condense", default="n",
help="Indicates whether to use the automatic condensing algorithm (y/n).")
# parse the input settings
args = parser.parse_args()
problem_name = args.problem_name
exact_hessian = ("y" == args.exact_hessian)
auto_condense = ("y" == args.auto_condense)
# file where the results will be saved
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, "logs/ipopt_lists.log")
# get the current mode (used for some algorithms)
if problem_name[-3:] == "OED":
mode = "OED"
else:
mode = "default"
# general settings
lifting_type = "all"
init_type = "auto"
num_lifting_points = 64
num_control_points = 64
max_iter = 200
num_reps = 5
# file where the results will be saved
log_name = "logs/default_multiple_shooting/" + "IPOPT_"
log_name += exact_hessian * "exact"
log_name += (not exact_hessian) * "quasi_newton"
iter_file = os.path.join(dirname, log_name + "_iters.log")
time_file = os.path.join(dirname, log_name + "_times.log")
if mode == "OED":
curr_problem = get_oed_problem(problem_name)
else:
curr_problem = get_problem(problem_name)
curr_init_type = init_type
ode = curr_problem.get_ode()
num_controls = num_control_points
num_lifts = num_lifting_points
max_t = curr_problem.get_grid_details()
# log the required number of iterations
with open(iter_file, 'a') as f:
output = "\n" + problem_name + ", "
f.write(output)
# log the required real time
with open(time_file, 'a') as f:
output = "\n" + problem_name + ", "
f.write(output)
# log average time and iterations for current lifting
curr_time_log = []
curr_iter_log = []
for i in range(num_reps):
if sum(curr_iter_log) == cs.inf:
break
# create grids
control_points = [i * max_t / num_controls for i in range(num_controls)]
time_points = [i * max_t / num_lifts for i in range(num_lifts + 1)]
lifting_points = list(np.zeros(len(time_points)))
grid = {}
grid["time"] = time_points
grid["control"] = control_points
# initialize starting values
init_vals = curr_problem.get_init()
s_dim = init_vals["s_dim"]
q_dim = init_vals["q_dim"]
q_start = init_vals["q_start"]
q_init = cs.DM(q_start * num_controls)
if problem_name != "Quadrotor":
print("Add random noise to control")
# add random noise to controls for default mode
np.random.seed(i)
noise = np.random.rand(q_init.shape[0]) - 0.5
q_init += 1.e-2 * noise
start = init_vals["s_start"]
init_vals["sol"] = cs.vertcat(q_init, start)
init_vals["controls"] = q_init
init_vals["s_end"] = start
# initialize intermediate states
s_init = initialization.initialize(init_vals, grid, ode, curr_init_type)
init_vals["s_init"] = s_init
curr_lifting_type = lifting_type
match curr_lifting_type:
case "all":
lifting_points = [1 for i in range(num_lifts + 1)]
case _:
lifting_points = [0 for i in range(num_lifts + 1)]
# Use the inital values as candidates for the lifting points
s_init = initialization.select_states(s_init, s_dim, lifting_points)
grid["lift"] = lifting_points
init = cs.vertcat(q_init, s_init)
input_size = init.shape[0]
# Input for Newton's method
default_init = {}
default_init["sol"] = init
default_init["s_dim"] = s_dim
default_init["q_dim"] = q_dim
w, lbw, ubw, g, lbg, ubg, J = create_nlp.create_nlp(curr_problem, grid)
plot_details = {}
plot_details["grid"] = grid
plot_details["ode"] = ode
plot_details["problem"] = curr_problem
plot_details["init"] = default_init
plot_details["log_results"] = False
plot_details["time_scale"] = curr_problem.time_scale_ind
plot_details["plot_iter"] = False
plot_details["condense"] = auto_condense
plot_details['lbg'] = lbg
plot_details['ubg'] = ubg
plot_details['lbw'] = lbw
plot_details['ubw'] = ubw
mycallback = cb.MyCallback('mycallback', cs.vertcat(*w).shape[0],
cs.vertcat(*g).shape[0], 0, plot_details)
prob = {'f': J, 'x': cs.vertcat(*w), 'g': cs.vertcat(*g)}
opts = {}
opts['ipopt.print_level'] = 5
opts['iteration_callback'] = mycallback
if not exact_hessian:
print("Using approximate Hessian!")
opts['ipopt.hessian_approximation'] = "limited-memory"
opts["ipopt.tol"] = 1.e-6
opts['ipopt.max_iter'] = 200
solver = cs.nlpsol('solver', 'ipopt', prob, opts)
start_time = timeit.default_timer()
sol = solver(x0=init, lbx=lbw, ubx=ubw, lbg=lbg, ubg=ubg)
diff_time = timeit.default_timer() - start_time
stats = solver.stats()
success = stats["success"]
condense_success = mycallback.condense_success
if success or condense_success:
num_iter = mycallback.iter
else:
num_iter = float(cs.inf)
curr_time_log += [diff_time]
curr_iter_log += [num_iter]
avg_time = sum(curr_time_log) / num_reps
avg_iters = sum(curr_iter_log) / num_reps
# log the required number of iterations
with open(iter_file, 'a') as f:
output = str(avg_iters) + ", "
f.write(output)
# log the required real time
with open(time_file, 'a') as f:
output = str(avg_time) + ", "
f.write(output)