Files
ortools-clone/examples/cpp/jobshop_earlytardy.h
lperron@google.com a2f8554a6d ported examples
2014-07-09 11:09:30 +00:00

198 lines
7.0 KiB
C++

// Copyright 2010-2014 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This model implements a simple jobshop problem with
// earlyness-tardiness costs.
//
// A earlyness-tardinessjobshop is a standard scheduling problem where
// you must schedule a set of jobs on a set of machines. Each job is
// a sequence of tasks (a task can only start when the preceding task
// finished), each of which occupies a single specific machine during
// a specific duration. Therefore, a job is a sequence of pairs
// (machine id, duration), along with a release data (minimum start
// date of the first task of the job, and due data (end time of the
// last job) with a tardiness linear penalty.
// The objective is to minimize the sum of early-tardy penalties for each job.
//
// This will be modelled by sets of intervals variables (see class
// IntervalVar in constraint_solver/constraint_solver.h), one per
// task, representing the [start_time, end_time] of the task. Tasks
// in the same job will be linked by precedence constraints. Tasks on
// the same machine will be covered by Sequence constraints.
#ifndef OR_TOOLS_EXAMPLES_JOBSHOP_EARLYTARDY_H_
#define OR_TOOLS_EXAMPLES_JOBSHOP_EARLYTARDY_H_
#include <cstdio>
#include <cstdlib>
#include <vector>
#include "base/integral_types.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/strtoint.h"
#include "base/file.h"
#include "base/filelinereader.h"
#include "base/random.h"
#include "base/split.h"
namespace operations_research {
struct Task {
Task(int j, int m, int d) : job_id(j), machine_id(m), duration(d) {}
int job_id;
int machine_id;
int duration;
};
struct Job {
Job(int r, int d, int ew, int tw)
: release_date(r),
due_date(d),
early_cost(ew),
tardy_cost(tw) {}
int release_date;
int due_date;
int early_cost;
int tardy_cost;
std::vector<Task> all_tasks;
};
class EtJobShopData {
public:
EtJobShopData()
: machine_count_(0),
job_count_(0),
horizon_(0) {}
~EtJobShopData() {}
void LoadJetFile(const std::string& filename) {
LOG(INFO) << "Reading jet file " << filename;
name_ = StringPrintf("JetData(%s)", filename.c_str());
FileLineReader reader(filename.c_str());
reader.set_line_callback(NewPermanentCallback(
this,
&EtJobShopData::ProcessNewJetLine));
reader.Reload();
if (!reader.loaded_successfully()) {
LOG(ERROR) << "Could not open jobshop file";
}
}
void GenerateRandomData(int machine_count,
int job_count,
int max_release_date,
int max_early_cost,
int max_tardy_cost,
int max_duration,
int scale_factor,
int seed) {
name_ = StringPrintf("EtJobshop(m%d-j%d-mrd%d-mew%d-mtw%d-md%d-sf%d-s%d)",
machine_count,
job_count,
max_release_date,
max_early_cost,
max_tardy_cost,
max_duration,
scale_factor,
seed);
LOG(INFO) << "Generating random problem " << name_;
ACMRandom random(seed);
machine_count_ = machine_count;
job_count_ = job_count;
for (int j = 0; j < job_count_; ++j) {
const int release_date = random.Uniform(max_release_date);
int sum_of_durations = max_release_date;
all_jobs_.push_back(Job(release_date,
0, // due date, to be filled later.
random.Uniform(max_early_cost),
random.Uniform(max_tardy_cost)));
for (int m = 0; m < machine_count_; ++m) {
const int duration = random.Uniform(max_duration);
all_jobs_.back().all_tasks.push_back(Task(j, m, duration));
sum_of_durations += duration;
}
all_jobs_.back().due_date = sum_of_durations * scale_factor / 100;
horizon_ += all_jobs_.back().due_date;
// Scramble jobs.
for (int m = 0; m < machine_count_; ++m) {
Task t = all_jobs_.back().all_tasks[m];
const int target = random.Uniform(machine_count_);
all_jobs_.back().all_tasks[m] = all_jobs_.back().all_tasks[target];
all_jobs_.back().all_tasks[target] = t;
}
}
}
// The number of machines in the jobshop.
int machine_count() const { return machine_count_; }
// The number of jobs in the jobshop.
int job_count() const { return job_count_; }
// The name of the jobshop instance.
const std::string& name() const { return name_; }
// The horizon of the workshop (the sum of all durations), which is
// a trivial upper bound of the optimal make_span.
int horizon() const { return horizon_; }
// Returns the tasks of a job, ordered by precedence.
const Job& GetJob(int job_id) const {
return all_jobs_[job_id];
}
private:
void ProcessNewJetLine(char* const line) {
// TODO(user): more robust logic to support single-task jobs.
static const char kWordDelimiters[] = " ";
std::vector<std::string> words;
SplitStringUsing(line, kWordDelimiters, &words);
if (words.size() == 2) {
job_count_ = atoi32(words[0]);
machine_count_ = atoi32(words[1]);
CHECK_GT(machine_count_, 0);
CHECK_GT(job_count_, 0);
LOG(INFO) << machine_count_ << " - machines and "
<< job_count_ << " jobs";
} else if (words.size() > 2 && machine_count_ != 0) {
const int job_id = all_jobs_.size();
CHECK_EQ(words.size(), machine_count_ * 2 + 3);
const int due_date = atoi32(words[2 * machine_count_]);
const int early_cost = atoi32(words[2 * machine_count_ + 1]);
const int late_cost = atoi32(words[2 * machine_count_ + 2]);
LOG(INFO) << "Add job with due date = " << due_date
<< ", early cost = " << early_cost
<< ", and late cost = " << late_cost;
all_jobs_.push_back(Job(0, due_date, early_cost, late_cost));
for (int i = 0; i < machine_count_; ++i) {
const int machine_id = atoi32(words[2 * i]);
const int duration = atoi32(words[2 * i + 1]);
all_jobs_.back().all_tasks.push_back(
Task(job_id, machine_id, duration));
horizon_ += duration;
}
}
}
std::string name_;
int machine_count_;
int job_count_;
int horizon_;
std::vector<Job> all_jobs_;
};
} // namespace operations_research
#endif // OR_TOOLS_EXAMPLES_JOBSHOP_EARLYTARDY_H_