aiParts |
Free Open Source Artificial Intelligence C++ Parts |
|
Home Page Open Source Contact Us Free Downloads Releases and Credits Software Status License About rrproj assigning people and/or equipment to projects High-Hope Technique History of the AI View Source Files and how they are organized Making Programs Development Notes Using aiParts Your Application Support and Services |
aiParts Source File
//**********************************************************************
// rrproj_solv.cpp - function bodies for rrproj_solv.h
//
// Copyright (c) 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 07/11/21 [BRM] began development
//
//----------------------------------------------------------------------
#include "rrproj_solv.h"
#include <string.h>
#include <iostream>
using namespace std;
//======================================================================
// rpsProblem
//
//----------------------------------------------------------------------
// Constructor
rpsProblem::rpsProblem () {
aipTime tmp("Jan 1 1900");
m_start_day = m_end_day = tmp;
}
//----------------------------------------------------------------------
// Destructor
rpsProblem::~rpsProblem () {}
//----------------------------------------------------------------------
// add_position
void rpsProblem::add_position (rpsPosition *x) {
add_requirement(x);
}
//----------------------------------------------------------------------
// add_employee
void rpsProblem::add_employee (rpsEmployee *x) {
add_resource(x);
}
//----------------------------------------------------------------------
// set_day_range
void rpsProblem::set_day_range (long start_yyyymmdd,
long end_yyyymmdd) {
m_start_day = aipTime(start_yyyymmdd);
m_end_day = aipTime(end_yyyymmdd);
}
//----------------------------------------------------------------------
// position_iterator - return an iterator: positions in the problem
rpsPositionItr rpsProblem::position_iterator() const {
rpsPositionItr i(requirement_pandemonium());
return i;
}
//----------------------------------------------------------------------
// employee_iterator - return an iterator: employees in the problem
rpsEmployeeItr rpsProblem::employee_iterator() const {
rpsEmployeeItr i(resource_pandemonium());
return i;
}
//----------------------------------------------------------------------
// decision_iterator - return an iterator: decisions in the problem
rpsDecisionItr rpsProblem::decision_iterator() const {
rpsDecisionItr i(decision_pandemonium());
return i;
}
//----------------------------------------------------------------------
// take_msg
void rpsProblem::take_msg (aipMsg *mm) {
aiprrProblem::take_msg(mm);
}
//----------------------------------------------------------------------
// Note that a decision has decided or failed to decide
void rpsProblem::note_decide (aipHHDecision *dd, aipHHOption *oo) {
if (!dd) return;
aiprrProblem::note_decide (dd, oo);
rpsDecision *d = (rpsDecision*)dd;
rpsOption *o = (rpsOption*)oo;
if (should_log_options()) log_decide (d, o);
if (o) apply_emp_aspects (d, o);
}
//----------------------------------------------------------------------
// A decision has just chosen an option - apply some aspects to
// some other unchosen options (by changing their dynamic goodness).
// The aspects, here, are related to the employee of the chosen option.
void rpsProblem::apply_emp_aspects (rpsDecision *d1, rpsOption *o1) {
// regarding the emp, dcsn and chosen opt
rpsPosDay * pd1 = d1->posday();
rpsPosition * p1 = pd1->pos();
rpsEmpDay * ed1 = o1->empday();
rpsEmployee * e1 = ed1->emp();
// regarding other dcsns and opts for this emp
rpsDecision * d2;
rpsOption * o2;
rpsPosDay * pd2;
rpsEmpDay * ed2;
// good for an emp to work if has not worked for a while
// but now emp has worked
if ( e1->g_last_work() > aipNeutral) e1->reset_g_last_work();
rpsEmpDayItr editr = e1->empday_iterator(); // emp
for ( ed2 = editr.first(); ed2; ed2 = editr.next() ) { // empday
if (e1->g_last_work() == aipNeutral) {
long day_diff = ed2->day().days_since(pd1->day());
if ( day_diff < -1 || day_diff > 2 ) continue;
}
rpsOptItr oitr = ed2->opt_iterator();
for ( o2 = oitr.first(); o2; o2 = oitr.next() ) { // opt
if ( o2->is_chosen() ) continue;
if ( o2->g_opt().is_forbidden() ) continue;
d2 = (rpsDecision*)(o2->owner()); // dcsn
if ( d2->is_decided() ) continue;
pd2 = d2->posday(); // posday
// emp cannot work overlapping posdays
if ( pd2->end_time() > pd1->start_time() &&
pd2->start_time() < pd1->end_time() ) {
o2->set_g_dynamic(aipForbidden);
continue;
}
// good for an emp to work same pos as previous day
if ( pd2->pos()->pos_id() == p1->pos_id() &&
pd2->proj_id() == pd1->proj_id() &&
pd2->day().days_since(pd1->day()) == 1 ) {
o2->add_g_dynamic(aipGood);
}
} // end of loop through options in ed2
} // end of loop through empdays ed2 for the emp e1
}
//----------------------------------------------------------------------
// Write about a decision being decided if enable_log_options
// has been called
void rpsProblem::log_decide (rpsDecision *d, rpsOption *o) {
cout << "log: Decision for: "
<< " proj " << d->posday()->proj_id()
<< " pos " << d->posday()->pos_id()
<< " on " << d->posday()->yyyymmdd();
if (o) {
cout << " emp: " << o->emp()->emp_id()
<< " g: " << o->g_opt_cmp().numeric_value();
} else {
cout << " Failed";
}
cout << "\n";
}
//----------------------------------------------------------------------
// Write about the try to cout if enable_log_tries() has been called
void rpsProblem::log_this_try () {
aipHHSolveStat * ss = solve_stat();
long g_val = ss->g_usr_cur().numeric_value();
long g_val_bsf = ss->g_usr_bsf().numeric_value();
cout << "\n +++ A Try has ended - Goodness: " << g_val
<< " (Best-so-far: " << g_val_bsf << ")\n"
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
}
//======================================================================
// rpsDecision
//
//----------------------------------------------------------------------
// constructor
rpsDecision::rpsDecision (rpsPosDay *a_posday, long a_num_to_decide)
: aiprrDecision(a_posday,a_num_to_decide) {}
//----------------------------------------------------------------------
// destructor
rpsDecision::~rpsDecision() {}
//----------------------------------------------------------------------
// add_rps_option
void rpsDecision::add_rps_option (rpsOption *x) {
add_aiprr_option(x);
}
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsDecision::take_msg (aipMsg *mm) {
aiprrDecision::take_msg(mm);
// rpsMsg *m = (rpsMsg *)mm;
// if (m->typ() == HH_Starting_New_Try) {
// }
}
//======================================================================
// rpsOption - an employee working a position on a day
//
//----------------------------------------------------------------------
// constructor
rpsOption::rpsOption(rpsEmpDay *a_empday, aipG g_constant)
: aiprrOption(a_empday, g_constant) {}
//----------------------------------------------------------------------
// destructor
rpsOption::~rpsOption () {}
//----------------------------------------------------------------------
// return emp, pos, day
rpsEmployee * rpsOption::emp () const { return empday()->emp(); }
rpsPosition * rpsOption::pos () const { return posday()->pos(); }
aipTime rpsOption::day () const { return empday()->day(); }
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsOption::take_msg (aipMsg *mm) {
aiprrOption::take_msg(mm);
// rpsMsg *m = (rpsMsg *)mm;
// if (m->typ() == HH_Starting_New_Try) {
// }
}
//----------------------------------------------------------------------
// g_opt - for making decisions
aipG rpsOption::g_opt() {
return ( aiprrOption::g_opt() + emp()->g_last_work() );
}
//----------------------------------------------------------------------
// g_opt_cmp - for comparing solutions
aipG rpsOption::g_opt_cmp() {
return ( aiprrOption::g_opt_cmp() + emp()->g_last_work() );
}
//----------------------------------------------------------------------
// g_opt_usr - for reporting to the user
aipG rpsOption::g_opt_usr() { // for reporting to the user
return ( aiprrOption::g_opt_usr() + emp()->g_last_work() );
}
//======================================================================
// rpsPosition
//
//----------------------------------------------------------------------
// constructor
rpsPosition::rpsPosition (long a_pos_id, rpsProblem *a_prob)
: aiprrRequirement(a_pos_id, a_prob) {
}
//----------------------------------------------------------------------
// add_posday
void rpsPosition::add_posday (rpsPosDay *x) {
add_reqday(x);
}
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsPosition::take_msg (aipMsg *mm) {
aiprrRequirement::take_msg(mm);
// rpsMsg *m = (rpsMsg *)mm;
}
//----------------------------------------------------------------------
// Note that a decision for this position has been decided
// void rpsPosition::note_rps_decide (rpsDecision *d, rpsOption *o) {}
//----------------------------------------------------------------------
// return an iterator: position-days for the position
rpsPosDayItr rpsPosition::posday_iterator() const {
rpsPosDayItr i(reqday_pandemonium());
return i;
}
//======================================================================
// rpsPosDay
//
//----------------------------------------------------------------------
// constructor
//
// set_dcsn() must be called after the decision is created.
rpsPosDay::rpsPosDay(rpsPosition *a_pos, long a_yyyymmdd,
long a_proj_id,
long a_start_hhmm, long a_end_hhmm)
: aiprrReqDay(a_pos, a_yyyymmdd) {
m_proj_id = a_proj_id;
m_start_time = aipTime(a_yyyymmdd, a_start_hhmm);
m_end_time = aipTime(a_yyyymmdd, a_end_hhmm);
m_yyyymmdd = a_yyyymmdd;
// if posday crosses midnight...
if (m_end_time < m_start_time) m_end_time.add_days(1);
}
//----------------------------------------------------------------------
// Destructor
rpsPosDay::~rpsPosDay() {}
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsPosDay::take_msg (aipMsg *mm) {
aiprrReqDay::take_msg(mm);
// rpsMsg *m = (rpsMsg *)mm;
}
//----------------------------------------------------------------------
// Note that a decision for this position-day has been decided
// void rpsPosDay::note_rps_decide (rpsDecision *d, rpsOption *o) { }
//======================================================================
// rpsEmployee
//
//----------------------------------------------------------------------
// constructor
rpsEmployee::rpsEmployee(long a_id, rpsProblem *a_prob)
: aiprrResource(a_id, a_prob) {
m_g_last_work = aipNeutral;
m_start_last_work = aipTime(20010203);
}
//----------------------------------------------------------------------
// destructor
rpsEmployee::~rpsEmployee() {}
//----------------------------------------------------------------------
// set_start_last_work
void rpsEmployee::set_start_last_work (aipTime x) {
m_start_last_work = x;
}
//----------------------------------------------------------------------
// add_empday
void rpsEmployee::add_empday (rpsEmpDay *x) {
add_resday(x);
}
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsEmployee::take_msg (aipMsg *mm) {
aiprrResource::take_msg(mm);
rpsMsg *m = (rpsMsg *)mm;
if (m->typ() == HH_Starting_New_Try) {
aipTime limit_day(20020101);
if (m_start_last_work < limit_day) {
m_start_last_work = prob()->start_day();
}
long days_since_work =
prob()->start_day().days_since(m_start_last_work);
if (days_since_work > 64) {
m_g_last_work = aipGood;
} else if (days_since_work > 32) {
m_g_last_work = aipQuiteGood;
} else if (days_since_work > 16) {
m_g_last_work = aipPrettyGood;
} else if (days_since_work > 8) {
m_g_last_work = aipFairlyGood;
} else if (days_since_work > 4) {
m_g_last_work = aipSomewhatGood;
} else if (days_since_work > 2) {
m_g_last_work = aipSlightlyGood;
}
}
}
//----------------------------------------------------------------------
// Note that a decision involving this employee has been decided
// void rpsEmployee::note_rps_decide (rpsDecision *d, rpsOption *o) { }
//----------------------------------------------------------------------
// empday_iterator
rpsEmpDayItr rpsEmployee::empday_iterator() const {
rpsEmpDayItr i(resday_pandemonium());
return i;
}
//======================================================================
// rpsEmpDay
//
//----------------------------------------------------------------------
// constructor
rpsEmpDay::rpsEmpDay(rpsEmployee *a_emp, long a_yyyymmdd,
long a_start_hhmm, long a_end_hhmm)
: aiprrResDay(a_emp, a_yyyymmdd) {
m_start_time = aipTime(a_yyyymmdd, a_start_hhmm);
m_end_time = aipTime(a_yyyymmdd, a_end_hhmm);
m_yyyymmdd = a_yyyymmdd;
// if empday crosses midnight...
if (m_end_time < m_start_time) m_end_time.add_days(1);
}
//----------------------------------------------------------------------
// take_msg - take and react to a message
void rpsEmpDay::take_msg (aipMsg *mm) {
aiprrResDay::take_msg(mm);
// rpsMsg *m = (rpsMsg *)mm;
// if (m->typ() == HH_Starting_New_Try) {
// }
}
//----------------------------------------------------------------------
// Note that a decision involving this empday has been decided
// void rpsEmpDay::note_rps_decide (rpsDecision *d, rpsOption *o) { }
//----------------------------------------------------------------------
// opt_iterator - return an iterator: options for an EmpDay
rpsOptItr rpsEmpDay::opt_iterator() const {
rpsOptItr i(opt_pandemonium());
return i;
}
//======================================================================
// Iterators
//
// All function bodies in header file.
//
//======================================================================
// License
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to
// whom the Software is furnished to do so, subject to the
// following conditions:
//
// The copyright notice and this license shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//======================================================================
|