Skip to content

Commit 295de66

Browse files
committed
cache C problem in best of
1 parent d875f54 commit 295de66

5 files changed

Lines changed: 50 additions & 17 deletions

File tree

cvxpy/reductions/solvers/nlp_solvers/copt_nlpif.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,15 @@ def solve_via_data(self, data, warm_start: bool, verbose: bool, solver_opts, sol
121121
# COPT always uses exact Hessian (no quasi-Newton option currently)
122122
use_hessian = True
123123

124-
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
125-
verbose=verbose, use_hessian=use_hessian)
124+
if solver_cache is None:
125+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
126+
verbose=verbose, use_hessian=use_hessian)
127+
elif 'oracles' in solver_cache:
128+
oracles = solver_cache['oracles']
129+
else:
130+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
131+
verbose=verbose, use_hessian=use_hessian)
132+
solver_cache['oracles'] = oracles
126133

127134
class COPTNlpCallbackCVXPY(copt.NlpCallbackBase):
128135
def __init__(self, oracles, m):

cvxpy/reductions/solvers/nlp_solvers/ipopt_nlpif.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ def solve_via_data(self, data, warm_start: bool, verbose: bool, solver_opts, sol
110110
data : dict
111111
Data used by the solver.
112112
This consists of:
113-
- "oracles": An Oracles object that computes the objective and constraints
114113
- "x0": Initial guess for the primal variables
115114
- "lb": Lower bounds on the primal variables
116115
- "ub": Upper bounds on the primal variables
@@ -150,9 +149,16 @@ def solve_via_data(self, data, warm_start: bool, verbose: bool, solver_opts, sol
150149
hessian_approx = solver_opts.get('hessian_approximation', 'exact')
151150
use_hessian = (hessian_approx == 'exact')
152151

153-
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
154-
verbose=verbose, use_hessian=use_hessian)
155-
152+
if solver_cache is None:
153+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
154+
verbose=verbose, use_hessian=use_hessian)
155+
elif 'oracles' in solver_cache:
156+
oracles = solver_cache['oracles']
157+
else:
158+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
159+
verbose=verbose, use_hessian=use_hessian)
160+
solver_cache['oracles'] = oracles
161+
156162
nlp = cyipopt.Problem(
157163
n=len(data["x0"]),
158164
m=len(data["cl"]),

cvxpy/reductions/solvers/nlp_solvers/knitro_nlpif.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,15 @@ def solve_via_data(self, data, warm_start: bool, verbose: bool, solver_opts, sol
176176
hessopt = solver_opts.get('hessopt', 1) if solver_opts else 1
177177
use_hessian = (hessopt == 1)
178178

179-
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
180-
verbose=verbose, use_hessian=use_hessian)
179+
if solver_cache is None:
180+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
181+
verbose=verbose, use_hessian=use_hessian)
182+
elif 'oracles' in solver_cache:
183+
oracles = solver_cache['oracles']
184+
else:
185+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
186+
verbose=verbose, use_hessian=use_hessian)
187+
solver_cache['oracles'] = oracles
181188

182189
# Extract data from the data dictionary
183190
x0 = data["x0"]

cvxpy/reductions/solvers/nlp_solvers/uno_nlpif.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,15 @@ def solve_via_data(self, data, warm_start: bool, verbose: bool, solver_opts, sol
135135
# UNO always uses exact Hessian (no quasi-Newton option currently)
136136
use_hessian = True
137137

138-
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
139-
verbose=verbose, use_hessian=use_hessian)
138+
if solver_cache is None:
139+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
140+
verbose=verbose, use_hessian=use_hessian)
141+
elif 'oracles' in solver_cache:
142+
oracles = solver_cache['oracles']
143+
else:
144+
oracles = Oracles(bounds.new_problem, bounds.x0, len(bounds.cl),
145+
verbose=verbose, use_hessian=use_hessian)
146+
solver_cache['oracles'] = oracles
140147

141148
# Extract data from the data dictionary
142149
x0 = data["x0"]

cvxpy/reductions/solvers/nlp_solving_chain.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,30 +175,35 @@ def solve_nlp(problem, solver, warm_start, verbose, **kwargs):
175175
The optimal problem value.
176176
"""
177177
nlp_chain, kwargs = _build_nlp_chain(problem, solver, kwargs)
178-
best_of = kwargs.pop("best_of", 1)
179-
180-
if not isinstance(best_of, int) or best_of < 1:
181-
raise ValueError("best_of must be a positive integer.")
182-
178+
183179
# Standard single solve
184-
if best_of == 1:
180+
if "best_of" not in kwargs:
185181
_set_nlp_initial_point(problem)
186182
canon_problem, inverse_data = nlp_chain.apply(problem=problem)
187183
solution = nlp_chain.solver.solve_via_data(canon_problem, warm_start,
188184
verbose, solver_opts=kwargs)
189185
problem.unpack_results(solution, nlp_chain, inverse_data)
190186
return problem.value
187+
188+
best_of = kwargs.pop("best_of")
189+
if not isinstance(best_of, int) or best_of < 1:
190+
raise ValueError("best_of must be a positive integer.")
191191

192192
# Best-of-N solve
193193
best_obj, best_solution = float("inf"), None
194194
all_objs = np.zeros(shape=(best_of,))
195195
user_initials = {}
196196

197+
# inside solve_via_data we cache the construction of the C problem
198+
# (which includes the construction of the oracles)
199+
solver_cache = {}
200+
197201
for run in range(best_of):
198202
_set_random_nlp_initial_point(problem, run, user_initials)
199203
canon_problem, inverse_data = nlp_chain.apply(problem=problem)
200204
solution = nlp_chain.solver.solve_via_data(canon_problem, warm_start,
201-
verbose, solver_opts=kwargs)
205+
verbose, solver_opts=kwargs,
206+
solver_cache=solver_cache)
202207

203208
# Unpack to get the objective value in the original problem space
204209
problem.unpack_results(solution, nlp_chain, inverse_data)
@@ -212,6 +217,7 @@ def solve_nlp(problem, solver, warm_start, verbose, **kwargs):
212217
if verbose:
213218
print("Run %d/%d: obj = %.6e | best so far = %.6e"
214219
% (run + 1, best_of, obj_value, best_obj))
220+
print("-" * 60)
215221

216222
# Unpack best solution
217223
if type(problem.objective) == Maximize:

0 commit comments

Comments
 (0)