📄 rrproj_prob.cpp
字号:
//======================================================================
// rrproj_prob.cpp - function bodies for rrproj_prob.h
//
// Copyright (c) 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/01/27 [BRM] began development
//
//----------------------------------------------------------------------
#include "rrproj_prob.h"
#include "rrproj_fctry.h"
#include <string.h>
#include <stdlib.h>
// #include <iostream> // for debugging
// #include <fstream>
// using namespace std;
//======================================================================
// local functions
//
//----------------------------------------------------------------------
// save the solution from a solver-problem in a problem-problem
void save_solution (rppProblem *rpp_problem, rpsProblem *rps_problem) {
rpsDecision * rd;
rpsOption * ro;
rpsPosDay * rpd;
rpsPosition * rp;
rpsEmployee * re;
long syyyymmdd;
aipHHOption * shhopt;
aipHHOptionItr oitr;
rpsDecisionItr ditr = rps_problem->decision_iterator();
for ( rd=ditr.first(); rd; rd=ditr.next() ) {
oitr = rd->bsf_opt_iterator();
for ( shhopt=oitr.first(); shhopt; shhopt=oitr.next() ) {
ro = (rpsOption*)shhopt;
rpd = ro->bsf_posday();
rp = rpd->pos();
re = ro->emp();
syyyymmdd = rpd->yyyymmdd();
rpp_problem->add_posdayemp ( rpd->proj_id(), rp->pos_id(),
syyyymmdd, re->emp_id() );
} // end of loop through options in best-so-far solution
} // end of loop through decisions
}
//======================================================================
// rppProblem
//
//----------------------------------------------------------------------
// Constructor
rppProblem::rppProblem () {
m_start_yyyymmdd = 19000101;
m_end_yyyymmdd = 19000101;
m_num_tries = 0;
m_logger = new aipStringLogger(Max_Log_Len);
if (m_logger) set_logger(m_logger);
m_posdays = new aipPandemonium;
m_empdows = new aipPandemonium;
m_empoffs = new aipPandemonium;
m_posemps = new aipPandemonium;
m_assignments = new aipPandemonium;
m_empdaypos = new aipPandemonium;
m_posdayemps = new aipPandemonium;
m_posdayemp_itr = 0; // managed by get_pos_day_emp()
}
//----------------------------------------------------------------------
// Destructor
rppProblem::~rppProblem () {
if (m_logger) delete m_logger;
if (m_posdays) delete m_posdays;
if (m_empdows) delete m_empdows;
if (m_empoffs) delete m_empoffs;
if (m_posemps) delete m_posemps;
if (m_assignments) delete m_assignments;
if (m_empdaypos) delete m_empdaypos;
if (m_posdayemps) delete m_posdayemps;
if (m_posdayemp_itr) delete m_posdayemp_itr;
}
//----------------------------------------------------------------------
// Return true if the problem is valid after construction.
// Log problems.
int rppProblem::is_valid () {
if ( ! m_posdays ) {
log("Error creating m_posdays");
return 0;
}
if ( ! m_empdows ) {
log("Error creating m_empdows");
return 0;
}
if ( ! m_empoffs ) {
log("Error creating m_empoffs");
return 0;
}
if ( ! m_posemps ) {
log("Error creating m_posemps");
return 0;
}
if ( ! m_assignments ) {
log("Error creating m_assignments");
return 0;
}
if ( ! m_empdaypos ) {
log("Error creating m_empdaypos");
return 0;
}
if ( ! m_posdayemps ) {
log("Error creating m_posdayemps");
return 0;
}
if (m_posdayemp_itr != 0) {
log("m_posdayemp_itr should be zero");
return 0;
}
return 1;
}
//----------------------------------------------------------------------
// Read the input data from a file; return 1 (true) on success
int rppProblem::read (const char *filename) {
FILE *ifp = fopen (filename, "r");
if (!ifp) {
log("Error opening input file: ");
log(filename);
return 0;
}
int istatus = 1;
int rstatus;
char buf[201], record_type[31];
const char *p;
while (istatus) {
rstatus = fgets(buf,200,ifp) != 0;
if (!rstatus) break;
buf[200] = '\0'; // make sure it is terminated
char *q = buf;
int anything = 0;
while (*q) { // terminate at the newline
if ( (*q >= 'A' && *q <= 'Z') ||
(*q >= 'a' && *q <= 'z') ||
(*q >= '0' && *q <= '9') ) {
anything = 1; // has some data
} else if (*q == '\n') {
*q = '\0';
break;
}
q++;
}
if (buf[0] == '#' || !anything) continue;
p = buf;
if (*p) p = aip_get_str(p, 30, record_type, '|');
if (!p) continue;
if ( strcmp (record_type, "rppProblem") == 0) {
istatus = read_str(p);
} else if ( strcmp (record_type, "rppPosDay") == 0) {
rppPosDay *pd = new rppPosDay;
if (!pd) { log("new pd failure"); return 0; }
istatus = pd->read_str(p);
if (istatus && m_posdays) {
m_posdays->add(pd);
} else {
delete pd;
}
} else if ( strcmp (record_type, "rppPosEmp") == 0) {
rppPosEmp *pqe = new rppPosEmp;
if (!pqe) { log("new pqe failure"); return 0; }
istatus = pqe->read_str(p);
if (istatus && m_posemps) {
m_posemps->add(pqe);
} else {
delete pqe;
}
} else if ( strcmp (record_type, "rppEmpDow") == 0) {
rppEmpDow *edow = new rppEmpDow;
if (!edow) { log("new edow failure"); return 0; }
istatus = edow->read_str(p);
if (istatus && m_empdows) {
m_empdows->add(edow);
} else {
delete edow;
}
} else if ( strcmp (record_type, "rppEmpOff") == 0) {
rppEmpOff *eoff = new rppEmpOff;
if (!eoff) { log("new eoff failure"); return 0; }
istatus = eoff->read_str(p);
if (istatus && m_empoffs) {
m_empoffs->add(eoff);
} else {
delete eoff;
}
} else if ( strcmp (record_type, "rppAssignment") == 0) {
rppAssignment *assg = new rppAssignment;
if (!assg) { log("new assg failure"); return 0; }
istatus = assg->read_str(p);
if (istatus && m_assignments) {
m_assignments->add(assg);
} else {
delete assg;
}
} else if ( strcmp (record_type, "rppEmpDayPos") == 0) {
rppEmpDayPos *edp = new rppEmpDayPos;
if (!edp) { log("new edp failure"); return 0; }
istatus = edp->read_str(p);
if (istatus && m_empdaypos) {
m_empdaypos->add(edp);
} else {
delete edp;
}
} else {
log("Read - bad record_type: ");
log(record_type);
return 0;
}
} // end of loop through records in input file
if (!istatus) {
log(" Error reading input: ");
log(buf);
}
fclose (ifp);
return istatus;
}
//----------------------------------------------------------------------
// Read data from string to setup this object
int rppProblem::read_str (const char *x) {
m_start_yyyymmdd = m_end_yyyymmdd = 19000101;
m_week_start_day = m_num_tries = 0;
char s_start_date[31], s_end_date[31];
if (x && *x) x = aip_get_str(x, 30, s_start_date, '|');
if (x && *x) x = aip_get_str(x, 30, s_end_date, '|');
if (x && *x) x = aip_get_val(x, 10, &m_week_start_day, '|');
if (x && *x) x = aip_get_val(x, 10, &m_num_tries, '|');
if (!x) return 0;
rppFileDate x_start_date(s_start_date);
if ( !x_start_date.is_valid() ) {
log("problem start-date must be set and valid");
return 0;
}
m_start_yyyymmdd = x_start_date.long_date();
if (m_start_yyyymmdd < 19000101 || m_start_yyyymmdd > 21000101) {
log("problem start-date must be between 1900 and 2100");
return 0;
}
rppFileDate x_end_date(s_end_date);
if ( !x_end_date.is_valid() ) {
log("problem end-date must be set and valid");
return 0;
}
m_end_yyyymmdd = x_end_date.long_date();
if (m_end_yyyymmdd < 19000101 || m_end_yyyymmdd > 21000101) {
log("problem end-date must be between 1900 and 2100");
return 0;
}
if (m_end_yyyymmdd < m_start_yyyymmdd) {
log("problem end-date must be after problem start-date");
return 0;
}
if (m_week_start_day < 1 || m_week_start_day > 7) {
log("week_start_day must be between 1 and 7");
return 0;
}
if (m_num_tries < 1 || m_num_tries > 100000) {
log("num_tries must be between 1 and 100000");
return 0;
}
return 1;
}
//----------------------------------------------------------------------
// Write the data in this object to the string; return 0 on failure
int rppProblem::write_str (char *x) const {
rppFileDate x_start_date(m_start_yyyymmdd);
if ( !x_start_date.is_valid() ) return 0;
rppFileDate x_end_date(m_end_yyyymmdd);
if ( !x_end_date.is_valid() ) return 0;
int n = sprintf (x, "rppProblem|%s|%s|%ld|%ld",
x_start_date.file_date(),
x_end_date.file_date(),
m_week_start_day,
m_num_tries);
return (n ? 1 : 0);
}
//----------------------------------------------------------------------
// Write the input data to a file; return 1 (true) on success
int rppProblem::write_input (const char *filename) {
FILE *ofp = fopen (filename, "w");
if (!ofp) {
log("Error opening export file");
return 0;
}
int n = 1;
if (n) n = fprintf (ofp, "# rrproj export file\n");
if (n) n = fprintf (ofp, "# \n");
char rec[1001];
if (n) n = write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec); // rppProblem record
rppPosDayItr pditr = posday_iterator();
rppPosDay *pd;
for (pd = pditr.first(); pd && n; pd = pditr.next()) {
if (n) n = pd->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
rppPosEmpItr peitr = posemp_iterator();
rppPosEmp *pe;
for (pe = peitr.first(); pe && n; pe = peitr.next()) {
if (n) n = pe->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
rppEmpDowItr edowitr = empdow_iterator();
rppEmpDow *edow;
for (edow = edowitr.first(); edow && n; edow = edowitr.next()) {
if (n) n = edow->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
rppEmpOffItr eoffitr = empoff_iterator();
rppEmpOff *eoff;
for (eoff = eoffitr.first(); eoff && n; eoff = eoffitr.next()) {
if (n) n = eoff->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
rppAssgnItr assgnitr = assgn_iterator();
rppAssignment *assgn;
for (assgn = assgnitr.first(); assgn && n; assgn = assgnitr.next()) {
if (n) n = assgn->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
rppEmpDayPosItr edpitr = empdaypos_iterator();
rppEmpDayPos *edp;
for (edp = edpitr.first(); edp && n; edp = edpitr.next()) {
if (n) n = edp->write_str(rec);
if (n) n = fprintf (ofp, "%s\n", rec);
}
fclose(ofp);
if (!n) {
log("Error writing export file");
return 0;
}
return 1;
}
//----------------------------------------------------------------------
// Return a pointer to a description of the results of trying to
// to solve this problem.
const char * rppProblem::get_rslt_desc () const {
return m_logger->get();
}
//----------------------------------------------------------------------
// Add a Position-Day
void rppProblem::add_pos_day (long a_proj_id, long a_pos_id,
long a_yyyymmdd, long a_num_emps_req) {
rppPosDay *x = new rppPosDay (a_proj_id, a_pos_id,
a_yyyymmdd, a_num_emps_req);
if (x) m_posdays->add(x);
}
//----------------------------------------------------------------------
// Add an Employee-Day-of-week
void rppProblem::add_emp_dow (long a_emp_id, long a_dow,
long a_start_hhmm, long a_end_hhmm) {
rppEmpDow *x = new rppEmpDow (a_emp_id, a_dow,
a_start_hhmm, a_end_hhmm);
if (x) m_empdows->add(x);
}
//----------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -