|
20 | 20 | from cvxpy.reductions.cvx_attr2constr import CvxAttr2Constr |
21 | 21 | from cvxpy.reductions.dnlp2smooth.dnlp2smooth import Dnlp2Smooth |
22 | 22 | from cvxpy.reductions.flip_objective import FlipObjective |
23 | | -from cvxpy.reductions.solvers.defines import INSTALLED_SOLVERS, SOLVER_MAP_NLP |
| 23 | +from cvxpy.reductions.solvers.defines import INSTALLED_SOLVERS, NLP_SOLVER_VARIANTS, SOLVER_MAP_NLP |
24 | 24 | from cvxpy.reductions.solvers.solving_chain import SolvingChain |
25 | 25 |
|
26 | | -# Solver variants: maps variant name → (base solver name, extra kwargs). |
27 | | -NLP_SOLVER_VARIANTS = { |
28 | | - "knitro_ipm": ("KNITRO", {"algorithm": 1}), |
29 | | - "knitro_sqp": ("KNITRO", {"algorithm": 4}), |
30 | | - "knitro_alm": ("KNITRO", {"algorithm": 6}), |
31 | | - "uno_ipm": ("UNO", {"preset": "ipopt", "linear_solver": "MUMPS"}), |
32 | | - "uno_sqp": ("UNO", {"preset": "filtersqp"}), |
33 | | -} |
34 | | - |
35 | 26 |
|
36 | 27 | def _build_nlp_chain(problem, solver, kwargs): |
37 | 28 | """Build the NLP reduction chain and return (SolvingChain, kwargs). |
38 | 29 |
|
39 | 30 | Solver selection may mutate kwargs (e.g., Knitro algorithm, Uno preset). |
40 | 31 | """ |
41 | | - if type(problem.objective) == Maximize: |
42 | | - reductions = [FlipObjective()] |
43 | | - else: |
44 | | - reductions = [] |
45 | | - reductions = reductions + [CvxAttr2Constr(reduce_bounds=False), Dnlp2Smooth()] |
46 | | - |
| 32 | + # Resolve the solver instance. |
47 | 33 | if solver is None: |
48 | 34 | # Pick first installed NLP solver in preference order. |
49 | 35 | for name, inst in SOLVER_MAP_NLP.items(): |
50 | 36 | if name in INSTALLED_SOLVERS: |
51 | | - reductions.append(inst) |
| 37 | + solver_instance = inst |
52 | 38 | break |
53 | 39 | else: |
54 | 40 | raise error.SolverError( |
55 | 41 | "No NLP solver is installed. Install one of: %s" |
56 | 42 | % ", ".join(SOLVER_MAP_NLP) |
57 | 43 | ) |
58 | 44 | elif solver in SOLVER_MAP_NLP: |
59 | | - reductions.append(SOLVER_MAP_NLP[solver]) |
| 45 | + solver_instance = SOLVER_MAP_NLP[solver] |
60 | 46 | elif solver.lower() in NLP_SOLVER_VARIANTS: |
61 | 47 | base_name, variant_kwargs = NLP_SOLVER_VARIANTS[solver.lower()] |
62 | 48 | kwargs.update(variant_kwargs) |
63 | | - reductions.append(SOLVER_MAP_NLP[base_name]) |
| 49 | + solver_instance = SOLVER_MAP_NLP[base_name] |
64 | 50 | else: |
65 | 51 | raise error.SolverError( |
66 | 52 | "Solver %s is not supported for NLP problems." % solver |
67 | 53 | ) |
68 | 54 |
|
| 55 | + # Build the reduction chain. |
| 56 | + if type(problem.objective) == Maximize: |
| 57 | + reductions = [FlipObjective()] |
| 58 | + else: |
| 59 | + reductions = [] |
| 60 | + reductions += [ |
| 61 | + CvxAttr2Constr(reduce_bounds=not solver_instance.BOUNDED_VARIABLES), |
| 62 | + Dnlp2Smooth(), |
| 63 | + solver_instance, |
| 64 | + ] |
| 65 | + |
69 | 66 | return SolvingChain(reductions=reductions), kwargs |
70 | 67 |
|
71 | 68 |
|
|
0 commit comments