AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
lp_solver.h
1#ifndef LP_LP_SOLVER_H
2#define LP_LP_SOLVER_H
3
4#include "downward/lp/solver_interface.h"
5
6#include "downward/algorithms/named_vector.h"
7
8#include <iostream>
9#include <memory>
10#include <string_view>
11#include <vector>
12
13namespace lp {
14enum class LPSolverType { CPLEX, SOPLEX };
15
16enum class LPObjectiveSense { MAXIMIZE, MINIMIZE };
17
18class LinearProgram;
19
20class LPConstraint {
21 std::vector<int> variables;
22 std::vector<double> coefficients;
23 double lower_bound;
24 double upper_bound;
25
26public:
27 LPConstraint(double lower_bound, double upper_bound);
28
29 const std::vector<int>& get_variables() const { return variables; }
30 const std::vector<double>& get_coefficients() const { return coefficients; }
31
32 double get_lower_bound() const { return lower_bound; }
33 void set_lower_bound(double lb) { lower_bound = lb; }
34 double get_upper_bound() const { return upper_bound; }
35 void set_upper_bound(double ub) { upper_bound = ub; }
36
37 void clear();
38 bool empty() const;
39 // Coefficients must be added without duplicate indices.
40 void insert(int index, double coefficient);
41 double remove(int index);
42
43 std::ostream&
44 dump(std::ostream& stream, const LinearProgram* program = nullptr) const;
45};
46
47struct LPVariable {
48 double lower_bound;
49 double upper_bound;
50 double objective_coefficient;
51 bool is_integer;
52
53 LPVariable(
54 double lower_bound,
55 double upper_bound,
56 double objective_coefficient,
57 bool is_integer = false);
58};
59
60class LinearProgram {
61 LPObjectiveSense sense;
62 std::string objective_name;
63
64 named_vector::NamedVector<LPVariable> variables;
65 named_vector::NamedVector<LPConstraint> constraints;
66 double infinity;
67
68public:
69 // objective_name is the name of the objective function used when writing
70 // the lp to a file.
71 LinearProgram(
72 LPObjectiveSense sense,
73 named_vector::NamedVector<LPVariable>&& variables,
74 named_vector::NamedVector<LPConstraint>&& constraints,
75 double infinity)
76 : sense(sense)
77 , variables(std::move(variables))
78 , constraints(std::move(constraints))
79 , infinity(infinity)
80 {
81 }
82
83 /*
84 Variables and constraints can be given a custom name for debugging
85 purposes. This has an impact on performance and should not be used in
86 production code.
87 */
88 named_vector::NamedVector<LPVariable>& get_variables();
89 named_vector::NamedVector<LPConstraint>& get_constraints();
90 const named_vector::NamedVector<LPVariable>& get_variables() const;
91 const named_vector::NamedVector<LPConstraint>& get_constraints() const;
92 double get_infinity() const;
93 LPObjectiveSense get_sense() const;
94 void set_objective_name(const std::string& name);
95 const std::string& get_objective_name() const;
96};
97
98class LPSolver {
99 std::unique_ptr<SolverInterface> pimpl;
100
101public:
102 explicit LPSolver(LPSolverType solver_type);
103
104 void load_problem(const LinearProgram& lp);
105 void add_temporary_constraints(
106 const named_vector::NamedVector<LPConstraint>& constraints);
107 void clear_temporary_constraints();
108 double get_infinity() const;
109
110 void set_objective_coefficients(const std::vector<double>& coefficients);
111 void set_objective_coefficient(int index, double coefficient);
112 void set_constraint_lower_bound(int index, double bound);
113 void set_constraint_upper_bound(int index, double bound);
114 void set_variable_lower_bound(int index, double bound);
115 void set_variable_upper_bound(int index, double bound);
116
117 void set_mip_gap(double gap);
118
119 void solve();
120 void write_lp(const std::string& filename) const;
121 void print_failure_analysis() const;
122 bool is_infeasible() const;
123 bool is_unbounded() const;
124
125 /*
126 Return true if the solving the LP showed that it is bounded feasible and
127 the discovered solution is guaranteed to be optimal. We test for
128 optimality explicitly because solving the LP sometimes finds suboptimal
129 solutions due to numerical difficulties.
130 The LP has to be solved with a call to solve() before calling this method.
131 */
132 bool has_optimal_solution() const;
133
134 /*
135 Return the objective value found after solving an LP.
136 The LP has to be solved with a call to solve() and has to have an optimal
137 solution before calling this method.
138 */
139 double get_objective_value() const;
140
141 /*
142 Return the solution found after solving an LP as a vector with one entry
143 per variable.
144 The LP has to be solved with a call to solve() and has to have an optimal
145 solution before calling this method.
146 */
147 std::vector<double> extract_solution() const;
148
149 int get_num_variables() const;
150 int get_num_constraints() const;
151 int has_temporary_constraints() const;
152 void print_statistics() const;
153
158 std::vector<double> extract_dual_solution() const;
159
160 void add_variable(
161 const LPVariable& var,
162 const std::vector<int>& constraint_ids,
163 const std::vector<double>& coefficients,
164 std::string_view name = "");
165
166 void add_constraint(const LPConstraint& constraint, std::string_view = "");
167};
168} // namespace lp
169
170#endif
STL namespace.