Skip to content

Commit

Permalink
Add ability to handle infeasible models when optimizations are turned…
Browse files Browse the repository at this point in the history
… off.
  • Loading branch information
sukritkalra committed Dec 2, 2023
1 parent 2ee2250 commit bd13518
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 11 deletions.
6 changes: 6 additions & 0 deletions schedulers/tetrisched/include/tetrisched/Solver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ struct SolverSolution {
/// The time taken by the solver to find the solution (in microseconds).
uint64_t solverTimeMicroseconds;

/// Check if the solution was valid.
bool isValid() const {
return solutionType == SolutionType::FEASIBLE ||
solutionType == SolutionType::OPTIMAL;
}

/// Get a string representation of the Solver's type.
std::string getSolutionTypeStr() const {
switch (solutionType) {
Expand Down
2 changes: 2 additions & 0 deletions schedulers/tetrisched/python/Backends.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void defineSolverSolution(py::module_& tetrisched_m) {
[](const tetrisched::SolverSolution& solution) {
return solution.solverTimeMicroseconds;
})
.def("isValid", &tetrisched::SolverSolution::isValid,
"Check if the solution was valid.")
.def("__str__", [](const tetrisched::SolverSolution& solution) {
return "SolverSolution<type=" + solution.getSolutionTypeStr() +
", objectiveValue=" +
Expand Down
8 changes: 4 additions & 4 deletions schedulers/tetrisched/src/GurobiSolver.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "tetrisched/GurobiSolver.hpp"

#include <chrono>
#include <thread>
#include <cmath>
#include <thread>

namespace tetrisched {
GurobiSolver::GurobiSolver()
Expand Down Expand Up @@ -241,16 +241,16 @@ SolverSolutionPtr GurobiSolver::solveModel() {
break;
case GRB_INFEASIBLE:
solverSolution->solutionType = SolutionType::INFEASIBLE;
break;
return solverSolution;
case GRB_INF_OR_UNBD:
case GRB_UNBOUNDED:
solverSolution->solutionType = SolutionType::UNBOUNDED;
break;
return solverSolution;
default:
solverSolution->solutionType = SolutionType::UNKNOWN;
TETRISCHED_DEBUG("The Gurobi solver returned the value: "
<< gurobiModel->get(GRB_IntAttr_Status));
break;
return solverSolution;
}
TETRISCHED_DEBUG("The Gurobi solver took "
<< solverSolution->solverTimeMicroseconds << " microseconds "
Expand Down
4 changes: 3 additions & 1 deletion schedulers/tetrisched/src/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ void Scheduler::schedule(Time currentTime) {
solverSolution = this->solver->solveModel();

// Populate the results from the solver into the expression tree.
this->expression.value()->populateResults(solverModel);
if (solverSolution.has_value() && solverSolution.value()->isValid()) {
this->expression.value()->populateResults(solverModel);
}
}

SolverSolutionPtr Scheduler::getLastSolverSolution() const {
Expand Down
28 changes: 22 additions & 6 deletions schedulers/tetrisched_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,21 @@ def schedule(
)
raise e

# If the solver could not solve the model, log an error.
if not self._scheduler.getLastSolverSolution().isValid():
self._logger.error(
f"[{sim_time.time}] The solver failed to find a solution for "
f"the STRL expression. Dumping the model to "
f"tetrisched_error_{sim_time.time}.lp and STRL expression to "
f"tetrisched_error_{sim_time.time}.dot."
)
objective_strl.exportToDot(
os.path.join(self._log_dir, f"tetrisched_error_{sim_time.time}.dot")
)
self._scheduler.exportLastSolverModel(
os.path.join(self._log_dir, f"tetrisched_error_{sim_time.time}.lp")
)

# If requested, log the model to a file.
if self._log_to_file or sim_time.time in self._log_times:
self._scheduler.exportLastSolverModel(
Expand All @@ -353,12 +368,13 @@ def schedule(

# Retrieve the solution and check if we were able to schedule anything.
solverSolution = objective_strl.getSolution()
self._logger.info(
f"[{sim_time.time}] Solver returned utility of {solverSolution.utility}"
f" and took {solver_time} to solve. The solution result "
f"was {self._scheduler.getLastSolverSolution()}."
)
if solverSolution.utility > 0:
if solverSolution is not None and solverSolution.utility > 0:
self._logger.info(
f"[{sim_time.time}] Solver returned utility of "
f"{solverSolution.utility} and took {solver_time} to solve. The "
f"solution result was {self._scheduler.getLastSolverSolution()}."
)

# Retrieve the Placements for each task.
for task in tasks_to_be_scheduled:
task_placement = solverSolution.getPlacement(task.unique_name)
Expand Down

0 comments on commit bd13518

Please sign in to comment.