107 template <
typename T>
115 {
return lower_bound == -std::numeric_limits<T>::infinity(); }
118 {
return upper_bound == std::numeric_limits<T>::infinity(); }
225 template <
typename T>
257 for (
int i = 0; i < M; ++i)
258 if (
m->read(0, i) < -
eps)
264 T minimum = std::numeric_limits<T>::max();
266 for (
int i = 0; i < M; ++i)
268 const T & c =
m->read(0, i);
296 const T den =
m->read(i, p);
347 const size_t cols = M + 1;
358 for (
size_t j = 0; j <= M; ++j)
362 for (
size_t j = 0; j <= M; ++j)
366 for (
size_t i = 0; i <=
num_rest; ++i)
370 for (
size_t i = 0; i <=
num_rest; ++i)
379 for (
size_t j = 0; j <= M; ++j)
381 m->write(i, j,
T{0});
395 if (std::abs(
m->read(0, j)) >
eps)
402 for (
size_t i = 1; i <=
num_rest; ++i)
404 const T & value =
m->read(i, j);
405 if (std::abs(value) <
eps)
408 if (std::abs(value -
T{1}) <
eps)
421 std::unique_ptr<DynMatrix<T>>
m;
448 <<
"Variable index " << i <<
" out of range [0, " << (
num_var - 1) <<
"]";
455 <<
"Restriction index " << i <<
" out of range [0, " << (
num_rest - 1) <<
"]";
465 for (
size_t i = 0; i <=
num_var; ++i)
488 m = std::unique_ptr<DynMatrix<T>>(
503 for (
size_t i = 0; i <
num_var; ++i)
527 T *
rest = it.get_curr();
531 for (
size_t j = 0; j <
num_var; ++j)
559 for (
size_t i = 0; i <
num_rest; ++i)
613 <<
"Number of variables must be greater than zero";
616 for (
size_t i = 0; i < n; ++i)
742 for (
size_t i = 0; i <
num_var; ++i)
752 for (
size_t i = 0; i <
num_var; ++i)
777 if (
coefs ==
nullptr)
780 for (
size_t i = 0; i <=
num_var; ++i)
823 for (
size_t i = 0; i <=
num_var; ++i)
843 return it.get_curr();
924 <<
"Cannot prepare linear program without constraints";
951 ah_logic_error_if(
m ==
nullptr) <<
"prepare_linear_program() must be called before solve()";
954 auto start_time = std::chrono::high_resolution_clock::now();
956 T prev_obj = std::numeric_limits<T>::lowest();
958 for (
int i, j;
true;)
965 auto end_time = std::chrono::high_resolution_clock::now();
1012 for (
size_t j = 0; j <
num_var; ++j)
1042 for (
size_t i = 0; i <
num_var; ++i)
1060 it.next_ne(),
type_it.next_ne())
1062 const T *
rest = it.get_curr();
1065 for (
size_t j = 0; j <
num_var; ++j)
1094 for (
size_t i = 0; i <=
num_rest; ++i)
1097 std::cout <<
float_f(
m->read(i, j), 2) <<
" ";
1099 std::cout << std::endl;
1111 const int p = -1,
const int q = -1)
const
1113 std::ofstream
out(name, std::ios::out);
1117 out <<
"$\\left(\\begin{array}{c";
1118 for (
size_t i = 0; i < cols; ++i)
1120 out <<
"}" << std::endl;
1122 for (
size_t i = 0; i <=
num_rest; ++i)
1124 for (
size_t j = 0; j <= cols; ++j)
1126 if (
static_cast<int>(i) == p
and static_cast<int>(j) == q)
1127 out <<
"\\circled{" <<
float_f(
m->read(i, j), d) <<
"}" <<
" ";
1139 out <<
"\\end{array}\\right)$" << std::endl;
1151 std::ofstream
out(name, std::ios::out);
1152 out <<
"\\begin{equation*}" << std::endl
1156 for (
size_t i = 0; i <
num_var; ++i)
1170 <<
"\\end{equation*}" << std::endl
1171 <<
"Subject to:" << std::endl
1172 <<
"\\begin{eqnarray*}" << std::endl;
1176 const T *
rest = it.get_curr();
1179 for (
size_t i = 0; i <
num_var; ++i)
1195 if (
not it.is_in_last())
1200 out <<
"\\end{eqnarray*}" << std::endl;
1213 const std::string base = name ? name :
"simplex";
1216 for (
int i, j,
k = 1;
true; ++
k)
1220 std::string str = base +
"-" + std::to_string(
k) +
".tex";
1230 latex_matrix(base +
"-" + std::to_string(
k) +
"-after.tex", 2, i, j);
1306 result.
lower_bound = -std::numeric_limits<T>::infinity();
1307 result.
upper_bound = std::numeric_limits<T>::infinity();
1310 bool is_basic =
false;
1312 for (
size_t i = 0; i <
num_rest; ++i)
1385 result.
lower_bound = -std::numeric_limits<T>::infinity();
1386 result.
upper_bound = std::numeric_limits<T>::infinity();
1478 for (
size_t i = 0; i <
num_rest; ++i)
1494 for (
size_t i = 0; i <
num_rest; ++i)
1509 for (
size_t i = 0; i <
num_var; ++i)
1528 <<
"dual_solve() requires a previously solved problem";
1532 auto start_time = std::chrono::high_resolution_clock::now();
1545 for (
size_t i = 1; i <=
num_rest; ++i)
1558 auto end_time = std::chrono::high_resolution_clock::now();
1609 <<
"Cannot update RHS without a solved problem";
1643 std::cout <<
"=== Simplex Statistics ===\n"
1658 <<
"Must solve before printing sensitivity analysis";
1660 std::cout <<
"=== Sensitivity Analysis ===\n\n";
1662 std::cout <<
"Objective Coefficients:\n";
1663 for (
size_t i = 0; i <
num_var; ++i)
1666 std::cout <<
" x_" << i <<
": current=" <<
range.current_value
1667 <<
", range=[" <<
range.lower_bound <<
", "
1668 <<
range.upper_bound <<
"]\n";
1671 std::cout <<
"\nRHS Values (Shadow Prices):\n";
1672 for (
size_t i = 0; i <
num_rest; ++i)
1676 std::cout <<
" Constraint " << i <<
": current=" <<
range.current_value
1677 <<
", range=[" <<
range.lower_bound <<
", " <<
range.upper_bound
1678 <<
"], shadow price=" <<
sp <<
"\n";
1681 std::cout <<
"\nReduced Costs:\n";
1682 for (
size_t i = 0; i <
num_var; ++i)
1686 std::cout <<
" x_" << i <<
": " <<
rc
1687 << (basic ?
" (basic)" :
" (non-basic)") <<
"\n";
1742 template <
typename T>
1754 std::vector<std::vector<T>>
A;
1776 mutable std::vector<T>
pi;
1777 mutable std::vector<T>
d;
1793 void ftran(
const std::vector<T>& a, std::vector<T>&
y)
const
1796 for (
size_t i = 0; i <
m; ++i)
1799 for (
size_t j = 0; j <
m; ++j)
1812 for (
size_t j = 0; j <
m; ++j)
1815 for (
size_t i = 0; i <
m; ++i)
1826 T rc = (j <
n) ?
c[j] :
T{0};
1828 for (
size_t i = 0; i <
m; ++i)
1830 T a_ij = (j <
n) ?
A[i][j] : ((j -
n == i) ?
T{1} :
T{0});
1844 for (
size_t i = 0; i <
m; ++i)
1851 for (
size_t i = 0; i <
m; ++i)
1861 std::vector<T>
c_B(
m);
1862 for (
size_t i = 0; i <
m; ++i)
1893 std::vector<T>
a_j(
m);
1900 theta = std::numeric_limits<T>::max();
1903 for (
size_t i = 0; i <
m; ++i)
1911 leaving =
static_cast<int>(i);
1931 std::vector<T> eta(
m);
1932 for (
size_t i = 0; i <
m; ++i)
1942 std::vector<std::vector<T>>
new_B_inv(
m, std::vector<T>(
m));
1944 for (
size_t i = 0; i <
m; ++i)
1946 for (
size_t j = 0; j <
m; ++j)
1970 std::vector<std::vector<T>>
B(
m, std::vector<T>(
m,
T{0}));
1972 for (
size_t i = 0; i <
m; ++i)
1975 if (var <
static_cast<int>(
n))
1984 B[var -
n][i] =
T{1};
1990 for (
size_t i = 0; i <
m; ++i)
1993 for (
size_t col = 0; col <
m; ++col)
2016 for (
size_t j = 0; j <
m; ++j)
2027 T factor =
B[
row][col];
2028 for (
size_t j = 0; j <
m; ++j)
2030 B[
row][j] -= factor *
B[col][j];
2063 <<
"Number of variables and constraints must be > 0";
2083 for (
size_t j = 0; j <
n; ++j)
2096 <<
"Constraint or variable index out of range";
2120 for (
size_t j = 0; j <
n; ++j)
2146 auto start_time = std::chrono::high_resolution_clock::now();
2149 for (
size_t i = 0; i <
m; ++i)
2151 basic[i] =
static_cast<int>(
n + i);
2158 for (
size_t j = 0; j <
n; ++j)
2159 nonbasic.push_back(
static_cast<int>(j));
2163 for (
size_t i = 0; i <
m; ++i)
2195 for (
size_t i = 0; i <
m; ++i)
2196 x_B[i] -= theta *
d[i];
2221 for (
size_t i = 0; i <
m; ++i)
2224 auto end_time = std::chrono::high_resolution_clock::now();
2249 for (
size_t j = 0; j <
n; ++j)
2272 for (
size_t i = 0; i <
m; ++i)
2275 for (
size_t j = 0; j <
n; ++j)
2286 std::cout <<
"=== Revised Simplex Statistics ===\n"
2287 <<
"Variables: " <<
n <<
", Constraints: " <<
m <<
"\n"
2291 <<
"Eta-matrices: " <<
eta_file.size() <<
"\n"
2292 <<
"Refactorizations: "
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_logic_error_if(C)
Throws std::logic_error if condition holds.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Dynamic doubly linked list with O(1) size and bidirectional access.
T & append(const T &item)
Append a copied item at the end of the list.
Revised Simplex algorithm for linear programming.
void set_refactorization_frequency(size_t freq)
Sets refactorization frequency.
void set_objective(const T *coefs)
Sets all objective coefficients.
void set_objective(size_t j, T coef)
Sets objective coefficient.
size_t get_num_vars() const noexcept
Gets number of variables.
std::vector< T > solution
std::vector< int > nonbasic
void print_stats() const
Prints statistics to stdout.
int select_entering_variable()
std::vector< bool > is_basic
size_t get_num_constraints() const noexcept
Gets number of constraints.
State
Solution states for the linear program.
const SimplexStats & get_stats() const noexcept
Gets execution statistics.
void update_basis_inverse(int leaving_row, const std::vector< T > &d_col)
size_t refactor_frequency
int select_leaving_variable(int entering, T &theta)
std::vector< std::vector< T > > A
void get_column(size_t j, std::vector< T > &col) const
void set_constraint_row(size_t i, const T *coefs, T rhs)
Adds a complete constraint.
std::vector< EtaMatrix > eta_file
State get_state() const noexcept
Gets current state.
T get_solution(size_t j) const
Gets solution value for variable j.
void ftran(const std::vector< T > &a, std::vector< T > &y) const
void set_constraint(size_t i, size_t j, T coef)
Sets constraint coefficient.
std::vector< std::vector< T > > B_inv_explicit
T objective_value() const
Computes objective function value.
void btran(const std::vector< T > &c_B, std::vector< T > &pi_out) const
State solve()
Solves the linear program.
T compute_reduced_cost(size_t j) const
void set_rhs(size_t i, T rhs)
Sets RHS value for a constraint.
bool verify_solution() const
Verifies solution satisfies all constraints.
RevisedSimplex(size_t num_vars, size_t num_constraints)
Constructs a Revised Simplex solver.
Linear program solver using the Simplex method.
void set_optimization_type(OptimizationType type) noexcept
Sets the optimization type.
SensitivityRange< T > rhs_sensitivity(size_t rest_idx) const
Computes sensitivity range for a RHS value.
void print_matrix() const
Prints the simplex tableau to stdout.
State
Solution states for the linear program.
OptimizationType get_optimization_type() const noexcept
Gets the current optimization type.
const SimplexStats & get_stats() const noexcept
Gets execution statistics.
T & get_restriction_coef(const size_t rest_num, size_t idx)
Gets a specific coefficient from a constraint.
void set_minimize() noexcept
Sets minimization mode.
std::vector< int > basic_vars
OptimizationType opt_type
std::vector< T > pivot_col_buffer
T objetive_value() const noexcept
Computes and returns the objective function value.
Simplex(Simplex &&)=default
std::vector< T > get_all_reduced_costs() const
Gets all reduced costs as a vector.
void print_sensitivity_analysis() const
Prints sensitivity analysis to stdout.
std::vector< T > pivot_row_buffer
T * get_restriction(const size_t rest_num)
Gets a pointer to a constraint array.
T * get_objetive_function() noexcept
Gets the objective function coefficients array.
void to_pivot(size_t p, size_t q)
bool verify_solution() const
Verifies that the solution satisfies all constraints.
DynDlist< ConstraintType > rest_types
void verify_rest_index(const size_t i) const
Simplex & operator=(const Simplex &)=delete
T find_value(const size_t j) const noexcept
SensitivityRange< T > objective_sensitivity(size_t var_idx) const
Computes sensitivity range for an objective coefficient.
void put_restriction_coef(const size_t rest_num, const size_t idx, const T &coef)
Sets a specific coefficient in a constraint.
std::unique_ptr< DynMatrix< T > > m
size_t get_pivot_count() const noexcept
Gets the number of pivot operations.
int compute_pivot_row(int p) const noexcept
T * put_restriction(const T *coefs=nullptr, ConstraintType type=ConstraintType::LE)
Adds a constraint to the linear program.
void prepare_linear_program()
Prepares the linear program for solving.
void latex_linear_program(const std::string &name) const
Exports the linear program to a LaTeX file.
T shadow_price(size_t rest_idx) const
Gets the shadow price (dual value) for a constraint.
State update_rhs_and_reoptimize(size_t rest_idx, T new_rhs)
Updates RHS value and re-optimizes using dual simplex.
bool is_basic_variable(size_t var_idx) const
Checks if a variable is basic in the optimal solution.
void print_stats() const
Prints a summary of statistics to stdout.
Simplex & operator=(Simplex &&)=default
void set_maximize() noexcept
Sets maximization mode.
size_t get_iteration_count() const noexcept
Gets the number of iterations performed.
size_t get_num_restrictions() const noexcept
Gets the number of constraints.
const T & get_solution(size_t i) const noexcept
Gets the solution value for a specific variable.
Simplex(const Simplex &)=delete
DynDlist< T * > rest_list
void latex_matrix(const std::string &name, const int d=2, const int p=-1, const int q=-1) const
Exports the simplex tableau to a LaTeX file.
void put_objetive_function_coef(size_t i, const T &coef)
Sets a coefficient in the objective function.
size_t count_artificial_vars() const noexcept
void set_pivot_rule(PivotRule rule) noexcept
Sets the pivot selection rule.
void verify_var_index(const size_t i) const
T * put_ge_restriction(const T *coefs)
Adds a ≥ constraint.
T reduced_cost(size_t var_idx) const
Gets the reduced cost for a variable.
void load_solution() noexcept
Loads the solution values into the solution array.
const T * get_objetive_function() const noexcept
Gets the objective function coefficients array (const).
int compute_pivot_col() const noexcept
State select_pivot(int &p, int &q) noexcept
State dual_solve()
Performs dual simplex iteration.
void set_epsilon(T epsilon) noexcept
Sets the floating-point comparison tolerance.
std::unique_ptr< T[]> solution
std::unique_ptr< T[]> objetive
void put_objetive_function(const DynArray< T > &coefs)
Sets all objective function coefficients from a DynArray.
size_t get_num_vars() const noexcept
Gets the number of decision variables.
T * create_restriction(ConstraintType type=ConstraintType::LE)
State get_state() const noexcept
Gets the current state of the solver.
size_t get_degenerate_pivot_count() const noexcept
Gets the number of degenerate pivots.
T * put_restriction(const DynArray< T > &coefs, ConstraintType type=ConstraintType::LE)
Adds a constraint from a DynArray.
PivotRule
Pivot selection rule.
T * put_eq_restriction(const T *coefs)
Adds an = constraint.
State latex_solve(const char *name=nullptr)
Solves with LaTeX output at each iteration.
void enable_bland_rule() noexcept
Enables Bland's anti-cycling rule.
Simplex(const size_t n, OptimizationType type=OptimizationType::Maximize)
Constructs a Simplex solver for n variables.
State solve()
Solves the linear program.
void put_objetive_function(const T coefs[])
Sets all objective function coefficients from a C array.
std::vector< T > get_all_shadow_prices() const
Gets all shadow prices as a vector.
const T & get_objetive_function_coef(size_t i) const
Gets a coefficient from the objective function.
double get_elapsed_time_ms() const noexcept
Gets the elapsed solving time.
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Main namespace for Aleph-w library functions.
std::decay_t< typename HeadC::Item_Type > T
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
ConstraintType
Constraint type for linear programming.
OptimizationType
Optimization direction for linear programming.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Sensitivity analysis result for a coefficient.
T lower_bound
Minimum value before basis change.
T upper_bound
Maximum value before basis change.
bool is_unbounded_below() const noexcept
T current_value
Current coefficient value.
bool is_unbounded_above() const noexcept
Execution statistics for the Simplex algorithm.
bool bland_rule_used
Whether Bland's rule was activated.
double elapsed_ms
Elapsed time in milliseconds.
size_t iterations
Total simplex iterations.
size_t pivots
Total pivot operations.
size_t degenerate_pivots
Pivots with zero improvement.
Dynamic doubly linked list implementation.
Dynamic matrix with lazy allocation.