📄 rrproj_prob.h
字号:
//**********************************************************************
// rrproj_prob.h - rrproj Problem
//
// An rrproj problem is the problem of assigning people and/or
// equipment to projects. An application includes this file to
// define and solve this type of problem.
//
// Copyright (c) 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/01/19 [BRM] began development
//
//----------------------------------------------------------------------
// Required Source Files
//
// To use the solve() function, the following files must be compiled:
// rrproj_prob.cpp (with rrproj_prob.h)
// rrproj_solv.cpp (with rrproj_solv.h)
// rrproj_fctry.cpp (with rrproj_fctry.h)
// aipReqRes.cpp (with aipReqRes.h)
// aipHighHope.cpp (with aipHighHope.h)
// aipProblem.cpp (with aipProblem.h)
// aipDecision.cpp (with aipDecision.h)
// aipEmotion.cpp (with aipEmotion.h)
// aipPandemonium.cpp (with aipPandemonium.h)
// aipBase.cpp (with aipBase.h)
// aipGood.cpp (with aipGood.h)
//
//----------------------------------------------------------------------
// Data relationships in a rrproj Problem
//
// If A is joined to B by a line, and A is higher than B in the
// diagram, there is a one-to-many relationship between A and B.
//
// <xyz> angle brackets indicate output solution data
// {abc} curly braces indicate virtual datasets
//
// [Problem]____[ProbWriter]
// _________| | |__________
// | | |
// {Position} {Project} | _{Employee}__________
// | | | | | | | | | | |_______ |
// | | | [Pos_Day] | | | | | | |
// | | | | | | | | [Emp_Dow] | |
// | | | <Pos_Day_Emp>____| | | | |
// | | | | [Emp_Off] | |
// | | |__________[Pos_Emp]_______| | |
// | | | |
// | |___________[Emp_Day_Pos]_____________________| |
// | |
// |_______________[Assignment]________________________|
//
//
//
// Pos_Day_Emp is the normalized output solution data.
// Emp_Day_Pos is for (optional) historic data.
// Other entities define the problem to be solved.
//
// If the problem is configured with an rppProbWriteWeek1
// for a [ProbWriter], the output solution data is
// denormalized into weeks:
//
// [Problem]____[rppProbWriteWeek1]
// _________| | |__________
// | | |
// {Position} {Project} | {Employee}
// | | | | |
// [Pos_Day] <<Proj_Week>> | |
// | | | |
// | <<Proj_Week_Emp>>_| |
// | | |
// <Pos_Day_Emp>___<Proj_Week_Emp_Day>____|
//
//
// <Pos_Day_Emp> is the normalized solution data
// <Proj_Week_Emp_Day> is reordered noralized solution data
// <<Proj_Week>> and <<Proj_Week_Emp>> are the solution data
// by project-week: master and detail data
// which are created from <Proj_Week_Emp_Day>
//
// The data is stored in the order indicated by the name.
// Input data can be provided in any order.
//
// In this software, Problem, Project, Position and Employee are
// virtual datasets. They would be in a logical data model, but
// they are not datasets in this software.
//
//----------------------------------------------------------------------
// Optionally providing historic Emp_Day_Pos data
//
// If an application expects the solver to consider data prior to
// the start of the problem, historic Emp_Day_Pos data must
// be supplied before the problem solve() function is called.
//
// Adding Emp_Day_Pos data is optional, and it may be added for
// just the employees for which it matters.
//
// Examples requiring (some) historic data:
// - It may be desirable to rotate through (some) employees
// (ex. part-time employees, contractors, volunteers).
// - It is desirable, for an employee who worked a position yesterday
// to work the same position today (if the employee works today).
//
// Currently, the minimum desirable amount of historic Emp_Day_Pos
// data is the last day worked (before the first day of the problem)
// for each employee. Employees may be omitted if they worked
// in the last couple of days before the problem.
//
// The solver does not get historic Emp_Day_Pos data; this data is
// used to set attributes in entities that are part of the solver.
//
// The output solution data does not include the historic data.
//
//----------------------------------------------------------------------
// Using this software in an application
//
// The application will create an instance of class rppProblem
// and call (some of) its public functions:
// either:
// - call functions to add the problem data to the rppProblem
// or:
// - call the problem read() function
// call solve() to solve the problem
// either:
// - call get_rslt_desc()
// - call get_pos_day_emp () to get the solution
// or:
// - create an instance of a subclass of rppProbWrite
// - call the write() function of the instance
// and then delete the instance of rrpProblem if required.
//
// The char* pointer returned from rrpProblem::get_rslt_desc()
// must not be used after the rrpProblem is deleted.
//
// A subclass of rppProbWrite can denormalize the data in a
// particular way - it customizes the solution data file
// for one or more applications.
//
// The application developer does not have to know or care about:
// - how rrpProblem stores data
// - how the public functions work
// - anything about any of the other classes in this file
//
//----------------------------------------------------------------------
// What rppProblem::solve() does (optional information)
//
// When solve() is called, it:
// - creates an instance of rpsFactory
// - uses the factory with the problem data to build a solver
// - deletes the factory
// - calls the solver solve() function
// - copies the solution data to the problem data
// - deletes the solver
//
//----------------------------------------------------------------------
#ifndef rrproj_prob_h_guard
#define rrproj_prob_h_guard
#include "aipPandemonium.h"
#include "aipTime.h"
#include <stdio.h>
//----------------------------------------------------------------------
// Local Constants
const long Max_Str_Key_Len = 30;
const long File_Date_Len = 10; // "yyyy-mm-dd"
const long File_Time_Len = 5; // "hh:mm"
const long Max_Log_Len = 300;
const long Max_File_Name = 100;
//----------------------------------------------------------------------
// Classes. Sub-classing is shown by indentation.
//
// class aipG is a typedef for aipGoodness.
//
// A class is a subclass of aipDemon (a list element) so that
// a pointer to it can be added to pandemoniums (lists).
// class aipBase; ( in aipBase.h )
class rppProblem; // rrproj problem
// class aipDemon; ( in aipPandemonium.h )
class rppPosDay; // position on a day
class rppEmpDow; // days-of-week the emp can work
class rppEmpOff; // days an emp cannot work
class rppPosEmp; // pos and an emp that can work it
class rppAssignment; // an emp pre-assigned to a pos
class rppEmpDayPos; // historic solution data
class rppPosDayEmp; // normalized solution data
class rppProjWeekEmpDay; // re-ordered normalized solution
class rppProjWeek; // output master for a week
class rppProjWeekEmp; // output detail for a week
class rppProbWrite; // problem solution-writer
class rppProbWriteWeek1; // week-based writer number 1
// class aipLogger; ( in aipBase.h )
// class aipStringLogger; ( in aipBase.h )
// class aipDemonItr; ( in aipPandemonium.h )
class rppPosDayItr; // position-day iterator
class rppEmpItr; // employee iterator
class rppEmpDowItr; // emp-off iterator
class rppEmpOffItr; // emp-off iterator
class rppPosEmpItr; // position-employee-pair iterator
class rppAssgnItr; // assignment iterator
class rppEmpDayPosItr; // historic emp-day-pos iterator
class rppPosDayEmpItr; // normalized-output iterator
class rppProjWeekEmpDayItr; // re-ordered output iterator
class rppProjWeekItr; // output-master iterator
class rppProjWeekEmpItr; // output-detail iterator
class rppFileDate; // read/write dates in a file
class rppFileTime; // read/write times in a file
//======================================================================
// rppProblem - an rrproj problem as defined by the application
class rppProblem : public aipBase {
long m_start_yyyymmdd;
long m_end_yyyymmdd;
long m_week_start_day; // 0=Sunday
long m_num_tries;
aipStringLogger * m_logger; // for calls to log()
aipPandemonium * m_posdays; // problem data
aipPandemonium * m_empdows;
aipPandemonium * m_empoffs;
aipPandemonium * m_posemps;
aipPandemonium * m_assignments;
aipPandemonium * m_empdaypos; // historic solution data
aipPandemonium * m_posdayemps; // output solution data
rppPosDayEmpItr * m_posdayemp_itr; // for get_pos_day_emp()
public:
// Functions Used by the Application
rppProblem ();
virtual ~rppProblem ();
int is_valid (); // returns true if valid
virtual int read (const char *filename); // return 0 on failure
// for problem data record - returns 0 on failure
virtual int read_str (const char *x);
virtual int write_str (char *x) const;
virtual int write_input (const char *filename);
const char * get_rslt_desc () const;
// or i/o by calls
void add_pos_day (long a_proj_id, long a_pos_id,
long a_yyyymmdd, long a_num_emps_req);
void add_emp_dow (long a_emp_id, long a_dow,
long a_start_hhmm, long a_end_hhmm);
void add_emp_off (long a_emp_id,
long a_start_yyyymmdd, long a_end_yyyymmdd);
void add_pos_emp (long a_pos_id, long a_emp_id);
void add_assignment (long a_proj_id, long a_pos_id, long a_emp_id,
long a_start_yyyymmdd, long a_end_yyyymmdd);
void add_empdaypos (long a_emp_id, long a_yyyymmdd, // historic
long a_proj_id, long a_pos_id);
void add_posdayemp (long a_proj_id, long a_pos_id, // solution
long a_yyyymmdd, long a_emp_id);
virtual int solve(); // returns 1 (true) on success
// get solution, returns 0 after last
int get_pos_day_emp (long *a_proj_id, long *a_pos_id,
long *a_yyyymmdd, long *a_emp_id);
// Functions Used Internally
long start_yyyymmdd () const { return m_start_yyyymmdd; }
long end_yyyymmdd () const { return m_end_yyyymmdd; }
long week_start_day () const { return m_week_start_day; }
long num_tries () const { return m_num_tries; }
rppPosDayItr posday_iterator () const; // get an iterator
rppEmpDowItr empdow_iterator () const;
rppEmpOffItr empoff_iterator () const;
rppPosEmpItr posemp_iterator () const;
rppAssgnItr assgn_iterator () const;
rppEmpDayPosItr empdaypos_iterator () const;
rppPosDayEmpItr posdayemp_iterator () const;
};
//======================================================================
// rppPosDay - Position on a Day that requires Employees
class rppPosDay : public aipDemon {
long m_proj_id;
long m_pos_id;
long m_yyyymmdd;
long m_num_emps_req; // employees required
long m_start_hhmm; // 1430 is 2:30 pm
long m_end_hhmm;
public:
rppPosDay () {}
rppPosDay (long a_proj_id, long a_pos_id,
long a_yyyymmdd, long a_num_emps_req,
long a_start_hhmm =0, long a_end_hhmm =0);
virtual ~rppPosDay ();
virtual long num_keys (void) const { return 3; }
virtual long key1 (void) const { return m_proj_id; }
virtual long key2 (void) const { return m_pos_id; }
virtual long key3 (void) const { return m_yyyymmdd; }
// returns 0 on failure
virtual int read_str (const char *x);
virtual int write_str (char *x) const;
long proj_id () const { return m_proj_id; }
long pos_id () const { return m_pos_id; }
long yyyymmdd () const { return m_yyyymmdd; }
long num_emps_req () const { return m_num_emps_req; }
long start_hhmm () const { return m_start_hhmm; }
long end_hhmm () const { return m_end_hhmm; }
};
//======================================================================
// rppEmpDow - Day-of-week on which the employee can work
class rppEmpDow : public aipDemon {
long m_emp_id;
long m_dow; // ex: 0=sun, 1=mon, 2=tue, etc.
long m_start_hhmm; // 1430 is 2:30 pm
long m_end_hhmm;
public:
rppEmpDow () {}
rppEmpDow (long a_emp_id, long a_dow,
long a_start_hhmm, long a_end_hhmm);
virtual ~rppEmpDow ();
virtual long num_keys (void) const { return 2; }
virtual long key1 (void) const { return m_emp_id; }
virtual long key2 (void) const { return m_dow; }
// returns 0 on failure
virtual int read_str (const char *x);
virtual int write_str (char *x) const;
long emp_id () const { return m_emp_id; }
long dow () const { return m_dow; }
long start_hhmm () const { return m_start_hhmm; }
long end_hhmm () const { return m_end_hhmm; }
};
//======================================================================
// rppEmpOff - Days on which the employee cannot work
class rppEmpOff : public aipDemon {
long m_emp_id;
long m_start_yyyymmdd;
long m_end_yyyymmdd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -