Commit 571917f4 authored by Alexis Lebis's avatar Alexis Lebis

Merge branch 'compHierarchy' into 'master'

Comp hierarchy rework for v2.0

See merge request !9
parents 91b9b23b 5a95a536
......@@ -10,6 +10,7 @@
#include <model/magnitude.h>
#include <model/tools.h>
#include <model/competency.h>
#include <model/competencyDistribution.h>
#include <model/decay.h>
#include <model/ea/cursus.h>
......@@ -63,11 +64,26 @@ int main(int argc, char* argv[]){
unsigned int MINPRE = parser.createParam((unsigned int)(0), "minPre", "minimal competency by course",'q',"Param").value();
unsigned int MAXPRE = parser.createParam((unsigned int)(3), "maxPre", "maximal competency by course",'Q',"Param").value();
unsigned int CBYTF = parser.createParam((unsigned int)(2), "cbyTF", "course by time frame to pick",'A',"Param").value();
unsigned int THRESHOLD_HLEVEL = parser.createParam((unsigned int)(30), "minMaxHLevelPrq", "Threshold under the one the HLevel max is used instead of min for prqs", 'y', "Param").value();
CursusEval::WEIGHT_ECTS = parser.createParam((double)(1.0), "wECTS", "Weight of ECTS in the fitness value", 'V', "Param").value();
CursusEval::WEIGHT_REPETION = parser.createParam((double)(1.0), "wREP", "Weight of Repetition in the fitness value", 'v', "Param").value();
CursusEval::WEIGHT_JOB = parser.createParam((double)(1.0), "wJob", "Weight of profession in the fitness value", 'w', "Param").value();
CursusEval::WEIGHT_PREREQ = parser.createParam((double)(1.0), "wPrereq", "Weight of prerequisites in the fitness value", 'W', "Param").value();
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 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();
ConstraintsPrerequisites::OVERFLOW_PERCENT= parser.createParam((int)(0), "overflow", "Overflow above 1 authorized during prerequisite calculation can be negative too", 'Y', "Param").value();
CompetencyDistribution::HLEVEL[0] = parser.createParam((int)(50), "hLevel0", "Comp Percentage in the HLevel 0", '0', "Param").value();
CompetencyDistribution::HLEVEL[1] = parser.createParam((int)(50), "hLevel1", "Comp Percentage in the HLevel 1", '1', "Param").value();
CompetencyDistribution::HLEVEL[2] = parser.createParam((int)(-1), "hLevel2", "Comp Percentage in the HLevel 2", '2', "Param").value();
CompetencyDistribution::HLEVEL[3] = parser.createParam((int)(-1), "hLevel3", "Comp Percentage in the HLevel 3", '3', "Param").value();
CompetencyDistribution::HLEVEL[4] = parser.createParam((int)(-1), "hLevel4", "Comp Percentage in the HLevel 4", '4', "Param").value();
CompetencyDistribution::HLEVEL[5] = parser.createParam((int)(-1), "hLevel5", "Comp Percentage in the HLevel 5", '5', "Param").value();
CompetencyDistribution::HLEVEL[6] = parser.createParam((int)(-1), "hLevel6", "Comp Percentage in the HLevel 6", '6', "Param").value();
CompetencyDistribution::HLEVEL[7] = parser.createParam((int)(-1), "hLevel7", "Comp Percentage in the HLevel 7", '7', "Param").value();
CompetencyDistribution::HLEVEL[8] = parser.createParam((int)(-1), "hLevel8", "Comp Percentage in the HLevel 8", '8', "Param").value();
CompetencyDistribution::HLEVEL[9] = parser.createParam((int)(-1), "hLevel9", "Comp Percentage in the HLevel 9", '9', "Param").value();
//PROFESSION PARAMETERS
unsigned int JOB_SEED = parser.createParam((unsigned int)(7777), "jobSeed", "Seed used for the Profession", 'g', "Param").value();
......@@ -75,7 +91,8 @@ int main(int argc, char* argv[]){
unsigned int JOB_MAXPRE = parser.createParam((unsigned int)(4), "jobMaxPre" , "maximal competency prerequisite by a job", 'J', "Param").value();
double JOB_MINMAG = parser.createParam((double)(0.5), "jobMinMag" , "miminal magnitude for a job" , 'h', "Param").value();
double JOB_MAXMAG = parser.createParam((double)(0.95), "jobMaxMag" , "maxima magnitude for a job" , 'H', "Param").value();
Profession::JOB_SELECTION_TYPE = parser.createParam((unsigned int)(0), "jobSelectType" , "Which type to use to select job", 'z', "Param").value();
//EVOLUTION ENGINE PARAMETERS
unsigned int POPSIZE = parser.createParam((unsigned int)(100), "popSize", "Population size", 'P', "Evolution Engine").value();
double PMUT = parser.createParam((double)(0.5), "pMut", "mutation rate", 'x', "Evolution Engine").value();
......@@ -85,6 +102,7 @@ int main(int argc, char* argv[]){
RATIO_RANDOM_VS_BEST = parser.createParam((unsigned int)(75), "ratioBest", "Ratio between full random and best while prereq check fails in mutation",'B',"Param").value();
// ===== PB CONFIG ZONE =====
CompetencyDistribution::sanitizeHLEVEL(); //Mandatory for HLevel
CSDVP pb;
Profession job;
std::cout << "nb cours: ---> " << NBCOURSES << std::endl;
......@@ -103,6 +121,7 @@ int main(int argc, char* argv[]){
pb.set_cfg_minimalPrerequisiteByCourse(MINPRE);
pb.set_cfg_maximalPrerequisiteByCourse(MAXPRE);
pb.set_cfg_pickedCoursesByTimeFrame(CBYTF);
pb.set_cfg_thresholdHLevelMaxOverMin(THRESHOLD_HLEVEL);
CSDVP::generateProblem(pb, CSDVP::GenerationType::RANDOM, SEED);
assert(pb.checkConfig());
......@@ -167,7 +186,7 @@ int main(int argc, char* argv[]){
//POPULATION INITIALISATION
eoPop<Cursus> pop;
Cursus c1;
for(int i = 0; i < POPSIZE; i++){
for(unsigned int i = 0; i < POPSIZE; i++){
init(c1);
eval(c1);
pop.push_back(c1);
......@@ -310,7 +329,17 @@ int main(int argc, char* argv[]){
if(localDisplay)
{
pb.displayDistribution();
std::cout << pb << std::endl;
std::cout << job << std::endl;
std::vector<Competency> compHL = CompetencyDistribution::upToHLevel(pb,2);
std::cout << "HL GTTING" << std::endl;
for(unsigned int i = 0 ; i < compHL.size(); i++)
std::cout << compHL[i] << std::endl;
std::cout << "===== CURRENT POP =====" << std::endl;
// pop.printOn(std::cout);
pop.best_element().printOn(std::cout);
std::cout << " fitness:" << pop.best_element().fitness() << std::endl;
std::cout << "Stats & metrics: \n" << std::endl;
......@@ -360,7 +389,7 @@ int main(int argc, char* argv[]){
outputfile2 << pop.size() << std::endl;
outputfile3 << pop.size() << std::endl;
for(int i=0; i<pop.size();i++){
for(unsigned int i=0; i<pop.size();i++){
//Write pop + prerequires values
pop[i].printOn(outputfile2);
outputfile2 << " " << ctrECTS.integrityCheck(pop[i]).second << " " << ctrRep.integrityCheck(pop[i]).second << " " << ctrJob.integrityCheck(pop[i]).second << " " << ctrPrq.integrityCheck(pop[i]).second << std::endl;
......@@ -381,7 +410,7 @@ int main(int argc, char* argv[]){
outputfile2 << pop.size() << std::endl;
outputfile3 << pop.size() << std::endl;
for(int i=0; i<pop.size();i++){
for(unsigned int i=0; i<pop.size();i++){
//Write pop + prerequires values
pop[i].printOn(outputfile2);
outputfile2 << " " << ctrECTS.integrityCheck(pop[i]).second << " " << ctrRep.integrityCheck(pop[i]).second << " " << ctrJob.integrityCheck(pop[i]).second << " " << ctrPrq.integrityCheck(pop[i]).second << std::endl;
......@@ -439,6 +468,10 @@ int main(int argc, char* argv[]){
std::cout << " | value: " << resPrq.second << std::endl;
std::cout << "===============" << std::endl;
ctrPrq._displayDecayedArrays(pop.best_element());
std::cout << job ;
}
// ================================= END RUN ZONE ===============================
......
......@@ -10,6 +10,7 @@ SET (EXERCICE_SOURCES
profession.cpp
problem.cpp
decay.cpp
competencyDistribution.cpp
)
ADD_LIBRARY(lModel STATIC ${EXERCICE_SOURCES})
......
......@@ -145,7 +145,7 @@ void Competency::saveDecay()
// === OPERATOR
std::ostream& operator<<(std::ostream& Stream, const Competency & c)
{
std::string s = "Competency\n\tid:"+std::to_string(c.id())+"\n\tname:"+c.c_name()+"\n\tvalue:"+std::to_string(c.competencyValue());
std::string s = "Competency\n\tid:"+std::to_string(c.id())+"\n\tname:"+c.c_name()+"\n\tvalue:"+std::to_string(c.competencyValue())+"\n\tHLevel:"+std::to_string(c.hLevel());
Stream << s ;
return Stream;
}
......
......@@ -23,7 +23,7 @@ class Competency
std::string _name;
int _howLongDecaying; //Decay related
bool _isDecaying; //Decay related
int _hLevel; // Hierarchy level (HL) of the competency. HL should onlye have lower HL comp as prereq. thus HL 0 has no prereq
//Constructor
Competency(int, Magnitude, std::string);
......@@ -64,12 +64,15 @@ class Competency
///Retrieves the name of the competency
const std::string c_name() const {return this->_name;}
std::string & name() {return this->_name;}
int hLevel() const{return this->_hLevel;}
int id() const {return this->_id;}
// === SETTER
void setMagnitude(Magnitude & m){this->_m = m;}
void setName(std::string s){this->_name = s;}
void setHL(int hl){this->_hLevel = hl;}
// === DECAY
bool isDecaying() const {return this->_isDecaying;}
......
#include <iostream>
#include <assert.h>
#include <algorithm>
#include "competencyDistribution.h"
std::vector<int> CompetencyDistribution::HLEVEL(10);
bool CompetencyDistribution::hlevelSanitized = false;
void CompetencyDistribution::distribute(CSDVP &pb)
{
if(!hlevelSanitized)
{
std::cout << "WARNING! HLevel has not been progammatically sanitized; automatically doing it" << std::endl;
CompetencyDistribution::sanitizeHLEVEL();
}
std::vector<int> idxComp;
for(int i = 0 ; i < pb.cfg_quantityCompetencies(); i++)
{
idxComp.push_back(i);
}
std::random_shuffle(idxComp.begin(), idxComp.end());
int nbAffected=0;
for(unsigned int i = 0; i < CompetencyDistribution::HLEVEL.size(); i++)
{
for(unsigned int j = 0; j < idxComp.size() && (j < (CompetencyDistribution::HLEVEL.at(i) * pb.cfg_quantityCompetencies()) / 100) ; j++)
{
pb.unlocked_competenciesCatalogue().at(idxComp.at(nbAffected)).setHL(i);
nbAffected++;
}
}
int notAffected = pb.cfg_quantityCompetencies() - nbAffected;
if(notAffected <= 0 )
return;
int hl = 0;
for(int i = 0; i < notAffected; i++)
{
assert(nbAffected+i <= pb.cfg_quantityCompetencies());
pb.unlocked_competenciesCatalogue().at(nbAffected+i).setHL(hl%CompetencyDistribution::HLEVEL.size());
hl++;
}
}
void CompetencyDistribution::linearDistribution(CSDVP &pb)
{
std::cout << "Linear distribution of competency is deprecated" << std::endl;
assert(false);
int interval = CompetencyDistribution::HLevelRange(pb);
if(pb.cfg_competencyByCourseMin() != 0) //if the min borne is not 0, we add another interval for comp with no prereq
interval++;
int nbCompByHL = pb.cfg_quantityCompetencies() / interval;
std::cout << "Interval" << interval << " -- nbCompByHL:" << nbCompByHL << std::endl;
for(int i = 0; i < pb.cfg_quantityCompetencies() && i < nbCompByHL * interval; i++)
{
pb.unlocked_competenciesCatalogue().at(i).setHL(i/nbCompByHL);
}
//Taking into account comp missed with the division
//int diff = pb.cfg_quantityCompetencies() - nbCompByHL*interval;
int idxInterval = 0;
for(int i = pb.cfg_quantityCompetencies()-1; i >= nbCompByHL*interval; i--)
{
pb.unlocked_competenciesCatalogue().at( i ).setHL(idxInterval%interval);
idxInterval++;
}
}
// === STATIC
int CompetencyDistribution::HLevelRange(CSDVP & pb)
{
assert(CompetencyDistribution::sanitizeHLEVEL);
// int interval = pb.cfg_competencyByCourseMax() - pb.cfg_competencyByCourseMin();
return CompetencyDistribution::HLEVEL.size();
}
std::vector<Competency> CompetencyDistribution::getHLevel(CSDVP & pb, int level)
{
std::vector<Competency> comp = std::vector<Competency>();
if(level < 0)
return comp;
if(level > CompetencyDistribution::HLevelRange(pb))
return comp;
std::vector<Competency> pbComp = pb.competencyCatalogue();
for(unsigned int i = 0; i < pbComp.size(); i++)
if(pbComp[i].hLevel() == level)
comp.push_back(pbComp[i]);
return comp;
}
std::vector<Competency> CompetencyDistribution::upToHLevel(CSDVP & pb, int level)
{
std::vector<Competency> res = std::vector<Competency>();
std::vector<Competency> tmp; //dry prog
int start;
for(start = 0; start <= level ; start++)
{
tmp = CompetencyDistribution::getHLevel(pb, start);
for(unsigned int i = 0; i < tmp.size(); i++)
res.push_back(tmp[i]);
}
return res;
}
std::vector<Competency> CompetencyDistribution::unassignedUpToHLevel(CSDVP & pb, int level)
{
std::vector<Competency> res;
std::vector<Competency> tmp;
//assert(level < HLEVEL.size());
for(int i = 0; i <= level; i++)
{
tmp = CompetencyDistribution::unassignedAtHLevel(pb, i);
for(unsigned int j = 0; j < tmp.size(); j++)
res.push_back(tmp[j]);
}
return res;
}
std::vector<Competency> CompetencyDistribution::unassignedAtHLevel(CSDVP &pb, int hlevel)
{
assert(hlevel >= 0);
std::vector<Competency> res;
for(unsigned int i = 0; i < pb.competencyCatalogue().size(); i++)
{
if(pb.competencyCatalogue().at(i).hLevel() == hlevel && pb.unlocked_distributedCompetencies().at(i) == -1)
res.push_back(pb.competencyCatalogue().at(i));
}
return res;
}
void CompetencyDistribution::sanitizeHLEVEL()
{
int sum = 0;
std::vector<int> tmp;
for(unsigned int i = 0; i < CompetencyDistribution::HLEVEL.size(); i++)
{
if(CompetencyDistribution::HLEVEL.at(i) >= 0) //ignoring all negative value
{
sum += CompetencyDistribution::HLEVEL.at(i);
tmp.push_back(CompetencyDistribution::HLEVEL.at(i));
}
}
assert(sum==100);
CompetencyDistribution::HLEVEL = tmp;
CompetencyDistribution::hlevelSanitized = true;
}
void CompetencyDistribution::displayHLevel()
{
std::cout << "HLEVEL:" << std::endl << "[";
for(unsigned int i = 0 ; i < CompetencyDistribution::HLEVEL.size()-1; i++)
{
std::cout << CompetencyDistribution::HLEVEL.at(i) << "|";
}
std::cout << CompetencyDistribution::HLEVEL.at(CompetencyDistribution::HLEVEL.size()-1) << "]" << std::endl << std::endl;
}
\ No newline at end of file
#ifndef SRC_COMPETENCY_DISTRIBUTION_H_
#define SRC_COMPETENCY_DISTRIBUTION_H_
#include <vector>
#include "problem.h"
#include "competency.h"
/**
* Represents the distribution of prerequisites from competencies.
*
* This is used to implement some hierarchy between competencies.
* CompetencyDistribution must be called after the competencies has been created within the problem
* and preferably before the compentecies have been affected to the courses.
*
* @author alexis.lebis
* @version 1
*/
class CompetencyDistribution
{
private:
static bool hlevelSanitized;
public:
static std::vector<int> HLEVEL;
void linearDistribution(CSDVP &);
/**
* distribute realises the competency distribution according to the HLEVEL
*/
void distribute(CSDVP &);
// === STATIC
static int HLevelRange(CSDVP &); //return the range max (starting from 0) of the HL
static std::vector<Competency> getHLevel(CSDVP &, int); // returns all the competency of a given HL
static std::vector<Competency> upToHLevel(CSDVP &, int); // retrieves all the comp comprised between [0;int] (and NOT [0;int[)
static std::vector<Competency> unassignedAtHLevel(CSDVP &, int hlevel);
static std::vector<Competency> unassignedUpToHLevel(CSDVP &, int);
/*
* sanitizeHLEVEL performs two task:
* * it verifies that the sum of all HLEVEL is equal to 100
* * it resize the HLEVEL array, eliminating all unasigned value
*/
static void sanitizeHLEVEL();
static void displayHLevel();
};
#endif // SRC_COMPETENCY_DISTRIBUTION_H_
\ No newline at end of file
......@@ -8,7 +8,7 @@ std::pair<bool, double> ConstraintsECTS::integrityCheck(Cursus indiv)
int tmpECTS = 0;
//std::cout << "courses size : " << std::to_string(courses.size()) << std::endl;
//std::cout << "courses catl : " << std::to_string(this->_pb.cfg_quantityCourses()) << std::endl;
for(int i = 0; i < indiv.size(); i++)
for(unsigned int i = 0; i < indiv.size(); i++)
{
tmpECTS += courses.at(indiv[i]).ects();
//std::cout << std::to_string(courses.at(indiv[i]).ects()) << " + ";
......
......@@ -3,6 +3,7 @@
#include <vector>
#include <utility>
#include <tuple>
#include <eo>
......@@ -25,19 +26,37 @@ class ConstraintsPrerequisites
/**
* Checks the prerequisites prereqs in the competencies cInTF (generally, the competencies from the previous TF).
* It returns a std::pair, where the first element indicates how many prerequisites HAS NOT BEEN FOUND.
* It returns a std::tuple, where the first element indicates how many prerequisites HAS NOT BEEN FOUND.
* The second elements indicates how many prerequisites has not enought mastery (BUT EXISTS in cInTF!)
* The third element is the continous metric calculated accordingly the difference of mag between cours prereqs and comp mag
* The fourth element is to be used to divide the third one (how many elements contributed to establish the mag diff)
*/
std::pair<int,int> _prereqsInPreviousTF(std::vector<Competency> cInTF, std::vector<Competency> prereqs);
std::tuple<int,int, double, int> _prereqsInPreviousTF(std::vector<Competency> cInTF, std::vector<Competency> prereqs);
public:
static int DISCRETE_METRIC;
static int INTEGRITY_CHECK;
static int OVERFLOW_PERCENT;
ConstraintsPrerequisites(const CSDVP & csdvp, const Profession & job)
: _pb(csdvp), _job(job) {}
/** Integrity check is used to investigate wheteher or not one indiv respects the constraints represented by THIS.
* 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.
* @deprecated
* @todo Decay competency magnitude
*/
std::pair<bool, double> integrityCheck(Cursus indiv);
std::pair<bool, double> old_integrityCheck(Cursus indiv);
/**
* 2nd version of integrity check. Supposed to be more reliable and faster
*/
std::pair<bool, double> integrityCheck(Cursus indiv);
/**
* Displayer debug purpose. Display decayed array and non decayed array
* This is mostly a duplicata of integrityCheck without the prerequisite check and display
*/
void _displayDecayedArrays(Cursus indiv);
};
#endif // SRC_MODEL_CONSTRAINTS_PREREQUISITES_CONSTRAINTS_H_
\ No newline at end of file
......@@ -9,11 +9,13 @@
#include "model/exception/competencyEvolvingException.h"
int ConstraintsProfession::DISCRETE_METRIC = 1;
std::pair<bool, double> ConstraintsProfession::integrityCheck(Cursus indiv)
{
std::vector<Competency> compToAnswer;
for(int i = 0 ; i < this->_job.prerequisites().size(); i++)
for(unsigned int i = 0 ; i < this->_job.prerequisites().size(); i++)
{
std::string name = this->_job.prerequisites().at(i).c_name();
compToAnswer.push_back(Competency::buildTMP(0, name)); //same name to exploit the Competency::operator== on name equality
......@@ -26,7 +28,7 @@ std::pair<bool, double> ConstraintsProfession::integrityCheck(Cursus indiv)
bool changedTF = false;
int currentTF = 0;
for(int i = 0 ; i < indiv.size(); i++)
for(unsigned int i = 0 ; i < indiv.size(); i++)
{
current = this->_pb.coursesCatalogue().at(indiv.at(i));
......@@ -36,12 +38,12 @@ std::pair<bool, double> ConstraintsProfession::integrityCheck(Cursus indiv)
changedTF = false;
currentTF = i / this->_pb.cfg_pickedCoursesByTimeFrame();
for(int j = 0; j < compToAnswer.size(); j++)
for(unsigned int j = 0; j < compToAnswer.size(); j++)
{
compToAnswer.at(j).increaseDecay();
}
for(int j = 0 ; j < current.teachedCompetenciesWeighted().size() ; j++)
for(unsigned int j = 0 ; j < current.teachedCompetenciesWeighted().size() ; j++)
{
currentComp = current.teachedCompetenciesWeighted().at(j).first;
......@@ -63,7 +65,7 @@ std::pair<bool, double> ConstraintsProfession::integrityCheck(Cursus indiv)
}
}
for(int i = 0; i < compToAnswer.size(); i++)
for(unsigned int i = 0; i < compToAnswer.size(); i++)
{
compToAnswer.at(i).saveDecay();
//std::cout << compToAnswer.at(i) << std::endl;
......@@ -72,16 +74,26 @@ std::pair<bool, double> ConstraintsProfession::integrityCheck(Cursus indiv)
//Now that we have evolve all the tmp competency, we compate their mag to the requirement. We count how many is not met to define the metric
int score = 0;
for(int i = 0; i < this->_job.prerequisites().size(); i++)
double magDiff = 0; // addendum from HL
for(unsigned int i = 0; i < this->_job.prerequisites().size(); i++)
{
if(compToAnswer.at(i).magnitude().value() < this->_job.prerequisites().at(i).c_magnitude().value())
{
score++;
magDiff += ( this->_job.prerequisites().at(i).c_magnitude().value() - compToAnswer.at(i).magnitude().value() ) / this->_job.prerequisites().at(i).c_magnitude().value() ;
}
}
//std::cout << "Score: " << std::to_string(score) << std::endl;
//std::cout << "Size: " << std::to_string(compToAnswer.size()) << std::endl;
bool res = score == 0;
return std::pair<bool, double>(res, 1 - ( (double)score / (double)compToAnswer.size()));
switch (ConstraintsProfession::DISCRETE_METRIC) //whether we use discrete or continue metrics
{
case 0:
return std::pair<bool, double>(res, 1 - ( magDiff / (double)compToAnswer.size() ) );
default:
return std::pair<bool, double>(res, 1 - ( (double)score / (double)compToAnswer.size()));
}
}
......@@ -22,6 +22,8 @@ class ConstraintsProfession
Profession _job;
public:
static int DISCRETE_METRIC;
ConstraintsProfession(const CSDVP & csdvp, const Profession & job)
: _pb(csdvp), _job(job) {}
......
......@@ -6,9 +6,9 @@ std::pair<bool, double> ConstraintsRepetition::integrityCheck(Cursus indiv)
{
int nbOfRepetition = 0;
for(int i = 0; i < indiv.size(); i++)
for(unsigned int i = 0; i < indiv.size(); i++)
{
for(int j = i+1; j < indiv.size(); j++)
for(unsigned int j = i+1; j < indiv.size(); j++)
{
if(indiv.at(i) == indiv.at(j))
nbOfRepetition++;
......
......@@ -53,6 +53,15 @@ Course::Course(int id, int ects, std::string name)
// === GETTER
//cf. course.h
const int Course::lastTimeFrame() const
{
int max = this->_temporalAvailability[0];
for(unsigned int i = 1; i < this->_temporalAvailability.size(); i++)
if(max < this->_temporalAvailability[i])
max = this->_temporalAvailability[i];
return max;
}
// === END GETTER
// === MUTATOR
......
......@@ -81,6 +81,7 @@ class Course
std::vector<Competency>& unlocked_prerequisites() {return this->_prerequisites;}
const std::vector<int> timeFrame() const {return this->_temporalAvailability;}
const std::vector<std::pair<Competency, double>> teachedCompetenciesWeighted() const{return this->_weightedTeached;}
const int lastTimeFrame() const;
// === MUTATOR
// SETTER
......
......@@ -19,6 +19,7 @@ class DecayEngine
if(t == 0)
return 0;
return (exp(t / 1.25) + 5)/100;
//return (double)t/10;
}
};
......
......@@ -26,6 +26,7 @@ void CursusEval::operator()(Cursus & _cursus){
resCP=cp.integrityCheck(_cursus);
resCR=cr.integrityCheck(_cursus);
resCPR=cpr.integrityCheck(_cursus);
/*
std::cout << "EVAL: ";
std::cout << resCE.first << " " << resCE.second << std::endl;
......
......@@ -34,9 +34,9 @@ class eoInitConstraintCSDVP: public eoInit<EOT>
sizeTF=chromSize/nbTF;
catalogue = pb.coursesCatalogue();
possibleIDbyTF.resize(nbTF);
for(int i=0; i<maxVal; i++){
for(unsigned int i=0; i<maxVal; i++){
tmp=catalogue[i].timeFrame();
for(int j=0; j<tmp.size(); j++){
for(unsigned int j=0; j<tmp.size(); j++){
possibleIDbyTF[tmp[j]-pb.cfg_minimalTimeFrame()].push_back(i);
}
}
......@@ -50,13 +50,13 @@ class eoInitConstraintCSDVP: public eoInit<EOT>
}
virtual void operator()(EOT& chrom){
int cpt=0;
unsigned int cpt=0;
//std::cout << "Enter init" << std::endl;
unsigned int r=eo::rng.random(possibleIDbyTF[0].size());
chrom.resize(0);
chrom.push_back(possibleIDbyTF[0][r]);
//std::cout << "push " << possibleIDbyTF[0][r] << std::endl;
for(int i = 1; i < chromSize; i++){
for(unsigned int i = 1; i < chromSize; i++){
cpt=0;
r=eo::rng.random(possibleIDbyTF[i/sizeTF].size());
while(!notin(chrom, possibleIDbyTF[i/sizeTF][r], i) && cpt<maxVal){
......
......@@ -24,8 +24,8 @@ class mutCSDVP: public eoMonOp<EOT>
//_CourseID subastraction from _chrom
void notin(std::vector<int>& _courseID, std::vector<int>& _chrom){
int tmp;
for (int i=0; i<_chrom.size(); i++){
unsigned int tmp;
for (unsigned int i=0; i<_chrom.size(); i++){
tmp=0;
while(tmp<_courseID.size() && _chrom[i]!=_courseID[tmp])
tmp++;
......@@ -230,7 +230,7 @@ class mutCSDVP: public eoMonOp<EOT>
bool changedTF = false;
int currentTF = 0;
for(int i = 0; i < _chrom.size() && (i / nbCbyTF < TF); i++)
for(unsigned int i = 0; i < _chrom.size() && (i / nbCbyTF < TF); i++)
{
currentCourse = catalogue.at(_chrom.at(i));
......@@ -242,13 +242,13 @@ class mutCSDVP: public eoMonOp<EOT>
if(changedTF) //if we have changed of tf, lets improve decay for all comp
{
for(int j = 0; j < tmpCourse.prerequisites().size(); j++)
for(unsigned int j = 0; j < tmpCourse.prerequisites().size(); j++)
{
tmpCourse.unlocked_prerequisites().at(j).increaseDecay();
}
}
for(int j = 0; j < currentCourse.teachedCompetenciesWeighted().size(); j++)
for(unsigned int j = 0; j < currentCourse.teachedCompetenciesWeighted().size(); j++)
{
tmpComp = currentCourse.teachedCompetenciesWeighted().at(j).first;
addStatus = tmpCourse.addPrerequisite(tmpComp);
......@@ -275,7 +275,7 @@ class mutCSDVP: public eoMonOp<EOT>
}
compStatus = tmpCourse.prerequisites();
for(int i = 0; i < compStatus.size(); i++)
for(unsigned int i = 0; i < compStatus.size(); i++)
compStatus.at(i).saveDecay();
return compStatus;
......@@ -292,7 +292,7 @@ class mutCSDVP: public eoMonOp<EOT>
Competency checkCmp;
for(int i = 0; i < availableC.size(); i++)
for(unsigned int i = 0; i < availableC.size(); i++)
{
isPrereqOK = true;
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
#define SRC_PROBLEM_H_
#include <vector>
#include <tuple>
#include "course.h"
#include "competency.h"
......@@ -48,6 +49,8 @@ class CSDVP
Magnitude _minimalMagnitude;
Magnitude _maximalMagnitude;
int _thresholdMinMaxHLevel; // used for rand in prereq assign with HLevel
// ---------- END CONFIGURATION ATTRIBUTES ----------
// ---------- PROBLEM SPECIFIC ATTRIBUTES ----------
......@@ -56,7 +59,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 +88,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
......@@ -117,6 +128,7 @@ class CSDVP
int cfg_prerequisiteByCourseMin() const {return this->_minimalPrerequisiteByCourse;}
int cfg_prerequisiteByCourseMax() const {return this->_maximalPrerequisiteByCourse;}
int cfg_pickedCoursesByTimeFrame() const {return this->_pickedCoursesByTimeFrame;}
int cfg_thresholdHLevelMaxOverMin() const {return this->_thresholdMinMaxHLevel;}
const Magnitude & cfg_magnitudeMin() const{return this->_minimalMagnitude;}
const Magnitude & cfg_magnitudeMax() const{return this->_maximalMagnitude;}
......@@ -130,7 +142,8 @@ class CSDVP
std::vector<int> & unlocked_timeFrames(){return this->_timeFrames;}
std::vector<Course> & unlocked_coursesCatalogue(){return this->_availableCourses;}
std::vector<Competency> & unlocked_competenciesCatalogue(){return this->_availableCompentecies;}
std::vector<double> & unlocked_distributedCompetencies(){return this->_distributedCompetencies;}
int getQuantityCoursesToPick() const{
if(this->_isConfig)
return this->_timeFrames.size() * this->_pickedCoursesByTimeFrame;
......@@ -140,8 +153,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.*/
......@@ -161,6 +188,7 @@ class CSDVP
void set_cfg_minimalPrerequisiteByCourse(int nb);
void set_cfg_maximalPrerequisiteByCourse(int nb);
void set_cfg_pickedCoursesByTimeFrame(int nb);
void set_cfg_thresholdHLevelMaxOverMin(int thr);
void setTimeFrames(std::vector<int> & v);
void setCoursesCatalogue(std::vector<Course> &);
......
......@@ -6,10 +6,12 @@
#include "profession.h"
#include "competency.h"
#include "competencyDistribution.h"
#include "exception/JobOverlappingBoundariesException.h"
int Profession::PROFESSION_COUNTER = 0;
unsigned int Profession::JOB_SELECTION_TYPE = 0;
// === FACTORY
// No factory needed
......@@ -170,21 +172,52 @@ void Profession::_randomlyGenerate(Profession & job, CSDVP & pb)
std::random_shuffle(tmpComp.begin(), tmpComp.end());
int i;
for(i = 0; i < (int)tmpComp.size() && i < howManyPrereq; i++)
std::vector<Competency> compHigherHL;
switch (Profession::JOB_SELECTION_TYPE)
{
magVal = job.cfg_minimalMagnitude().value() + ( (double)rand()/RAND_MAX) * ( job.cfg_maximalMagnitude().value() - job.cfg_minimalMagnitude().value()) ;
ctmp = Competency::buildTMP(magVal,tmpComp.at(i).name());
case 1: //at least one comp in the higher HL
compHigherHL = CompetencyDistribution::getHLevel(pb, CompetencyDistribution::HLevelRange(pb)-1);
// std::cout << "compHigherHL size :" << compHigherHL.size() << std::endl;
std::random_shuffle(compHigherHL.begin(), compHigherHL.end());
assert(compHigherHL.size() > 0); //if no comp retrieved in the higher hlevel (hhl), there is a pb here !
magVal = job.cfg_minimalMagnitude().value() + ( (double)rand()/RAND_MAX) * ( job.cfg_maximalMagnitude().value() - job.cfg_minimalMagnitude().value()) ;
ctmp = Competency::buildTMP(magVal,compHigherHL.at(0).name());
ctmp.setHL(compHigherHL.at(0).hLevel());
job.addPrerequisite(ctmp);
}
if(i != howManyPrereq) //Warning need to check if still in range because not enought courses
{
if(i < job.cfg_minimalPrerequisites() || i > job.cfg_maximalPrerequisites())
// !! No duplicata protection: we can insert another time the competency above from the HHL
for(i = 0; i < (int)tmpComp.size() && i < howManyPrereq-1; i++) //cp/paste from default case
{
magVal = job.cfg_minimalMagnitude().value() + ( (double)rand()/RAND_MAX) * ( job.cfg_maximalMagnitude().value() - job.cfg_minimalMagnitude().value()) ;
ctmp = Competency::buildTMP(magVal,tmpComp.at(i).name());
ctmp.setHL(tmpComp.at(i).hLevel());
job.addPrerequisite(ctmp);
}
break;
case 2: // emphasis on higher HL
_pickWithHLWeighting(howManyPrereq, job, pb);
break;
default: //classic behavior
for(i = 0; i < (int)tmpComp.size() && i < howManyPrereq; i++)
{
//considering as a fail during generation
assert(i < job.cfg_minimalPrerequisites() || i > job.cfg_maximalPrerequisites());
magVal = job.cfg_minimalMagnitude().value() + ( (double)rand()/RAND_MAX) * ( job.cfg_maximalMagnitude().value() - job.cfg_minimalMagnitude().value()) ;
ctmp = Competency::buildTMP(magVal,tmpComp.at(i).name());
ctmp.setHL(tmpComp.at(i).hLevel());
job.addPrerequisite(ctmp);
}
if(i != howManyPrereq) //Warning need to check if still in range because not enought courses
{
if(i < job.cfg_minimalPrerequisites() || i > job.cfg_maximalPrerequisites())
{
//considering as a fail during generation
assert(i < job.cfg_minimalPrerequisites() || i > job.cfg_maximalPrerequisites());
}
}
break;
}
// If ECTS is set to be random, then calculating it
......@@ -210,6 +243,49 @@ void Profession::_randomlyGenerate(Profession & job, CSDVP & pb)
job.setRequiredECTS(ects);
}
// Here we weight where we pick the comp, the higher the HL, more likely a comp is to be pick
void Profession::_pickWithHLWeighting(int nbToPick, Profession & job, CSDVP & pb)
{
std::vector<int> range;
int sumInterval = 0;
int x; unsigned int currentHL;
double magVal;
Competency ctmp;
const int hLRange = CompetencyDistribution::HLevelRange(pb);
std::vector<Competency> hlComp;
for(int i = 0; i < hLRange ; i++)
{
// sumInterval+=i;
// sumInterval = i * 2;
sumInterval = i * i;
range.push_back(sumInterval);
}
for(int i = 0; i < nbToPick; i++)
{
x = rand() % ( sumInterval + 1);
assert(x <= sumInterval);
currentHL = 0;
// std::cout << "sumInterval: " << sumInterval << " & x: " << x << std::endl;
while(x > range[currentHL] && currentHL < range.size())
{
currentHL++;
}
hlComp = CompetencyDistribution::getHLevel(pb, currentHL);//we get the correspond hl level
assert(hlComp.size() > 0);
std::random_shuffle(hlComp.begin(), hlComp.end());
magVal = job.cfg_minimalMagnitude().value() + ( (double)rand()/RAND_MAX) * ( job.cfg_maximalMagnitude().value() - job.cfg_minimalMagnitude().value()) ;
ctmp = Competency::buildTMP(magVal,hlComp.at(0).name());
ctmp.setHL(hlComp.at(0).hLevel());
job.addPrerequisite(ctmp);
}
}
// === STATIC
int Profession::assignID(){return ++Profession::PROFESSION_COUNTER;}
......
......@@ -40,12 +40,16 @@ class Profession
/** _duplicataProtection returns true if the value (2nd param) searched into (1st param) is found*/
bool _duplicataProtection(std::vector<Competency> *, Competency);
static void _pickWithHLWeighting(int nbToPick, Profession &, CSDVP &);
// Static
static int PROFESSION_COUNTER;
static int assignID();
static void _randomlyGenerate(Profession & job, CSDVP & pb);
public:
static unsigned int JOB_SELECTION_TYPE;
enum GenerationType
{
RANDOM
......
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