Commit 168b0342 authored by Alexis Lebis's avatar Alexis Lebis

profession can now be randomly generated + display improv in main

Solve the #11 issue
parent aff894ab
...@@ -87,17 +87,28 @@ int main(int argc, char* argv[]){ ...@@ -87,17 +87,28 @@ int main(int argc, char* argv[]){
CSDVP::generateProblem(pb, CSDVP::GenerationType::RANDOM, 7777); CSDVP::generateProblem(pb, CSDVP::GenerationType::RANDOM, 7777);
assert(pb.checkConfig()); assert(pb.checkConfig());
job.setRequiredECTS(4 * 6); job.setRequiredECTS(Profession::GenerationType::RANDOM);
Competency tmpC = pb.competencyCatalogue().at(0); job.set_cfg_minimalPrerequisites(2);
tmpC = Competency::buildTMP(0.8, tmpC.c_name()); job.set_cfg_maximalPrerequisites(5);
job.addPrerequisite(tmpC); job.set_cfg_minimalMagnitude(0.8);
tmpC = pb.competencyCatalogue().at(1); job.set_cfg_maximalMagnitude(1.0);
tmpC = Competency::buildTMP(0.8, tmpC.c_name());
job.addPrerequisite(tmpC); Profession::generateProfession(job, Profession::GenerationType::RANDOM, pb, 7777);
tmpC = pb.competencyCatalogue().at(2); assert(job.checkConfig());
tmpC = Competency::buildTMP(0.8, tmpC.c_name()); std::cout << "JOB IS : \n" << job << std::endl;
job.addPrerequisite(tmpC);
// job.setRequiredECTS(4 * 6);
// Competency tmpC = pb.competencyCatalogue().at(0);
// tmpC = Competency::buildTMP(0.8, tmpC.c_name());
// job.addPrerequisite(tmpC);
// tmpC = pb.competencyCatalogue().at(1);
// tmpC = Competency::buildTMP(0.8, tmpC.c_name());
// job.addPrerequisite(tmpC);
// tmpC = pb.competencyCatalogue().at(2);
// tmpC = Competency::buildTMP(0.8, tmpC.c_name());
// job.addPrerequisite(tmpC);
//tmpC = Competency::build(0.5,"Wesh"); //tmpC = Competency::build(0.5,"Wesh");
//job.addPrerequisite(tmpC); //job.addPrerequisite(tmpC);
//tmpC = pb.competencyCatalogue().at(8); //tmpC = pb.competencyCatalogue().at(8);
...@@ -247,20 +258,54 @@ int main(int argc, char* argv[]){ ...@@ -247,20 +258,54 @@ int main(int argc, char* argv[]){
std::cout << "===== CURRENT POP =====" << std::endl; std::cout << "===== CURRENT POP =====" << std::endl;
pop.best_element().printOn(std::cout); pop.best_element().printOn(std::cout);
std::cout << "===== =====" << std::endl; std::cout << " fitness:" << pop.best_element().fitness() << std::endl;
std::cout << "Stats & metrics: \n" << std::endl;
std::pair<bool, double> resECTS = ctrECTS.integrityCheck(pop.best_element());
std::pair<bool, double> resRep = ctrRep.integrityCheck(pop.best_element());
std::pair<bool, double> resJob = ctrJob.integrityCheck(pop.best_element());
std::pair<bool, double> resPrq = ctrPrq.integrityCheck(pop.best_element());
std::cout << "ECTS: ";
if(resECTS.first)
std::cout << "succeed";
else
std::cout << "failed";
std::cout << " | value: " << resECTS.second << std::endl;
std::cout << "Repetition: ";
if(resRep.first)
std::cout << "succeed";
else
std::cout << "failed";
std::cout << " | value: " << resRep.second << std::endl;
std::cout << "Job: ";
if(resJob.first)
std::cout << "succeed";
else
std::cout << "failed";
std::cout << " | value: " << resJob.second << std::endl;
std::cout << "Prereq: ";
if(resPrq.first)
std::cout << "succeed";
else
std::cout << "failed";
std::cout << " | value: " << resPrq.second << std::endl;
std::cout << "\n==========" << std::endl;
eoEasyEA<QUEEN> algo(cont,eval,select,transform,replace); eoEasyEA<QUEEN> algo(cont,eval,select,transform,replace);
algo(pop); algo(pop);
std::cout << "===== BEST INDIVIDU =====" << std::endl; std::cout << "\n===== BEST INDIVIDU =====" << std::endl;
pop.best_element().printOn(std::cout); pop.best_element().printOn(std::cout);
std::cout << " fitness:" << pop.best_element().fitness() << std::endl; std::cout << " fitness:" << pop.best_element().fitness() << std::endl;
std::cout << "Stats & metrics: \n" << std::endl; std::cout << "Stats & metrics: \n" << std::endl;
std::pair<bool, double> resECTS = ctrECTS.integrityCheck(pop.best_element()); resECTS = ctrECTS.integrityCheck(pop.best_element());
std::pair<bool, double> resRep = ctrRep.integrityCheck(pop.best_element()); resRep = ctrRep.integrityCheck(pop.best_element());
std::pair<bool, double> resJob = ctrJob.integrityCheck(pop.best_element()); resJob = ctrJob.integrityCheck(pop.best_element());
std::pair<bool, double> resPrq = ctrPrq.integrityCheck(pop.best_element()); resPrq = ctrPrq.integrityCheck(pop.best_element());
std::cout << "ECTS: "; std::cout << "ECTS: ";
if(resECTS.first) if(resECTS.first)
...@@ -290,7 +335,6 @@ int main(int argc, char* argv[]){ ...@@ -290,7 +335,6 @@ int main(int argc, char* argv[]){
std::cout << "failed"; std::cout << "failed";
std::cout << " | value: " << resPrq.second << std::endl; std::cout << " | value: " << resPrq.second << std::endl;
std::cout << "===============" << std::endl; std::cout << "===============" << std::endl;
std::cout << "cpt: " << cross.cpt << std::endl; std::cout << "cpt: " << cross.cpt << std::endl;
......
#ifndef SRC_MODEL_EXCEPTION_JOB_OVERLAPING_BOUNDARIES_EXCEPTION_H_
#define SRC_MODEL_EXCEPTION_JOB_OVERLAPING_BOUNDARIES_EXCEPTION_H_
#include <exception>
#include <iostream>
#include <string>
#include "../profession.h"
class JobOverlappingBoundariesException : public std::exception
{
private:
Profession * _job;
std::string _msg;
public:
JobOverlappingBoundariesException(Profession * pb) throw()
: _job(pb)
{
this->_msg = "Boundaries of the Profession (aka Job) (id:"+std::to_string(pb->id())+") are overlaping.";
}
~JobOverlappingBoundariesException() throw()
{ delete(this->_job); }
virtual const char* what() const throw()
{return this->_msg.c_str();}
Profession & getCSDVP() {return *(this->_job);}
};
#endif // SRC_MODEL_EXCEPTION_JOB_OVERLAPING_BOUNDARIES_EXCEPTION_H_
\ No newline at end of file
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "profession.h" #include "profession.h"
#include "competency.h" #include "competency.h"
#include "exception/JobOverlappingBoundariesException.h"
int Profession::PROFESSION_COUNTER = 0; int Profession::PROFESSION_COUNTER = 0;
// === FACTORY // === FACTORY
...@@ -62,6 +64,25 @@ int Profession::PROFESSION_COUNTER = 0; ...@@ -62,6 +64,25 @@ int Profession::PROFESSION_COUNTER = 0;
this->_requiredECTS = nb; this->_requiredECTS = nb;
} }
void Profession::setRequiredECTS(Profession::GenerationType type)
{
if(type == Profession::GenerationType::RANDOM)
this->_isECTSRandom = true;
}
void Profession::set_cfg_minimalPrerequisites(int nb)
{this->_minimalPrerequisites = nb;}
void Profession::set_cfg_maximalPrerequisites(int nb)
{this->_maximalPrerequisites = nb;}
void Profession::set_cfg_minimalMagnitude(double mag)
{
this->_minimalMagnitude = Magnitude::build(mag);
}
void Profession::set_cfg_maximalMagnitude(double mag)
{
this->_maximalMagnitude = Magnitude::build(mag);
}
// ADDER // ADDER
/** Adds a new competency to the prerequisites of a profession. It is protected against duplicata: it can't have twice the same competency. /** Adds a new competency to the prerequisites of a profession. It is protected against duplicata: it can't have twice the same competency.
* *
...@@ -89,10 +110,127 @@ int Profession::PROFESSION_COUNTER = 0; ...@@ -89,10 +110,127 @@ int Profession::PROFESSION_COUNTER = 0;
// === OPERATOR // === OPERATOR
std::ostream & operator<<(std::ostream & Stream, const Profession & p) std::ostream & operator<<(std::ostream & Stream, const Profession & p)
{ {
std::string s = "Profession\n\tid:"+std::to_string(p.id())+"\n\tname:"+p.name()+"\n\t#Prereq:"+std::to_string(p.prerequisites().size()); std::string s = "Profession\n\tid:"+std::to_string(p.id())+"\n\tName:"+p.name()+"\n\tECTS: " + std::to_string(p.requiredECTS()) +"\n\t#Prereq:"+std::to_string(p.prerequisites().size())+"\n\t===Details:===\n\t";
Stream << s; Stream << s ;
for(int i = 0; i < p.prerequisites().size(); i++)
Stream << "("<< i<< "th) " << p.prerequisites().at(i) << "\n\t";
Stream << "==========" << std::endl;
return Stream; return Stream;
} }
bool Profession::checkConfig()
{
if( !this->_isECTSRandom && this->_requiredECTS <= 0)
{
this->_isConfig = false;
std::cout << "INFO: Profession lacks ECTS config" << std::endl;
return false;
}
if(this->_name.empty())
{
this->_isConfig = false;
std::cout << "INFO: Profession lacks name config" << std::endl;
return false;
}
if( this->_minimalPrerequisites < 0 ||
this->_maximalPrerequisites < 0 ||
this->_minimalMagnitude.value() < 0 ||
this->_maximalMagnitude.value() < 0 )
{
std::cout << "INFO: Config attributes not yet config" << std::endl;
this->_isConfig = false;
return false;
}
//verifying overlapping range
if( this->_minimalPrerequisites > this->_maximalPrerequisites ||
this->_minimalMagnitude.value() > this->_maximalMagnitude.value())
{
throw JobOverlappingBoundariesException(this);
}
this->_isConfig = true;
return true;
}
void Profession::_randomlyGenerate(Profession & job, CSDVP & pb)
{
srand(job.seed());
job.unlocked_prerequisites().clear();
int howManyPrereq = job.cfg_minimalPrerequisites() + ( rand() % ( job.cfg_maximalPrerequisites() - job.cfg_minimalPrerequisites() + 1) );
std::vector<Competency> tmpComp = pb.competencyCatalogue();
Competency ctmp;
double magVal;
std::random_shuffle(tmpComp.begin(), tmpComp.end());
int i;
for(i = 0; i < tmpComp.size() && i < howManyPrereq; i++)
{
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());
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());
}
}
// If ECTS is set to be random, then calculating it
if(!job._isECTSRandom)
return;
// Formula of ECTS calcul is : SIGMA_{i=0}^{maxTF}(SIGMA_{j=0}^{nbCourseAvg}(rand(pb.minECTS,pb.maxECTS)))
int ects= 0;
// ects = pb.timeFrames().size() * 30; //30 is the default european value
for(i = 0; i < pb.timeFrames().size(); i++)
{
for(int j = 0; j < pb.cfg_pickedCoursesByTimeFrame(); j++)
{
if( (rand() % 100) > 35) //Take the average in 100-35 % of the cases
ects += ( pb.cfg_ectsMin() + rand() % (pb.cfg_ectsMax() - pb.cfg_ectsMin() +1) );
else
ects += ( pb.cfg_ectsMin() + rand() % ( (pb.cfg_ectsMax() -1) - pb.cfg_ectsMin() +1) );
}
}
job.setRequiredECTS(ects);
}
// === STATIC // === STATIC
int Profession::assignID(){return ++Profession::PROFESSION_COUNTER;} int Profession::assignID(){return ++Profession::PROFESSION_COUNTER;}
\ No newline at end of file
// ---------- GENERATION FUNCTIONS ----------
void Profession::generateProfession(Profession & job, Profession::GenerationType type, CSDVP & csdvp, int seed)
{
job._seed = seed;
if( !job.checkConfig() || !csdvp.checkConfig())
{
std::cout << "Can't generate a profession with non configurated problem and profession !" << std::endl;
return;
}
switch (type)
{
case Profession::GenerationType::RANDOM:
_randomlyGenerate(job, csdvp);
break;
default:
break;
}
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include "competency.h" #include "competency.h"
#include "problem.h"
/** /**
* A profession is a job sought by a student. * A profession is a job sought by a student.
...@@ -13,11 +14,27 @@ ...@@ -13,11 +14,27 @@
class Profession class Profession
{ {
private: private:
std::vector<Competency> _prerequisites; // ---------- CONFIGURATION ATTRIBUTES ---------
std::string _name; std::string _name;
int _requiredECTS = -1;
int _minimalPrerequisites = -1;
int _maximalPrerequisites = -1;
Magnitude _minimalMagnitude;
Magnitude _maximalMagnitude;
// ---------- END CONFIGURATIONS ATTRIBUTES ----------
// ---------- PROFESSION SPECIFIC ATTRIBUTES ----------
std::vector<Competency> _prerequisites;
// ---------- END PROFESSION SPECIFIC ATTRIBUTES
int _id; int _id;
int _seed;
int _requiredECTS; /// Use to determine if Profession has been config by the user.
bool _isConfig;
bool _isECTSRandom =false;
// === FUNC // === FUNC
/** _duplicataProtection returns true if the value (2nd param) searched into (1st param) is found*/ /** _duplicataProtection returns true if the value (2nd param) searched into (1st param) is found*/
...@@ -26,20 +43,41 @@ class Profession ...@@ -26,20 +43,41 @@ class Profession
// Static // Static
static int PROFESSION_COUNTER; static int PROFESSION_COUNTER;
static int assignID(); static int assignID();
static void _randomlyGenerate(Profession & job, CSDVP & pb);
public: public:
enum GenerationType
{
RANDOM
//PRESET
};
Profession(); Profession();
Profession(std::string name); Profession(std::string name);
Profession(std::vector<Competency> & p, std::string n = ""); Profession(std::vector<Competency> & p, std::string n = "");
/** Generates the profession configuration. ECTS still needs to be filled before calling this function.
* Nonetheless, progession _prerequisites are taken randomly in the problem
*/
static void generateProfession(Profession & job, Profession::GenerationType type, CSDVP & csdvp, int seed = 0);
/**Checks the configuration of a profession, mostly before performing a generation.*/
bool checkConfig();
// === GETTER // === GETTER
const int id() const{return this->_id;} const int id() const{return this->_id;}
const int seed() const{return this->_seed;}
const int requiredECTS() const{return this->_requiredECTS;} const int requiredECTS() const{return this->_requiredECTS;}
const std::string name() const{return this->_name;} const std::string name() const{return this->_name;}
const std::vector<Competency> & prerequisites() const{return this->_prerequisites;} const std::vector<Competency> & prerequisites() const{return this->_prerequisites;}
/// return a modifiable reference to _prerequisite; /// return a modifiable reference to _prerequisite;
std::vector<Competency> & unlocked_prerequisites(){return this->_prerequisites;} std::vector<Competency> & unlocked_prerequisites(){return this->_prerequisites;}
const int cfg_minimalPrerequisites() const{return this->_minimalPrerequisites;}
const int cfg_maximalPrerequisites() const{return this->_maximalPrerequisites;}
const Magnitude cfg_minimalMagnitude() const{return this->_minimalMagnitude;}
const Magnitude cfg_maximalMagnitude() const{return this->_maximalMagnitude;}
// === MUTATOR // === MUTATOR
// SETTER // SETTER
/// Set name of the profession. If name empty, creates a default name based on ID /// Set name of the profession. If name empty, creates a default name based on ID
...@@ -47,9 +85,15 @@ class Profession ...@@ -47,9 +85,15 @@ class Profession
/// Set the prerequisites of a profession. The old prereq is returned. /// Set the prerequisites of a profession. The old prereq is returned.
std::vector<Competency> & setPrerequisites(std::vector<Competency> & v); std::vector<Competency> & setPrerequisites(std::vector<Competency> & v);
void setRequiredECTS(int ects); void setRequiredECTS(int ects);
void setRequiredECTS(Profession::GenerationType type);
// ADDER // ADDER
bool addPrerequisite(Competency &); bool addPrerequisite(Competency &);
void set_cfg_minimalPrerequisites(int nb);
void set_cfg_maximalPrerequisites(int nb);
void set_cfg_minimalMagnitude(double mag);
void set_cfg_maximalMagnitude(double mag);
}; };
// === OPERATOR // === OPERATOR
......
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