Commit 3be4e3ec authored by Alexis Lebis's avatar Alexis Lebis

new prereqConstraint check and continue metric

parent 01e1c03c
......@@ -71,7 +71,8 @@ int main(int argc, char* argv[]){
DecayEngine::IS_DECAY_DEACTIVATED = parser.createParam((int)(0), "decayDeactivated", "Wether or not the decay is deactivated", 'D', "Param").value();
ConstraintsProfession::DISCRETE_METRIC = parser.createParam((unsigned int)(1), "jobEvalDiscrete" , "What type of metric to use between discret and continue with mag", 'k', "Param").value();
ConstraintsPrerequisites::DISCRETE_METRIC = parser.createParam((unsigned int)(1), "prqEvalDiscrete" , "What type of metric to use between discret and continue with mag", 'K', "Param").value();
ConstraintsPrerequisites::DISCRETE_METRIC = parser.createParam((unsigned int)(1), "prqEvalDiscrete" , "What type of metric to use between discret and continue with mag constraints", 'K', "Param").value();
ConstraintsPrerequisites::INTEGRITY_CHECK = parser.createParam((unsigned int)(1), "prqCheckFunc" , "Dev. option: switching between prereqCheck func 1 and 2", 'O', "Param").value();
//PROFESSION PARAMETERS
unsigned int JOB_SEED = parser.createParam((unsigned int)(7777), "jobSeed", "Seed used for the Profession", 'g', "Param").value();
......@@ -314,6 +315,7 @@ int main(int argc, char* argv[]){
if(localDisplay)
{
pb.displayDistribution();
std::cout << pb << std::endl;
std::cout << job << std::endl;
......@@ -330,7 +332,17 @@ int main(int argc, char* argv[]){
resECTS = ctrECTS.integrityCheck(pop.best_element());
resRep = ctrRep.integrityCheck(pop.best_element());
resJob = ctrJob.integrityCheck(pop.best_element());
resPrq = ctrPrq.integrityCheck(pop.best_element());
switch (ConstraintsPrerequisites::INTEGRITY_CHECK)
{
case 2:
resPrq = ctrPrq.integrityCheck2(pop.best_element());
break;
default:
resPrq = ctrPrq.integrityCheck(pop.best_element());
break;
}
std::cout << "ECTS: ";
if(resECTS.first)
......@@ -420,7 +432,16 @@ int main(int argc, char* argv[]){
resECTS = ctrECTS.integrityCheck(pop.best_element());
resRep = ctrRep.integrityCheck(pop.best_element());
resJob = ctrJob.integrityCheck(pop.best_element());
resPrq = ctrPrq.integrityCheck(pop.best_element());
switch (ConstraintsPrerequisites::INTEGRITY_CHECK)
{
case 2:
resPrq = ctrPrq.integrityCheck2(pop.best_element());
break;
default:
resPrq = ctrPrq.integrityCheck(pop.best_element());
break;
}
std::cout << "ECTS: ";
if(resECTS.first)
......
......@@ -11,6 +11,7 @@
#include "model/exception/competencyEvolvingException.h"
int ConstraintsPrerequisites::DISCRETE_METRIC = 1;
int ConstraintsPrerequisites::INTEGRITY_CHECK = 1;
std::pair<bool, double> ConstraintsPrerequisites::integrityCheck(Cursus indiv)
{
......@@ -133,7 +134,7 @@ std::pair<bool, double> ConstraintsPrerequisites::integrityCheck(Cursus indiv)
switch (ConstraintsPrerequisites::DISCRETE_METRIC)
{
case 0/* constant-expression */:
std::cout << "MagDiff: " << magDiff << " for " << (double)magDivisor << " prereqs. (1 - " << ( magDiff / (double)magDivisor ) << std::endl;
// std::cout << "MagDiff: " << magDiff << " for " << (double)magDivisor << " prereqs. (1 - " << ( magDiff / (double)magDivisor ) << std::endl;
assert(magDivisor != 0);
return std::pair<bool, double>(isOK, 1 - ( magDiff / (double)magDivisor ) );
default:
......@@ -184,7 +185,7 @@ std::tuple<int, int, double, int> ConstraintsPrerequisites::_prereqsInPreviousTF
{
notRespected++;
magDiff += ( prereqs.at(i).c_magnitude().value() - cInTF.at(j).decay() ) / prereqs.at(i).c_magnitude().value();
std::cout << "\tMag diff: " << prereqs.at(i).c_magnitude().value() - cInTF.at(j).decay() << "\t Ratio:" << magDiff << std::endl;
// std::cout << "\tMag diff: " << prereqs.at(i).c_magnitude().value() - cInTF.at(j).decay() << "\t Ratio:" << magDiff << std::endl;
}
}
}
......@@ -197,3 +198,158 @@ std::tuple<int, int, double, int> ConstraintsPrerequisites::_prereqsInPreviousTF
//std::cout << "NF: " << std::to_string(notFound) << " | NR: " << std::to_string(notRespected) << std::endl;
return std::tuple<int, int, double, int>(notFound, notRespected, magDiff, divisor);
}
std::pair<bool, double> ConstraintsPrerequisites::integrityCheck2(Cursus indiv)
{
std::pair<bool, double> res;
std::vector<std::vector<double>> compDistribyTF; //each i contains an vector representing the magnitique of each comp existing, according to the path followed. [0;1]
// === init
for(unsigned int i = 0; i < this->_pb.timeFrames().size(); i++)
{
std::vector<double> tmp;
for(unsigned int j = 0; j < this->_pb.competencyCatalogue().size(); j++)
{
tmp.push_back(0);
}
compDistribyTF.push_back(tmp);
}
// === fill each double vector of each tf according to comp seen
int currentTF = 0;
Course currentCourse;
std::vector<std::pair<Competency, double>> teachedComps;
unsigned int idx;
for(int i = 0; i < indiv.size(); i++)
{
currentTF = i / this->_pb.cfg_pickedCoursesByTimeFrame();
currentCourse = this->_pb.coursesCatalogue().at(indiv.at(i));
teachedComps = currentCourse.teachedCompetenciesWeighted();
for(int j = 0; j < teachedComps.size(); j++)
{
idx = this->_pb.mapCompToPosition(teachedComps.at(j).first);
assert(idx >= 0);
compDistribyTF.at(currentTF).at(idx) += teachedComps.at(j).first.magnitude().value();
if(compDistribyTF.at(currentTF).at(idx) > 1) //can't exceed 1 in a signle TF
compDistribyTF.at(currentTF).at(idx) = 1;
}
}
// === sum for t of all t-i
for(int i = 1; i < this->_pb.timeFrames().size() ; i++)
{
for(int j = 0; j < i; j++)
{
for(int k = 0; k < this->_pb.competencyCatalogue().size() ; k++)
{
compDistribyTF.at(i).at(k) += compDistribyTF.at(j).at(k);
// if(compDistribyTF.at(i).at(k) > 1) //commented because decay
// compDistribyTF.at(i).at(k) = 1;
}
}
}
// === apply decay
std::vector<double> tmpDiff;
std::vector<int> decayClock(this->_pb.competencyCatalogue().size());
double decayVal = 0; double delta = 0;
for(int i = 1; i < compDistribyTF.size(); i++) //starts to 1 because 0 does not have decay
{
for(int j = 0; j < compDistribyTF.at(0).size(); j++) //0 because we do not care which, they all have the same size == this->_pb.competencyCatalogue().size()
{
decayVal = 0; delta = 0;
tmpDiff.push_back(compDistribyTF.at(i).at(j) - compDistribyTF.at(i-1).at(j));
if(tmpDiff.at(j) == 0) //if 0->comp stagnation therefore decay
{
decayClock.at(j)++;
}
else
{
if(decayClock.at(j)>0)
decayVal = DecayEngine::defaultDecay(decayClock.at(j)-1);
// storing the delta of the mag in i-1 ; i
delta = compDistribyTF.at(i).at(j) - compDistribyTF.at(i-1).at(j);
compDistribyTF.at(i).at(j) = delta + ( compDistribyTF.at(i-1).at(j) - decayVal );
decayClock.at(j) = 0;
}
}
}
// === checking courses prerequisite
int notFound = 0; int notRespected = 0; int nbPrereq = 0;
double magDiff = 0; int magDivisor = 0;
for(int i = 0; i < indiv.size(); i++)
{
currentTF = i / this->_pb.cfg_pickedCoursesByTimeFrame();
assert(indiv.at(i) < this->_pb.coursesCatalogue().size());
currentCourse = this->_pb.coursesCatalogue().at(indiv.at(i));
// std::cout << currentCourse << std::endl;
for(int j = 0; j < currentCourse.prerequisites().size(); j++)
{
nbPrereq++;
idx = this->_pb.mapCompToPosition(currentCourse.prerequisites().at(j));
if( currentTF == 0 || //if we have prereq at tf 0 -> automatically fails !
compDistribyTF.at(currentTF-1).at(idx) < currentCourse.prerequisites().at(j).c_magnitude().value())
{
// PREREQ KO !
if(currentTF == 0 || compDistribyTF.at(currentTF-1).at(idx) == 0)
{
magDiff += currentCourse.prerequisites().at(j).c_magnitude().value(); //not exists so full value in diff here
notFound++;
}
else
{
magDiff += ( currentCourse.prerequisites().at(j).c_magnitude().value() - compDistribyTF.at(currentTF-1).at(idx) ) / currentCourse.prerequisites().at(j).c_magnitude().value(); // percentage of diff in [0;1]
notRespected++;
}
}
else
{
// PREREQ OK !
}
}
}
bool isOK = ((notFound == 0) && (notRespected == 0));
switch (ConstraintsPrerequisites::DISCRETE_METRIC)
{
case 0/* constant-expression */:
// std::cout << "MagDiff: " << magDiff << " for " << (double)nbPrereq << " prereqs. (1 - " << ( magDiff / (double)nbPrereq ) << std::endl;
// assert(magDivisor != 0);
return std::pair<bool, double>(isOK, 1 - ( magDiff / (double)nbPrereq ) );
default:
double metric = 0;
if(nbPrereq > 0)
{
metric = 1.0 - ( (((double)2 * (double)notFound) + (double)notRespected ) / (2 * (double) nbPrereq) );
}
else //can't divide by 0
{
if(isOK)
metric = 1;
else
metric = 0;
}
//std::cout << "Metric: " << std::to_string(metric) << std::endl;
//std::cout << "====================" << std::endl;
return std::pair<bool, double>(isOK, metric);
}
}
......@@ -34,6 +34,7 @@ class ConstraintsPrerequisites
std::tuple<int,int, double, int> _prereqsInPreviousTF(std::vector<Competency> cInTF, std::vector<Competency> prereqs);
public:
static int DISCRETE_METRIC;
static int INTEGRITY_CHECK;
ConstraintsPrerequisites(const CSDVP & csdvp, const Profession & job)
: _pb(csdvp), _job(job) {}
......@@ -42,7 +43,12 @@ class ConstraintsPrerequisites
* Returns a std::pair. First is a boolean set to true when the indiv passes the test and therefore is compilant with the constraint, false otherwise. Second is the associated metric, mostly usable during fitness calcul.
* @todo Decay competency magnitude
*/
std::pair<bool, double> integrityCheck(Cursus indiv);
std::pair<bool, double> integrityCheck(Cursus indiv);
/**
* 2nd version of integrity check. Supposed to be more reliable and faster
*/
std::pair<bool, double> integrityCheck2(Cursus indiv);
};
#endif // SRC_MODEL_CONSTRAINTS_PREREQUISITES_CONSTRAINTS_H_
\ No newline at end of file
......@@ -25,7 +25,17 @@ void CursusEval::operator()(Cursus & _cursus){
resCE=ce.integrityCheck(_cursus);
resCP=cp.integrityCheck(_cursus);
resCR=cr.integrityCheck(_cursus);
resCPR=cpr.integrityCheck(_cursus);
switch (ConstraintsPrerequisites::INTEGRITY_CHECK)
{
case 2:
resCPR=cpr.integrityCheck2(_cursus);
break;
default:
resCPR=cpr.integrityCheck(_cursus);
break;
}
/*
std::cout << "EVAL: ";
std::cout << resCE.first << " " << resCE.second << std::endl;
......
......@@ -5,6 +5,7 @@
#include <cstdlib>
#include <queue>
#include <cassert>
#include <tuple>
#include "problem.h"
#include "tools.h"
......@@ -188,6 +189,16 @@ int CSDVP::CSDVP_COUNTER = 0;
return i;
return -1;
}
int CSDVP::mapCompToPosition(const Competency & comp)
{
for(unsigned int i = 0; i < this->competencyCatalogue().size();i++)
{
if(comp == this->competencyCatalogue().at(i))
return i;
}
return -1;
}
// === END FUNC
// === STATIC
......@@ -342,6 +353,14 @@ int CSDVP::CSDVP_COUNTER = 0;
assert(c == pb.competencyCatalogue().at(pb.competencyCatalogue().size()-1));
}
/* Creating _distributedCompetencies array for assignation */
for(int i = 0; i < pb.competencyCatalogue().size(); i++)
{
pb._distributedCompetencies.push_back(-1);
}
assert (pb._distributedCompetencies.size() == pb.competencyCatalogue().size());
/* Assigning Hierachy Level (HL) for each comp
* HL is used to improve the average quality of the course catalogue compared to random
*/
......@@ -387,10 +406,7 @@ int CSDVP::CSDVP_COUNTER = 0;
{
// tmpComp = queue.front();
tmpComp = HLComp.at(j);
magVal = pb.cfg_magnitudeMin().value() + ( (double)rand()/RAND_MAX) * ( pb.cfg_magnitudeMax().value() - pb.cfg_magnitudeMin().value()) ;
Competency cpt = Competency::build(magVal,tmpComp.c_name());
teachedComp = std::pair<Competency,double>(cpt, 1.0);
pb.unlocked_coursesCatalogue().at(i).addTeachedComp(teachedComp);
pb._sourceCourseTeachedComp(pb, i, tmpComp);
}
}
......@@ -445,10 +461,87 @@ int CSDVP::CSDVP_COUNTER = 0;
}
}
void CSDVP::_sourceCourseTeachedComp(CSDVP & pb, unsigned int idx, Competency & c)
{
double magVal;
magVal = pb.cfg_magnitudeMin().value() + ( (double)rand()/RAND_MAX) * ( pb.cfg_magnitudeMax().value() - pb.cfg_magnitudeMin().value()) ;
Competency cpt = Competency::build(magVal,c.c_name());
std::pair<Competency, double> teachedComp = std::pair<Competency,double>(cpt, 1.0);
pb.unlocked_coursesCatalogue().at(idx).addTeachedComp(teachedComp);
_updateDistribComp(pb, cpt);
}
void CSDVP::_updateDistribComp(CSDVP & pb, Competency & cpt)
{
int idx = pb.mapCompToPosition(cpt);
assert (idx >= 0);
if(pb._distributedCompetencies.at(idx) == -1) //not yet assigned? Then first 0
pb._distributedCompetencies.at(idx) = 0;
pb._distributedCompetencies.at(idx) += cpt.magnitude().value();
if(pb._distributedCompetencies.at(idx) > 1) //if range overflow --> rebase to one
pb._distributedCompetencies.at(idx) = 1;
}
// --------- END GENERATION RELATED FUNCTIONS ---------
// === END STATIC
void const CSDVP::displayDistribution(){
std::cout << "------------------------------" << std::endl;
std::cout << "| PB Competency distribution |" << std::endl;
std::cout << "------------------------------" << std::endl;
std::tuple<int, int, double, double> stats = this->distributionStats();
std::cout << "Stats: " << std::endl ;
std::cout << "\n\t# of Comp: " << this->_distributedCompetencies.size();
std::cout << "\n\t# of Unassigned: " << std::get<0>(stats);
std::cout << "\n\t# of above 0.5: " << std::get<1>(stats);
std::cout << "\n\tDistrib mean: " << std::get<2>(stats);
std::cout << "\n\tDistrib median: " << std::get<3>(stats) << std::endl;
std::cout << "\n\tUnassigned in HL#" << -1 << std::endl;
std::cout << "Distrib:" << std::endl;
std::cout << "[";
for(int i = 0; i < this->_distributedCompetencies.size(); i++)
{
std::cout << this->_distributedCompetencies.at(i);
if(i < this->_distributedCompetencies.size() -1 )
std::cout << "|";
}
std::cout << "]" << std::endl;
std::cout << "------------------------------" << std::endl << std::endl;
}
std::tuple<int, int, double, double> CSDVP::distributionStats()
{
std::tuple<int, int, double, double> stats;
int unassigned = 0;
int aboveFive = 0;// >= 0.5
double mean = 0;
double median = 0;
for(int i = 0; i < this->_distributedCompetencies.size(); i++)
{
if(this->_distributedCompetencies.at(i) == -1)
unassigned++;
else
{
mean += this->_distributedCompetencies.at(i);
if(this->_distributedCompetencies.at(i) >= 0.5)
aboveFive++;
}
}
mean = mean / ( (double)(this->_distributedCompetencies.size() - unassigned));
std::get<0>(stats) = unassigned;
std::get<1>(stats) = aboveFive;
std::get<2>(stats) = mean; //todo
std::get<3>(stats) = -1; //todo
return stats;
}
// === OPERATOR
std::ostream & operator<<(std::ostream & Stream, const CSDVP & c)
{
......
......@@ -2,6 +2,7 @@
#define SRC_PROBLEM_H_
#include <vector>
#include <tuple>
#include "course.h"
#include "competency.h"
......@@ -56,7 +57,11 @@ class CSDVP
std::vector<Course> _availableCourses;
std::vector<std::vector<Course>> _coursesSortedByTF; //sorted by standard index. e.g. TF[4;6] -> [0]=4; [1]=5 ; [2] = 6
std::vector<Competency> _availableCompentecies; //The competency's magnitude should not be used here.
// This array is index aligned with the compCatalogue of the problem. It represents the current compentecies distrib in the pb. Mostly used during configuratioin.
// -1 : not assigned ; [0;1] the ith comp at the indice i in the cmpCatalogue as been assigned, with a value of x € [0;1].
std::vector<double> _distributedCompetencies;
///@todo implements a decay politics
//DecayPolitics
// --------- END PROBLEM SPECIFIC ATTRIBUTES ---------
......@@ -81,6 +86,10 @@ class CSDVP
/// It sources _coursesSortedByTF, which is another view of _availableCourses, sorted by TF
void _makeCoursesSortedByTF();
// This fuction creates a new tmpComp with mag and add it the comp teached by the course idx of the catalogue
// Using the sourcing function keeps the _distributedCompetencies up to date
void _sourceCourseTeachedComp(CSDVP & pb, unsigned int idx, Competency & c);
void _updateDistribComp(CSDVP & pb, Competency & cpt);
public:
// --------- GENERATION RELATED FUNCTION ---------
/// allows a random attribution of pb's attributes
......@@ -140,8 +149,22 @@ class CSDVP
* returns the index of the course within the coursesCatalogue [0;size[ ; otherwise return -1 if the course is not found.
*/
int mapCourseToPosition(const Course & c);
/** Maps a competency into its position inside the this->competencyCatalogue().
* returns the index of the competency within the competencyCatalogue [0;size[ ; otherwise return -1 if the competency is not found.
*/
int mapCompToPosition(const Competency & comp);
///@todo getDecayPolitic
// === Competency Distribution related
void const displayDistribution();
/* Retrieves some stats regarding the comp distrib
* First element is the nb of unassigned comp
* Second element is the nb of comp above 0.5
* Third element is the mean (all unassigned elm excluded)
* Fourth element is the median (idem)
*/
std::tuple<int, int, double, double> distributionStats();
// === MUTATOR
// SETTER
/*setSeed is deactivated. The only way to attribute a seed to CSDVP is by generateProblem.*/
......
  • mentioned in issue #19 (closed)

    Toggle commit list
  • New checkIntegrity function (checkIntegrity2) improving reliability of decay and improving speed of the algo.

    For ./ceao -d=1 -C=30 -c=40 -A=4 -n=4 -B=50 -x=0.75 -X=0.75 -F=3 -G=200 z=2 -k=0 -K=0 -O=2 -s=7 we win ~4.5 sec (10.7 sec in total compared to 15.1 sec)

  • mentioned in issue #21 (closed)

    Toggle commit list
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment