00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef OR_TOOLS_EXAMPLES_JOBSHOP_H_
00034 #define OR_TOOLS_EXAMPLES_JOBSHOP_H_
00035
00036 #include <cstdio>
00037 #include <cstdlib>
00038
00039 #include "base/integral_types.h"
00040 #include "base/logging.h"
00041 #include "base/stringprintf.h"
00042 #include "base/strtoint.h"
00043 #include "base/file.h"
00044 #include "base/filelinereader.h"
00045 #include "base/split.h"
00046
00047 namespace operations_research {
00048
00049
00050
00051
00052 class JobShopData {
00053 public:
00054
00055 struct Task {
00056 Task(int j, int m, int d) : job_id(j), machine_id(m), duration(d) {}
00057 int job_id;
00058 int machine_id;
00059 int duration;
00060 };
00061
00062 enum ProblemType {
00063 UNDEFINED,
00064 JSSP,
00065 TAILLARD
00066 };
00067
00068 enum TaillardState {
00069 START,
00070 JOBS_READ,
00071 MACHINES_READ,
00072 SEED_READ,
00073 JOB_ID_READ,
00074 JOB_LENGTH_READ,
00075 JOB_READ
00076 };
00077
00078 JobShopData()
00079 : name_(""),
00080 machine_count_(0),
00081 job_count_(0),
00082 horizon_(0),
00083 current_job_index_(0),
00084 problem_type_(UNDEFINED),
00085 taillard_state_(START) {}
00086
00087 ~JobShopData() {}
00088
00089
00090
00091
00092
00093 void Load(const string& filename) {
00094 FileLineReader reader(filename.c_str());
00095 reader.set_line_callback(NewPermanentCallback(
00096 this,
00097 &JobShopData::ProcessNewLine));
00098 reader.Reload();
00099 if (!reader.loaded_successfully()) {
00100 LOG(ERROR) << "Could not open jobshop file";
00101 }
00102 }
00103
00104
00105 int machine_count() const { return machine_count_; }
00106
00107
00108 int job_count() const { return job_count_; }
00109
00110
00111 const string& name() const { return name_; }
00112
00113
00114
00115 int horizon() const { return horizon_; }
00116
00117
00118 const std::vector<Task>& TasksOfJob(int job_id) const {
00119 return all_tasks_[job_id];
00120 }
00121
00122 private:
00123 void ProcessNewLine(char* const line) {
00124
00125 static const char kWordDelimiters[] = " ";
00126 std::vector<string> words;
00127 SplitStringUsing(line, kWordDelimiters, &words);
00128 switch (problem_type_) {
00129 case UNDEFINED: {
00130 if (words.size() == 2 && words[0] == "instance") {
00131 problem_type_ = JSSP;
00132 LOG(INFO) << "Reading jssp instance " << words[1];
00133 name_ = words[1];
00134 } else if (words.size() == 1 && atoi32(words[0]) > 0) {
00135 problem_type_ = TAILLARD;
00136 taillard_state_ = JOBS_READ;
00137 job_count_ = atoi32(words[0]);
00138 CHECK_GT(job_count_, 0);
00139 all_tasks_.resize(job_count_);
00140 }
00141 break;
00142 }
00143 case JSSP: {
00144 if (words.size() == 2) {
00145 job_count_ = atoi32(words[0]);
00146 machine_count_ = atoi32(words[1]);
00147 CHECK_GT(machine_count_, 0);
00148 CHECK_GT(job_count_, 0);
00149 LOG(INFO) << machine_count_ << " machines and "
00150 << job_count_ << " jobs";
00151 all_tasks_.resize(job_count_);
00152 }
00153
00154 if (words.size() > 2 && machine_count_ != 0) {
00155 CHECK_EQ(words.size(), machine_count_ * 2);
00156 for (int i = 0; i < machine_count_; ++i) {
00157 const int machine_id = atoi32(words[2 * i]);
00158 const int duration = atoi32(words[2 * i + 1]);
00159 AddTask(current_job_index_, machine_id, duration);
00160 }
00161 current_job_index_++;
00162 }
00163 break;
00164 }
00165 case TAILLARD: {
00166 switch (taillard_state_) {
00167 case START: {
00168 LOG(FATAL) << "Should not be here";
00169 break;
00170 }
00171 case JOBS_READ: {
00172 CHECK_EQ(1, words.size());
00173 machine_count_ = atoi32(words[0]);
00174 CHECK_GT(machine_count_, 0);
00175 taillard_state_ = MACHINES_READ;
00176 break;
00177 }
00178 case MACHINES_READ: {
00179 CHECK_EQ(1, words.size());
00180 const int seed = atoi32(words[0]);
00181 LOG(INFO) << "Taillard instance with " << job_count_
00182 << " jobs, and " << machine_count_
00183 << " machines, generated with a seed of " << seed;
00184 taillard_state_ = SEED_READ;
00185 break;
00186 }
00187 case SEED_READ:
00188 case JOB_READ: {
00189 CHECK_EQ(1, words.size());
00190 current_job_index_ = atoi32(words[0]);
00191 taillard_state_ = JOB_ID_READ;
00192 break;
00193 }
00194 case JOB_ID_READ: {
00195 CHECK_EQ(1, words.size());
00196 taillard_state_ = JOB_LENGTH_READ;
00197 break;
00198 }
00199 case JOB_LENGTH_READ: {
00200 CHECK_EQ(machine_count_, words.size());
00201 for (int i = 0; i < machine_count_; ++i) {
00202 const int duration = atoi32(words[i]);
00203 AddTask(current_job_index_, i, duration);
00204 }
00205 taillard_state_ = JOB_READ;
00206 break;
00207 }
00208 }
00209 break;
00210 }
00211 }
00212 }
00213
00214 void AddTask(int job_id, int machine_id, int duration) {
00215 all_tasks_[job_id].push_back(Task(job_id, machine_id, duration));
00216 horizon_ += duration;
00217 }
00218
00219 string name_;
00220 int machine_count_;
00221 int job_count_;
00222 int horizon_;
00223 std::vector<std::vector<Task> > all_tasks_;
00224 int current_job_index_;
00225 ProblemType problem_type_;
00226 TaillardState taillard_state_;
00227 };
00228 }
00229
00230 #endif // OR_TOOLS_EXAMPLES_JOBSHOP_H_