From 30bf38e938deabfe800e6d504ca437aa0fe1b514 Mon Sep 17 00:00:00 2001 From: maxguy2001 Date: Mon, 13 Mar 2023 13:02:46 +0000 Subject: [PATCH 1/2] dimendionality issues --- lib/core/consts.hpp | 13 +- lib/solvers/CMakeLists.txt | 2 +- .../CMakeLists.txt | 2 +- .../{dual_simplex => dual_bland}/main.cpp | 0 .../{dual_simplex => dual_bland}/main.hpp | 0 lib/utils/dual_reformatter.cpp | 219 ++++++++++++++++++ lib/utils/dual_reformatter.hpp | 27 +++ src/CMakeLists.txt | 2 +- 8 files changed, 258 insertions(+), 7 deletions(-) rename lib/solvers/{dual_simplex => dual_bland}/CMakeLists.txt (90%) rename lib/solvers/{dual_simplex => dual_bland}/main.cpp (100%) rename lib/solvers/{dual_simplex => dual_bland}/main.hpp (100%) create mode 100644 lib/utils/dual_reformatter.cpp create mode 100644 lib/utils/dual_reformatter.hpp diff --git a/lib/core/consts.hpp b/lib/core/consts.hpp index 956dadf..318fc16 100644 --- a/lib/core/consts.hpp +++ b/lib/core/consts.hpp @@ -5,10 +5,10 @@ namespace core { -enum class PresolveRulesIds { - freeRowId = 0, - singletonVariableId, - rowSingletonId, +enum class PresolveRulesIds { + freeRowId = 0, + singletonVariableId, + rowSingletonId, parallelRowId, emptyColId, fixedColId, @@ -26,6 +26,11 @@ struct FormattedPrimalProblem { std::vector basic_variables; }; +struct FormattedDualProblem { + std::vector> problem_matrix; + std::vector basic_variables; +}; + struct FormattedLogicalProblem { std::vector> problem_matrix; std::vector lower_bounds; diff --git a/lib/solvers/CMakeLists.txt b/lib/solvers/CMakeLists.txt index 9af5dc2..350efdb 100644 --- a/lib/solvers/CMakeLists.txt +++ b/lib/solvers/CMakeLists.txt @@ -1,4 +1,4 @@ -add_subdirectory(dual_simplex) +add_subdirectory(dual_bland) add_subdirectory(primal_simplex) add_subdirectory(logical_solver) add_subdirectory(revised_primal_solver) diff --git a/lib/solvers/dual_simplex/CMakeLists.txt b/lib/solvers/dual_bland/CMakeLists.txt similarity index 90% rename from lib/solvers/dual_simplex/CMakeLists.txt rename to lib/solvers/dual_bland/CMakeLists.txt index 4fb7491..de75d17 100644 --- a/lib/solvers/dual_simplex/CMakeLists.txt +++ b/lib/solvers/dual_bland/CMakeLists.txt @@ -1,4 +1,4 @@ -set(target "dual_simplex") +set(target "dual_bland") file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp") file(GLOB code "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") add_library(${target} STATIC ${headers} ${code}) diff --git a/lib/solvers/dual_simplex/main.cpp b/lib/solvers/dual_bland/main.cpp similarity index 100% rename from lib/solvers/dual_simplex/main.cpp rename to lib/solvers/dual_bland/main.cpp diff --git a/lib/solvers/dual_simplex/main.hpp b/lib/solvers/dual_bland/main.hpp similarity index 100% rename from lib/solvers/dual_simplex/main.hpp rename to lib/solvers/dual_bland/main.hpp diff --git a/lib/utils/dual_reformatter.cpp b/lib/utils/dual_reformatter.cpp new file mode 100644 index 0000000..a54cbc4 --- /dev/null +++ b/lib/utils/dual_reformatter.cpp @@ -0,0 +1,219 @@ +#include "dual_reformatter.hpp" + +namespace utils { + +DualRefomatter::DualRefomatter() {} + +core::FormattedDualProblem +DualRefomatter::reformatProblem(const core::InputRows input_rows) { + const std::vector dual_bounds = getDualBounds(input_rows); + const std::vector> dual_table = getDualTable(input_rows); + const std::vector objective_row = + getObjectiveRow(dual_bounds, dual_table); + const core::FormattedDualProblem full_table = + getFullTable(dual_table, objective_row); + return full_table; +} + +std::vector getDualBounds(const core::InputRows input_rows) { + + const float negative_one = -1.0; + std::vector dual_bounds; + + // add inequality rows to bounds + for (std::size_t i = 0; i < input_rows.inequality_rows.size(); ++i) { + dual_bounds.push_back(negative_one * + input_rows.inequality_rows.at(i).at(0)); + } + + // add potitive and negative of equality rows to bounds, creating equality by + // constraint + for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { + dual_bounds.push_back(negative_one * input_rows.equality_rows.at(i).at(0)); + } + + for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { + dual_bounds.push_back(input_rows.equality_rows.at(i).at(0)); + } + + return dual_bounds; +} + +std::vector> +DualRefomatter::getDualTable(const core::InputRows input_rows) { + + std::vector> dual_table; + + // make temporary row vector container + std::vector row_vector; + int rowlength; + const float negative_one = -1.0; + + // add inequality rows to table + for (std::size_t i = 0; i < input_rows.inequality_rows.size(); ++i) { + // remove first element of row vector + row_vector = input_rows.inequality_rows.at(i); + row_vector.erase(row_vector.begin()); + // add negative of ineqality constriaint to row + rowlength = row_vector.size(); + for (std::size_t j = 0; j < rowlength; ++j) { + row_vector.push_back(negative_one * row_vector.at(j)); + } + dual_table.push_back(row_vector); + row_vector.clear(); + } + + // add equality rows (and their negative) to table + for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { + // remove first element of row vector + row_vector = input_rows.equality_rows.at(i); + row_vector.erase(row_vector.begin()); + // add negative of eqality constriaint to row + rowlength = row_vector.size(); + for (std::size_t j = 0; j < rowlength; ++j) { + row_vector.push_back(negative_one * row_vector.at(j)); + } + dual_table.push_back(row_vector); + row_vector.clear(); + } + + for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { + // remove first element of row vector + row_vector = input_rows.equality_rows.at(i); + row_vector.erase(row_vector.begin()); + for (std::size_t j = 0; j < row_vector.size(); ++j) { + row_vector.at(j) = negative_one * row_vector.at(j); + } + // add negative of eqality constriaint to row + rowlength = row_vector.size(); + for (std::size_t j = 0; j < rowlength; ++j) { + row_vector.push_back(negative_one * row_vector.at(j)); + } + dual_table.push_back(row_vector); + row_vector.clear(); + } + + return dual_table; +} + +std::vector DualRefomatter::getObjectiveRow( + const std::vector dual_bounds, + const std::vector> dual_table) { + + // define length of objectve row + const uint32_t row_length = + dual_table.size() + 2 * dual_table.at(0).size() + 1; + + // initialiase and add first element of objective row + std::vector dual_objective_row; + dual_objective_row.push_back(1); + + const float negative_one = -1.0; + + // add primal bounds to dual objective row + for (std::size_t i = 0; i < dual_bounds.size(); ++i) { + dual_objective_row.push_back(negative_one * dual_bounds.at(i)); + } + + // add the neccesary number of zeros on to the end + const uint32_t num_zero_entries = row_length - dual_objective_row.size(); + for (size_t i = 0; i < num_zero_entries; ++i) { + dual_objective_row.push_back(0); + } + + // allow for zero bounds on dual table + dual_objective_row.push_back(0); + + return dual_objective_row; +} + +core::FormattedDualProblem +DualRefomatter::getFullTable(const std::vector> dual_table, + const std::vector objective_row) { + + std::vector> dual_table; + dual_table.push_back(objective_row); + + const std::uint32_t number_positive_rows = dual_table.at(0).size(); + const std::uint32_t row_length = objective_row.size() - 1; + + // to keep track of slack being added to dual table + std::size_t identity_1_position = 0; + + // temporary container to hold rows as they are created and slack matrix + // temporary colmns to be added + std::vector temp_row; + std::uint32_t num_slack_columns; + + // adding the negative primal table entries (transposed) + for (std::size_t i = 0; i < number_positive_rows; ++i) { + temp_row.push_back(0); + + // add primal transposed entries + for (std::size_t j = 0; j < dual_table.size(); ++j) { + temp_row.push_back(dual_table.at(j).at(i)); + } + + // add slack + num_slack_columns = row_length - temp_row.size(); + for (std::size_t j = 0; j < num_slack_columns; ++j) { + if (j == identity_1_position) { + temp_row.push_back(1); + } else { + temp_row.push_back(0); + } + } + + // add zero bounds column + temp_row.push_back(0); + + // add row, increment identity position and clear temporary row + dual_table.push_back(temp_row); + ++identity_1_position; + temp_row.clear(); + } + + const float negative_one = -1.0; + // adding the positive primal table entries (transposed) + for (std::size_t i = 0; i < number_positive_rows; ++i) { + temp_row.push_back(0); + + // add primal transposed entries + for (std::size_t j = 0; j < dual_table.size(); ++j) { + temp_row.push_back(negative_one * dual_table.at(j).at(i)); + } + + // add slack + num_slack_columns = row_length - temp_row.size(); + for (std::size_t j = 0; j < num_slack_columns; ++j) { + if (j == identity_1_position) { + temp_row.push_back(1); + } else { + temp_row.push_back(0); + } + } + + // add zero bounds column + temp_row.push_back(0); + + // add row, increment identity position and clear temporary row + dual_table.push_back(temp_row); + ++identity_1_position; + temp_row.clear(); + } + + // Get intial basis + std::vector initial_basis; + for (std::size_t i = dual_table.size() + 1; i < objective_row.size() - 2; + ++i) { + initial_basis.push_back(i); + } + + core::FormattedPrimalProblem formatted_problem; + formatted_problem.problem_matrix = dual_table; + formatted_problem.basic_variables = initial_basis; + + return formatted_problem; +} + +} // namespace utils \ No newline at end of file diff --git a/lib/utils/dual_reformatter.hpp b/lib/utils/dual_reformatter.hpp new file mode 100644 index 0000000..7a3d6a3 --- /dev/null +++ b/lib/utils/dual_reformatter.hpp @@ -0,0 +1,27 @@ +#include "../core/consts.hpp" +#include +#include + +namespace utils { + +class DualRefomatter { +public: + DualRefomatter(); + + core::FormattedDualProblem reformatProblem(const core::InputRows input_rows); + +private: + std::vector getDualBounds(const core::InputRows input_rows); + + std::vector> + getDualTable(const core::InputRows input_rows); + + std::vector + getObjectiveRow(const std::vector dual_bounds, + const std::vector> dual_table); + + core::FormattedDualProblem + getFullTable(const std::vector> dual_table, + const std::vector objective_row); +}; +} // namespace utils \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 09750b3..aa790b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories(${target} ) target_link_libraries(${target} - dual_simplex + dual_bland primal_simplex utils logical_solver From 341a768101997236ed75b786084485358807e767 Mon Sep 17 00:00:00 2001 From: maxguy2001 Date: Tue, 14 Mar 2023 15:29:05 +0000 Subject: [PATCH 2/2] dual reformatter mostly working --- lib/utils/dual_reformatter.cpp | 217 ++++++++++----------------------- lib/utils/dual_reformatter.hpp | 13 +- 2 files changed, 67 insertions(+), 163 deletions(-) diff --git a/lib/utils/dual_reformatter.cpp b/lib/utils/dual_reformatter.cpp index a54cbc4..181675b 100644 --- a/lib/utils/dual_reformatter.cpp +++ b/lib/utils/dual_reformatter.cpp @@ -6,212 +6,121 @@ DualRefomatter::DualRefomatter() {} core::FormattedDualProblem DualRefomatter::reformatProblem(const core::InputRows input_rows) { - const std::vector dual_bounds = getDualBounds(input_rows); - const std::vector> dual_table = getDualTable(input_rows); - const std::vector objective_row = - getObjectiveRow(dual_bounds, dual_table); - const core::FormattedDualProblem full_table = - getFullTable(dual_table, objective_row); + const std::vector bounds = getBounds(input_rows); + const std::vector> table = getTable(input_rows); + const core::FormattedDualProblem full_table = getFullTable(table, bounds); return full_table; } -std::vector getDualBounds(const core::InputRows input_rows) { +std::vector DualRefomatter::getBounds(const core::InputRows input_rows) { - const float negative_one = -1.0; - std::vector dual_bounds; + std::vector bounds; // add inequality rows to bounds for (std::size_t i = 0; i < input_rows.inequality_rows.size(); ++i) { - dual_bounds.push_back(negative_one * - input_rows.inequality_rows.at(i).at(0)); + bounds.push_back(-1.0F * input_rows.inequality_rows.at(i).at(0)); } // add potitive and negative of equality rows to bounds, creating equality by // constraint for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { - dual_bounds.push_back(negative_one * input_rows.equality_rows.at(i).at(0)); + bounds.push_back(-1.0F * input_rows.equality_rows.at(i).at(0)); } for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { - dual_bounds.push_back(input_rows.equality_rows.at(i).at(0)); + bounds.push_back(input_rows.equality_rows.at(i).at(0)); } - return dual_bounds; + return bounds; } std::vector> -DualRefomatter::getDualTable(const core::InputRows input_rows) { +DualRefomatter::getTable(const core::InputRows input_rows) { - std::vector> dual_table; + std::vector> table; // make temporary row vector container std::vector row_vector; - int rowlength; - const float negative_one = -1.0; // add inequality rows to table for (std::size_t i = 0; i < input_rows.inequality_rows.size(); ++i) { - // remove first element of row vector - row_vector = input_rows.inequality_rows.at(i); - row_vector.erase(row_vector.begin()); - // add negative of ineqality constriaint to row - rowlength = row_vector.size(); - for (std::size_t j = 0; j < rowlength; ++j) { - row_vector.push_back(negative_one * row_vector.at(j)); - } - dual_table.push_back(row_vector); row_vector.clear(); + for (std::size_t j = 1; j < input_rows.inequality_rows.at(0).size(); ++j) { + row_vector.push_back(input_rows.inequality_rows.at(i).at(j)); + } + for (std::size_t j = 1; j < input_rows.inequality_rows.at(0).size(); ++j) { + row_vector.push_back(-1.0F * input_rows.inequality_rows.at(i).at(j)); + } + table.push_back(row_vector); } - // add equality rows (and their negative) to table + // add equality rows to table for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { - // remove first element of row vector - row_vector = input_rows.equality_rows.at(i); - row_vector.erase(row_vector.begin()); - // add negative of eqality constriaint to row - rowlength = row_vector.size(); - for (std::size_t j = 0; j < rowlength; ++j) { - row_vector.push_back(negative_one * row_vector.at(j)); - } - dual_table.push_back(row_vector); row_vector.clear(); + for (std::size_t j = 1; j < input_rows.equality_rows.at(0).size(); ++j) { + row_vector.push_back(input_rows.equality_rows.at(i).at(j)); + } + for (std::size_t j = 1; j < input_rows.equality_rows.at(0).size(); ++j) { + row_vector.push_back(-1.0F * input_rows.equality_rows.at(i).at(j)); + } + table.push_back(row_vector); } + // add negative of equality rows to table for (std::size_t i = 0; i < input_rows.equality_rows.size(); ++i) { - // remove first element of row vector - row_vector = input_rows.equality_rows.at(i); - row_vector.erase(row_vector.begin()); - for (std::size_t j = 0; j < row_vector.size(); ++j) { - row_vector.at(j) = negative_one * row_vector.at(j); + row_vector.clear(); + for (std::size_t j = 1; j < input_rows.equality_rows.at(0).size(); ++j) { + row_vector.push_back(-1.0F * input_rows.equality_rows.at(i).at(j)); } - // add negative of eqality constriaint to row - rowlength = row_vector.size(); - for (std::size_t j = 0; j < rowlength; ++j) { - row_vector.push_back(negative_one * row_vector.at(j)); + for (std::size_t j = 1; j < input_rows.equality_rows.at(0).size(); ++j) { + row_vector.push_back(input_rows.equality_rows.at(i).at(j)); } - dual_table.push_back(row_vector); - row_vector.clear(); + table.push_back(row_vector); } - - return dual_table; -} - -std::vector DualRefomatter::getObjectiveRow( - const std::vector dual_bounds, - const std::vector> dual_table) { - - // define length of objectve row - const uint32_t row_length = - dual_table.size() + 2 * dual_table.at(0).size() + 1; - - // initialiase and add first element of objective row - std::vector dual_objective_row; - dual_objective_row.push_back(1); - - const float negative_one = -1.0; - - // add primal bounds to dual objective row - for (std::size_t i = 0; i < dual_bounds.size(); ++i) { - dual_objective_row.push_back(negative_one * dual_bounds.at(i)); - } - - // add the neccesary number of zeros on to the end - const uint32_t num_zero_entries = row_length - dual_objective_row.size(); - for (size_t i = 0; i < num_zero_entries; ++i) { - dual_objective_row.push_back(0); - } - - // allow for zero bounds on dual table - dual_objective_row.push_back(0); - - return dual_objective_row; + return table; } core::FormattedDualProblem -DualRefomatter::getFullTable(const std::vector> dual_table, - const std::vector objective_row) { - - std::vector> dual_table; - dual_table.push_back(objective_row); - - const std::uint32_t number_positive_rows = dual_table.at(0).size(); - const std::uint32_t row_length = objective_row.size() - 1; - - // to keep track of slack being added to dual table - std::size_t identity_1_position = 0; - - // temporary container to hold rows as they are created and slack matrix - // temporary colmns to be added - std::vector temp_row; - std::uint32_t num_slack_columns; +DualRefomatter::getFullTable(const std::vector> input_table, + const std::vector bounds) { - // adding the negative primal table entries (transposed) - for (std::size_t i = 0; i < number_positive_rows; ++i) { - temp_row.push_back(0); + // container for full table + std::vector> full_table; - // add primal transposed entries - for (std::size_t j = 0; j < dual_table.size(); ++j) { - temp_row.push_back(dual_table.at(j).at(i)); - } - - // add slack - num_slack_columns = row_length - temp_row.size(); - for (std::size_t j = 0; j < num_slack_columns; ++j) { - if (j == identity_1_position) { - temp_row.push_back(1); - } else { - temp_row.push_back(0); - } - } - - // add zero bounds column - temp_row.push_back(0); + // temporary row vector for use in making table + std::vector row_vector; + const int row_length = input_table.size() + input_table.at(0).size() + 1; - // add row, increment identity position and clear temporary row - dual_table.push_back(temp_row); - ++identity_1_position; - temp_row.clear(); + // add objective row + row_vector.push_back(1.0F); + for (std::size_t i = 0; i < row_length; ++i) { + row_vector.push_back(0.0F); } + full_table.push_back(row_vector); + row_vector.clear(); - const float negative_one = -1.0; - // adding the positive primal table entries (transposed) - for (std::size_t i = 0; i < number_positive_rows; ++i) { - temp_row.push_back(0); - - // add primal transposed entries - for (std::size_t j = 0; j < dual_table.size(); ++j) { - temp_row.push_back(negative_one * dual_table.at(j).at(i)); + int index_1_position = 0; + for (std::size_t i = 0; i < input_table.size(); ++i) { + row_vector.clear(); + row_vector.push_back(0); + for (std::size_t j = 0; j < input_table.at(0).size(); ++j) { + row_vector.push_back(input_table.at(i).at(j)); } - - // add slack - num_slack_columns = row_length - temp_row.size(); - for (std::size_t j = 0; j < num_slack_columns; ++j) { - if (j == identity_1_position) { - temp_row.push_back(1); + for (std::size_t j = 0; j < input_table.size(); ++j) { + if (j == index_1_position) { + row_vector.push_back(1); } else { - temp_row.push_back(0); + row_vector.push_back(0); } } - - // add zero bounds column - temp_row.push_back(0); - - // add row, increment identity position and clear temporary row - dual_table.push_back(temp_row); - ++identity_1_position; - temp_row.clear(); - } - - // Get intial basis - std::vector initial_basis; - for (std::size_t i = dual_table.size() + 1; i < objective_row.size() - 2; - ++i) { - initial_basis.push_back(i); + row_vector.push_back(bounds.at(i)); + full_table.push_back(row_vector); } - core::FormattedPrimalProblem formatted_problem; - formatted_problem.problem_matrix = dual_table; - formatted_problem.basic_variables = initial_basis; + core::FormattedDualProblem formatted_problem; + formatted_problem.problem_matrix = full_table; + // TODO: figure out basic variables here + // formatted_problem.basic_variables; return formatted_problem; } diff --git a/lib/utils/dual_reformatter.hpp b/lib/utils/dual_reformatter.hpp index 7a3d6a3..864db13 100644 --- a/lib/utils/dual_reformatter.hpp +++ b/lib/utils/dual_reformatter.hpp @@ -11,17 +11,12 @@ class DualRefomatter { core::FormattedDualProblem reformatProblem(const core::InputRows input_rows); private: - std::vector getDualBounds(const core::InputRows input_rows); + std::vector getBounds(const core::InputRows input_rows); - std::vector> - getDualTable(const core::InputRows input_rows); - - std::vector - getObjectiveRow(const std::vector dual_bounds, - const std::vector> dual_table); + std::vector> getTable(const core::InputRows input_rows); core::FormattedDualProblem - getFullTable(const std::vector> dual_table, - const std::vector objective_row); + getFullTable(const std::vector> input_table, + const std::vector bounds); }; } // namespace utils \ No newline at end of file