29 #include "SolverConfig.h"
42 EXIT_WITH_SUCCESS = 0,
43 INVALID_PARAMETER = 1,
44 INPUT_OUTPUT_ERROR = 2,
58 cout<<
"Energy optimizator of robotic cells."<<endl;
59 cout<<
"Authors: Libor Bukata and Premysl Sucha"<<endl;
60 cout<<
"Licence: GNU General Public License"<<endl;
61 cout<<
"Program version: "<<PROGRAM_VERSION<<endl;
63 cout<<
"Build type: "<<BUILD_TYPE<<endl;
73 cout<<endl<<
"Usage:"<<endl;
74 cout<<
"\t"<<progName<<
" [options] --dataset FILE"<<endl<<endl;
75 cout<<
"General options:"<<endl;
76 cout<<
"\t--dataset ARG, -d ARG, ARG: FILE"<<endl;
77 cout<<
"\t\tThe input dataset to solve (an xml file)."<<endl;
78 cout<<
"\t--verbose, -v"<<endl;
79 cout<<
"\t\tAn additional information is printed (solver progress, runtime, etc.)."<<endl;
80 cout<<
"\t--number-of-segments ARG, -nos ARG, ARG: INTEGER"<<endl;
81 cout<<
"\t\tThe number of segments of each discretized energy function."<<endl;
82 cout<<
"\t--number-of-threads ARG, -not ARG, ARG: INTEGER"<<endl;
83 cout<<
"\t\tThe number of concurrent threads (default is autodetect)."<<endl;
84 cout<<
"\t--help, -h"<<endl;
85 cout<<
"\t\tIt prints this help."<<endl;
86 cout<<
"\t--max-runtime ARG, -mr ARG, ARG: FLOAT"<<endl;
87 cout<<
"\t\t"<<
"It sets the time limit per instance for a selected algorithm (in seconds)."<<endl;
88 cout<<
"\t--use-heuristic-algorithm, -uha"<<endl;
89 cout<<
"\t\t"<<
"A heuristic algorithm is employed to solve instances."<<endl;
90 cout<<
"\t--use-exact-algorithm, -uea"<<endl;
91 cout<<
"\t\t"<<
"An exact algorithm is preferred as a problem solver."<<endl;
92 cout<<
"\t--write-results ARG, -wr ARG, ARG: DIRECTORY"<<endl;
93 cout<<
"\t\tIt specifies where the solutions, error logs, and performance logs will be written."<<endl<<endl;
94 cout<<
"ILP solver options:"<<endl;
95 cout<<
"\t--ilp-solver-relative-gap ARG, -isrg ARG, ARG: DECIMAL"<<endl;
96 cout<<
"\t\tIt stops the solver after achieving the relative gap between the best integer solution and lower bound."<<endl;
97 cout<<
"\t\tSetting the gap to 0.05 means that solver stops after proving 5 % maximal gap from the optimal solution."<<endl;
98 cout<<
"\t--lower-bound-calculation, -lbc"<<endl;
99 cout<<
"\t\tIt turns on the calculation of a tighter lower bound by using a problem decomposition and an ILP solver."<<endl;
100 cout<<
"\t--lower-bound-runtime ARG, -lbr ARG, ARG: FLOAT"<<endl;
101 cout<<
"\t\tIt sets a time limit for the tight lower bound calculation."<<endl<<endl;
102 cout<<
"Heuristic options:"<<endl;
103 cout<<
"\t--number-of-elite-solutions ARG, -noes ARG, ARG: INTEGER"<<endl;
104 cout<<
"\t\tThe maximal number of elite solutions in the pool."<<endl;
105 cout<<
"\t--max-number-of-alternatives ARG, -mnoa ARG, ARG: INTEGER"<<endl;
106 cout<<
"\t\tThe maximal number of alternatives to consider for each robot."<<endl;
107 cout<<
"\t--minimal-number-of-iters-per-tuple ARG, -mnoipt ARG, ARG: INTEGER"<<endl;
108 cout<<
"\t\tThe minimal number of runs of sub-heuristics for each feasible solution. Sub-heuristics, i.e."<<endl;
109 cout<<
"\t\t(de)select power mode, change locations, and change path, are executed in the round robin order."<<endl<<endl;
110 cout<<
"Default settings can be modified at \"DefaultSettings.h\" file."<<endl;
132 if (number.empty() || number[0] ==
'-')
133 throw InvalidArgument(caller(),
"Argument must be a positive number!");
136 istringstream istr(number, istringstream::in);
154 bool getArgument(
int& i,
int argc,
char* argv[],
const string& fullName,
const string& shortName,
string& writeArgument) {
155 string arg = argv[i];
156 if (arg == fullName || arg == shortName) {
158 writeArgument = argv[++i];
161 throw InvalidArgument(caller(),
"'"+fullName+
"' requires the argument!");
178 bool processArg(
int& i,
int argc,
char* argv[],
const string& fullName,
const string& shortName,
bool* toWrite =
nullptr) {
179 string arg = argv[i];
180 if (arg == fullName || arg == shortName) {
181 if (toWrite !=
nullptr)
199 bool processArg(
int& i,
int argc,
char* argv[],
const string& fullName,
const string& shortName,
string& toWrite) {
200 return getArgument(i, argc, argv, fullName, shortName, toWrite);
216 bool processArg(
int& i,
int argc,
char* argv[],
const string& fullName,
const string& shortName, T& toWrite, T minValue = 1) {
218 if (
getArgument(i, argc, argv, fullName, shortName, strNumber)) {
221 number = parsePositiveNumber<T>(strNumber);
223 throw_with_nested(
InvalidArgument(caller(),
"Cannot read the parameter of '"+fullName+
"' option!"));
226 if (number >= minValue) {
230 throw InvalidArgument(caller(),
"The '"+fullName+
"' parameter needs to be a positive number!");
245 for (
int i = 1; i < argc; ++i) {
251 if (
processArg(i, argc, argv,
"--help",
"-h") ==
true) {
270 throw InvalidArgument(caller(),
"Unknown argument \""+
string(argv[i])+
"\"!");
274 throw InvalidArgument(caller(),
"Insufficient number of parameters! At least a dataset must be specified!");
298 int main(
int argc,
char* argv[]) {
305 return EXIT_WITH_SUCCESS;
308 return EXIT_WITH_SUCCESS;
317 const vector<RoboticLine>& lines = reader.dataset();
318 const vector<PrecalculatedMapping>& mappings = reader.precalculatedMappings();
321 for (uint32_t lineId = 0; lineId < min(lines.size(), mappings.size()); ++lineId) {
330 solution = solver.
solve();
333 solution = solver.
solve();
346 cout<<solution<<endl;
361 cerr<<
"Solution of instance "<<lineId<<
" is invalid:"<<endl;
368 ofstream errorLog(instanceErrorFile.c_str());
369 if (errorLog.good()) {
371 errorLog<<errMsg<<endl;
373 cerr<<
"Cannot open an error log for instance "<<lineId<<
"!"<<endl;
384 cerr<<
"\nProjectSolver: Cannot read the input dataset!"<<endl;
385 return INPUT_OUTPUT_ERROR;
388 return INVALID_PARAMETER;
391 cerr<<
"\nProjectSolver: A runtime error occurred, terminating..."<<endl;
392 return RUNTIME_ERROR;
393 }
catch (
const exception& e) {
395 return UNKNOWN_ERROR;
399 return EXIT_WITH_SUCCESS;
bool USE_EXACT_ALGORITHM
The variable indicates whether the exact algorithm should be used.
double ILP_RELATIVE_GAP
If a given relative gap from the best known lower bound is achieved, then the solver stops...
bool processCommandLineArguments(int argc, char *argv[])
It parses the program arguments and sets the desired parameters for optimization. ...
The structure representing a solution found by an algorithm.
uint32_t MAX_ALTERNATIVES
The maximal number of alternative orders generated for each robot.
std::string exceptionToString(const std::exception &e, uint32_t level=0)
The recursive method creates the formatted error message for the given exception and their nested sub...
uint32_t NUMBER_OF_SEGMENTS
By how many segments (linear pieces) the energy function of the movement is approximated.
string DATASET_FILE
Dataset with problems to be solved.
ProgramReturnedCodes
Return codes of the program with obvious meanings.
void printProgramHelp(const string &progName)
It prints the program header and brief help.
The class is intended to be used by users for the dataset parsing and checking.
Solution solve()
It optimizes the robotic cell and returns the best found solution.
An instance of this class is devoted to the solution checking.
int main(int argc, char *argv[])
An entry point of the program, arguments are processed, dataset is parsed and solved, and results printed and optionally written to files.
Checking and post-processing of parsed datasets.
A general exception of the program.
bool CALCULATE_LOWER_BOUND
Indicates whether a tight lower bound should be calculated.
double RUNTIME_OF_LOWER_BOUND
Time limit for the tight lower bound.
Solution solve(double relGap=Settings::ILP_RELATIVE_GAP, double timLim=Settings::MAX_RUNTIME) const
ILP solver optimizes the energy consumption of the robotic cell until a stop criterion is reached...
std::vector< std::string > errorMessages() const
It returns error message(s) describing why the solution is invalid.
uint32_t MAX_ELITE_SOLUTIONS
The number of top solutions maintained by the heuristic.
bool VERBOSE
Boolean flag determining verbosity of the program.
uint32_t NUMBER_OF_THREADS
Maximal number of threads to be used.
bool checkAll()
It calls the private member methods to verify the solution.
Thrown if the dataset file contains ill-specified robotic cells.
The file defines extended exceptions for the better error handling in the program.
An exact solver for the energy optimization problem.
Solver-independent interface for solving Integer Linear Programming problems.
Exception is thrown if a method is given invalid parameters or a user provides invalid program argume...
State status
Enum specifying whether the solution is optimal, feasible, or infeasible...
#define DEFAULT_USE_HEURISTICS
It specifies whether the heuristic algorithm should be preferred by default.
void writeBriefResultToCsvFile(const std::string &instanceName, const std::string &pathToFile, const Solution &s)
It writes the solution to the file in the same format as writeBriefResultToStream function...
static double lowerBoundOnEnergy(const std::vector< Robot * > &robots, const PrecalculatedMapping &m)
A tight lower bound on the energy consumption.
std::string solverIdentification()
Returns an identification of the used solver, e.g. 'Gurobi 6.0.4'.
bool processArg(int &i, int argc, char *argv[], const string &fullName, const string &shortName, bool *toWrite=nullptr)
It processes the arguments without parameters.
A parallel hybrid heuristic solving the energy optimization problem of robotic cells.
It declares the namespace for program settings.
A parallel heuristic for the energy optimization of robotic cells.
void printProgramHeader()
It prints a brief description of the program including the authors, license, ILP solver, and version.
string RESULTS_DIRECTORY
If not empty, then the optimization results will be written to this directory.
void writeSolutionToCsvFile(const string &file, const Solution &s, const PrecalculatedMapping &mapper)
It writes the solution to a csv file, the header is 'activity id, start time, duration, type, point, power saving mode, movement, energy'.
uint32_t MIN_ITERS_PER_TUPLE
The minimal number of optimization iterations per each tuple.
A representation of the solution that is algorithm independent.
double lowerBound
Lower bound on energy, i.e. there is not a solution consuming less energy than this number...
#define DEFAULT_USE_EXACT_ALGORITHM
It specifies whether the exact algorithm should be preferred by default.
The file declares a class responsible for checking of solutions.
void writeBriefResultToStream(std::ostream &OUT, const string &instanceName, const Solution &s)
It prints the solution as follows: 'instance name (state, runtime s): energy'.
The robotic cell corresponds to an instance of this class.
The structure contains the maps for fast searching in the robotic cell.
void readInstances()
It processes the dataset specified in Settings::DATASET_FILE.
bool getArgument(int &i, int argc, char *argv[], const string &fullName, const string &shortName, string &writeArgument)
It processes the arguments with one parameter.
RoboticLineSolverILP class, declared in this file, addresses the energy optimization problem of robot...
T parsePositiveNumber(const string &number)
double MAX_RUNTIME
Maximal run time of the solver.
bool USE_HEURISTICS
The variable indicates whether the heuristic should be used.