Skip to content

Commit

Permalink
Fix rough edges in SolverModel.
Browse files Browse the repository at this point in the history
  • Loading branch information
sukritkalra committed Sep 23, 2023
1 parent 2f6f08a commit 3207bbd
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 42 deletions.
6 changes: 4 additions & 2 deletions schedulers/tetrisched/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
cmake_minimum_required(VERSION 3.5...3.26)
project(tetrisched LANGUAGES CXX)

# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
# Compile with atleast C++20.
# Set cmake -D CMAKE_CXX_COMPILER=/path/to/C++20/compatible/compiler.
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")

# Include debug information.
set(CMAKE_BUILD_TYPE Debug)
Expand Down
21 changes: 18 additions & 3 deletions schedulers/tetrisched/include/tetrisched/Expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <optional>
#include <unordered_map>
#include <variant>
#include <functional>

#include "tetrisched/Partition.hpp"
#include "tetrisched/SolverModel.hpp"
Expand All @@ -12,6 +13,12 @@

namespace tetrisched {

/// A `UtilityFn` represents the function that is used to calculate the utility
/// of a particular expression.
template <typename T>
using UtilityFnT = std::function<T(Time, Time)>;
using UtilityFn = UtilityFnT<TETRISCHED_ILP_TYPE>;

/// A `ParseResultType` enumeration represents the types of results that
/// parsing an expression can return.
enum ParseResultType {
Expand All @@ -30,14 +37,21 @@ enum ParseResultType {

/// A `ParseResult` class represents the result of parsing an expression.
struct ParseResult {
using TimeOrVariableT = std::variant<Time, VariablePtr>;
using IndicatorT = std::variant<uint32_t, VariablePtr>;
/// The type of the result.
ParseResultType type;
/// The start time associated with the parsed result.
/// Can be either a Time known at runtime or a pointer to a Solver variable.
std::optional<std::variant<Time, VariablePtr>> startTime;
std::optional<TimeOrVariableT> startTime;
/// The end time associated with the parsed result.
/// Can be either a Time known at runtime or a pointer to a Solver variable.
std::optional<std::variant<Time, VariablePtr>> endTime;
std::optional<TimeOrVariableT> endTime;
/// The indicator associated with the parsed result.
/// This indicator denotes if the expression was satisfied or not.
/// The indicator can return an integer if it is trivially satisfied during parsing.
/// Note that the startTime and endTime are only valid if the indicator is 1.
std::optional<IndicatorT> indicator;
};

struct PartitionTimePairHasher {
Expand Down Expand Up @@ -65,7 +79,8 @@ class CapacityConstraintMap {
CapacityConstraintMap() {}
void registerUsageAtTime(const Partition& partition, Time time,
VariablePtr variable);
void registerUsageAtTime(const Partition& partition, Time time, uint32_t usage);
void registerUsageAtTime(const Partition& partition, Time time,
uint32_t usage);
void registerUsageForDuration(const Partition& partition, Time startTime,
Time duration, VariablePtr variable,
Time granularity = 1);
Expand Down
2 changes: 1 addition & 1 deletion schedulers/tetrisched/include/tetrisched/Partition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Partition {
/// Partitions are being allowed to be constructed once and shared by
/// multiple Expressions. This allows equivalence checks that currently
/// rely on the ID of the Partition instead of the actual Workers inside it.
typedef std::shared_ptr<Partition> PartitionPtr;
using PartitionPtr = std::shared_ptr<Partition>;


/// @brief A Partitions object represents a collection of Partition.
Expand Down
52 changes: 29 additions & 23 deletions schedulers/tetrisched/include/tetrisched/SolverModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <optional>
#include <string>
#include <vector>
#include <fstream>

#include "tetrisched/Types.hpp"

Expand All @@ -13,11 +14,8 @@ namespace tetrisched {
/// A `VariableType` enumeration represents the types of variable that we allow
/// the user to construct. These map to the types of variables that the
/// underlying solver supports.
typedef enum VariableType {
VAR_CONTINUOUS,
VAR_INTEGER,
VAR_INDICATOR
} VariableType;
enum VariableType { VAR_CONTINUOUS, VAR_INTEGER, VAR_INDICATOR };
using VariableType = enum VariableType;

/// A `VariableT` class represents a variable in the solver model. Note that
/// this is an internal representation of a VariableT and does not contain an
Expand Down Expand Up @@ -67,21 +65,22 @@ class VariableT {
};

// Specialize the VariableT class for Integer type.
template class VariableT<int32_t>;
typedef VariableT<int32_t> Variable;
typedef std::shared_ptr<Variable> VariablePtr;
template class VariableT<TETRISCHED_ILP_TYPE>;
using Variable = VariableT<TETRISCHED_ILP_TYPE>;
using VariablePtr = std::shared_ptr<Variable>;

/// A `ConstraintType` enumeration represents the types of constraints that we
/// allow the user to construct. These map to the types of constraints that the
/// underlying solver supports.
typedef enum ConstraintType {
enum ConstraintType {
/// LHS <= RHS
CONSTR_LE,
/// LHS = RHS
CONSTR_EQ,
/// LHS >= RHS
CONSTR_GE,
} ConstraintType;
};
using ConstraintType = enum ConstraintType;

template <typename T>
class ConstraintT {
Expand All @@ -98,7 +97,8 @@ class ConstraintT {

public:
/// Generate a new constraint with the given type and right hand side.
ConstraintT(std::string constraintName, ConstraintType constraintType, T rightHandSide);
ConstraintT(std::string constraintName, ConstraintType constraintType,
T rightHandSide);

/// Adds a term to the left-hand side constraint.
void addTerm(std::pair<T, std::shared_ptr<VariableT<T>>> term);
Expand All @@ -112,23 +112,27 @@ class ConstraintT {
/// Retrieve a string representation of this Constraint.
std::string toString() const;

/// Retrieve the name of this Constraint.
std::string getName() const;

/// Retrieve the number of terms in this Constraint.
size_t size() const;
};

// Specialize the Constraint class for Integer.
template class ConstraintT<int32_t>;
typedef ConstraintT<int32_t> Constraint;
typedef std::unique_ptr<Constraint> ConstraintPtr;
template class ConstraintT<TETRISCHED_ILP_TYPE>;
using Constraint = ConstraintT<TETRISCHED_ILP_TYPE>;
using ConstraintPtr = std::unique_ptr<Constraint>;

/// A `ObjectiveType` enumeration represents the types of objective functions
/// that we allow the user to construct.
typedef enum ObjectiveType {
enum ObjectiveType {
/// Maximize the objective function.
OBJ_MAXIMIZE,
/// Minimize the objective function.
OBJ_MINIMIZE,
} ObjectiveType;
};
using ObjectiveType = enum ObjectiveType;

template <typename T>
class ObjectiveFunctionT {
Expand All @@ -153,9 +157,9 @@ class ObjectiveFunctionT {
};

// Specialize the ObjectiveFunction class for Integer.
template class ObjectiveFunctionT<int32_t>;
typedef ObjectiveFunctionT<int32_t> ObjectiveFunction;
typedef std::unique_ptr<ObjectiveFunction> ObjectiveFunctionPtr;
template class ObjectiveFunctionT<TETRISCHED_ILP_TYPE>;
using ObjectiveFunction = ObjectiveFunctionT<TETRISCHED_ILP_TYPE>;
using ObjectiveFunctionPtr = std::unique_ptr<ObjectiveFunction>;

template <typename T>
class SolverModelT {
Expand Down Expand Up @@ -187,6 +191,9 @@ class SolverModelT {
/// Retrieve a string representation of this SolverModel.
std::string toString() const;

/// Export the string representation of this SolverModel to a file.
void exportModel(std::string filename) const;

/// Retrieve the number of variables in this SolverModel.
size_t numVariables() const;

Expand All @@ -200,10 +207,9 @@ class SolverModelT {
};

// Specialize the SolverModel class for Integer.
template class SolverModelT<int32_t>;
typedef SolverModelT<int32_t> SolverModel;
typedef std::shared_ptr<SolverModel> SolverModelPtr;
template class SolverModelT<TETRISCHED_ILP_TYPE>;
using SolverModel = SolverModelT<TETRISCHED_ILP_TYPE>;
using SolverModelPtr = std::shared_ptr<SolverModel>;

} // namespace tetrisched

#endif
3 changes: 1 addition & 2 deletions schedulers/tetrisched/include/tetrisched/Task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class Task {

const std::string& getTaskName() const { return taskName; }
};

typedef std::shared_ptr<Task> TaskPtr;
using TaskPtr = std::shared_ptr<Task>;
} // namespace tetrisched
#endif // _TETRISCHED_TASK_HPP_
12 changes: 10 additions & 2 deletions schedulers/tetrisched/include/tetrisched/Types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
std::cout << x << std::endl; \
}

// Macro for the coefficient and the permissible values for the Variables.
// (Sukrit): It is unknown if the ILP will perform better if the coefficients
// and variables are int32_t or double. This is something that we should
// experiment with. Note that both CPLEX and Gurobi do not like 32-bit floating
// points (due to documented numerical difficulties) so the only permissible
// values for this macro is supposed to be int32_t or double.
#define TETRISCHED_ILP_TYPE int32_t

namespace tetrisched {
/// Defines the exceptions that the methods can throw.
namespace exceptions {
Expand All @@ -33,11 +41,11 @@ class ExpressionConstructionException : public std::exception {
/// We currently use a uint32_t since it translates well from the simulator.
/// When this library is deployed for real use, this might need to change to a
/// double.
typedef uint32_t Time;
using Time = uint32_t;

/// General forward declarations.
class Expression;
typedef std::unique_ptr<Expression> ExpressionPtr;
using ExpressionPtr = std::unique_ptr<Expression>;

/// Forward declarations for Solver instantiations so that we can declare
/// them as friend classes in the model.
Expand Down
3 changes: 1 addition & 2 deletions schedulers/tetrisched/include/tetrisched/Worker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class Worker {
const std::string &getWorkerName() const;
};

typedef std::shared_ptr<Worker> WorkerPtr;

using WorkerPtr = std::shared_ptr<Worker>;
} // namespace tetrisched
#endif
1 change: 1 addition & 0 deletions schedulers/tetrisched/src/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ ParseResult ChooseExpression::parse(SolverModelPtr solverModel,
.type = ParseResultType::EXPRESSION_UTILITY,
.startTime = startTime,
.endTime = endTime,
.indicator = isSatisfiedVar,
};
}
} // namespace tetrisched
Expand Down
19 changes: 16 additions & 3 deletions schedulers/tetrisched/src/SolverModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ std::string ConstraintT<T>::toString() const {
return constraintString;
}

template <typename T>
std::string ConstraintT<T>::getName() const {
return constraintName;
}

template <typename T>
size_t ConstraintT<T>::size() const {
return terms.size();
Expand Down Expand Up @@ -164,11 +169,12 @@ template <typename T>
std::string SolverModelT<T>::toString() const {
std::string modelString;
modelString += objectiveFunction->toString();
modelString += "\nConstraints: \n";
modelString += "\n\nConstraints: \n";
for (auto &constraint : constraints) {
modelString += "\t" + constraint->toString() + "\n";
modelString +=
constraint->getName() + ": \t" + constraint->toString() + "\n";
}
modelString += "Variables: ";
modelString += "\nVariables: \n\t";
for (auto &variable : variables) {
modelString += variable->toString();
if (&variable != &variables.back()) {
Expand All @@ -178,6 +184,13 @@ std::string SolverModelT<T>::toString() const {
return modelString;
}

template <typename T>
void SolverModelT<T>::exportModel(std::string filename) const {
std::ofstream modelFile(filename);
modelFile << this->toString();
modelFile.close();
}

template <typename T>
size_t SolverModelT<T>::numVariables() const {
return variables.size();
Expand Down
10 changes: 6 additions & 4 deletions schedulers/tetrisched/test/test_solver.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <gtest/gtest.h>

#include <filesystem>

#include "tetrisched/Solver.hpp"
#include "tetrisched/SolverModel.hpp"

Expand Down Expand Up @@ -50,10 +52,10 @@ TEST(SolverModelTypes, TestSolverModel) {

EXPECT_EQ(solverModel->numVariables(), 1);
EXPECT_EQ(solverModel->numConstraints(), 1);
EXPECT_EQ(solverModel->toString(),
"Maximize: (1*intVar)\n"
"Constraints: \n\t(1*intVar) <= 10\n"
"Variables: intVar");
solverModel->exportModel("test.lp");
EXPECT_TRUE(std::filesystem::exists("test.lp"))
<< "The file test.lp was not created.";
std::filesystem::remove("test.lp");
}

TEST(SolverModel, TestCPLEXSolverInitialization) {
Expand Down

0 comments on commit 3207bbd

Please sign in to comment.