From 3113a8a5f242580368329a06ea69a0bcd75fd9e5 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 6 Feb 2019 11:49:33 +0000 Subject: [PATCH 01/48] Add README to SMTI algorithms --- SMTI/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 SMTI/README.md diff --git a/SMTI/README.md b/SMTI/README.md new file mode 100644 index 0000000..5d87cd7 --- /dev/null +++ b/SMTI/README.md @@ -0,0 +1,14 @@ +# Naming + +The following table relates these folders to the names used in the paper + +| Folder name | Algorithm index in paper +|-------------|-------------------------| +|1_NOBIN_1STA_NOMERGED | M1 | +|2_YESBIN_1STA_NOMERGED | M2 | +|3_NOBIN_1STA_YESMERGED | M3 | +|4_YESBIN_1STA_YESMERGED | M4 | +|7_NOBIN_2STA_YESMERGED | M5 | +|8_YESBIN_2STA_YESMERGED | M6 | + +The folder 1_NOBIN_1STA_NOMERGED_NOPRE is M1 but with preprocessing disabled. From 145d48088ec9dbb0e3cdc7a87e29654ee8f5c84f Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 7 Feb 2019 09:27:34 +0000 Subject: [PATCH 02/48] Preprocessing: first run --- .../1_NOBIN_1STA_NOMERGED/AgentIterator.cpp | 223 ++++++++++ .../1_NOBIN_1STA_NOMERGED/AgentIterator.h | 54 +++ SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp | 399 ++++-------------- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h | 26 +- SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp | 9 +- SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.h | 2 +- SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile | 8 +- 7 files changed, 365 insertions(+), 356 deletions(-) create mode 100644 SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp create mode 100644 SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp new file mode 100644 index 0000000..48e688f --- /dev/null +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp @@ -0,0 +1,223 @@ +#include "AgentIterator.h" + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return _group == other.get_group() && _position == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(_group, _position); +} + +AgentIterator& AgentIterator::operator++() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return *this; +} + +AgentIterator AgentIterator::operator++(int) { + AgentIterator ret = *this; + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = -1; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return ret; +} + +AgentIterator AgentIterator::begin() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); +} + +AgentIterator AgentIterator::end() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); +} + +int AgentIterator::get_group() const { + return _group; +} + +int AgentIterator::get_position() const { + return _position; +} + + +template +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +template +SkipBigIterator& SkipBigIterator::operator++() { + int num_added; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return *this; +} + +template +SkipBigIterator SkipBigIterator::operator++(int) { + SkipBigIterator ret = *this; + int num_added = 0; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return ret; +} + +template class SkipBigIterator<5>; + + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +BestIterator& BestIterator::operator++() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return *this; +} + +BestIterator BestIterator::operator++(int) { + BestIterator ret = *this; + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return ret; +} diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h new file mode 100644 index 0000000..d866b4d --- /dev/null +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h @@ -0,0 +1,54 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + + class AgentIterator : public std::iterator, ptrdiff_t> { + public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++(); + AgentIterator operator++(int); + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + + protected: + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; + }; + +template +class SkipBigIterator : public AgentIterator { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + SkipBigIterator& operator++(); + SkipBigIterator operator++(int); +}; + +class BestIterator : public AgentIterator { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + BestIterator& operator++(); + BestIterator operator++(int); +}; + + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp index 9d5dec4..e196e56 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp @@ -1,4 +1,5 @@ #include "Allocation.h" +#include "AgentIterator.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -18,24 +19,6 @@ void Child::print(){ cout << endl; } -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - /* ************************************************************************************* ********************************** ALLOCATION *************************************** ************************************************************************************* */ @@ -163,312 +146,83 @@ void Allocation::printProb(){ } } -int Allocation::reductionFam1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + int number_here = nbChildren; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + } else { + thesep = &families; + otherp = &children; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + unsigned int count = 0; + AgentIterator *iter; + switch (mode) { + default: + case 0: + iter = new AgentIterator(these[i], candidates, positions, these, other); + break; + case 1: + iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); + break; + case 2: + iter = new BestIterator(these[i], candidates, positions, these, other); break; - } } - } - - for(int i=0; i p: *iter) { + int j = p.first; + int k = p.second; + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi2(){ - - int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j= candidates.size()) { + for (int k = j + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } } - } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + these[i].nbPref = j + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } + delete iter; } - - for(int i=0; i class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -31,21 +31,6 @@ void print(); }; -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - /* ************************************************************************************* ************************************* INFO ****************************************** ************************************************************************************* */ @@ -90,16 +75,13 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp index 3411d94..20473db 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp @@ -12,12 +12,13 @@ int main(int argc, char **argv){ string path = argv[1]; string pathAndFileout = argv[3]; int minGrade = atoi(argv[4]); + int mode = atoi(argv[5]); // functions allo.load(path,filein,minGrade); - allo.printProb(); + //allo.printProb(); - manlove(allo); + manlove(allo, mode); allo.printSol(); allo.checkSolution(); @@ -25,11 +26,11 @@ int main(int argc, char **argv){ } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int reduction_mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); - allo.reduction(); + allo.reduction(reduction_mode); allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.h +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile index f555425..f1f248e 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile @@ -1,21 +1,21 @@ SYSTEM = x86-64_sles10_4.1 LIBFORMAT = static_pic -GUROBI_DIR = /users/grad/wpette/opt/gurobi752/linux64 +GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 INC = $(GUROBI_DIR)/include/ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o NOBIN_1STA_NOMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +%.o : %.cpp $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : From eab2d8556f8ca10befce756c538d17f4d8169f86 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 7 Feb 2019 10:43:28 +0000 Subject: [PATCH 03/48] Updates to preprocessing, ready for tests --- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp | 4 +- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h | 1 + SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile | 2 +- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 223 ++++++++++ .../4_YESBIN_1STA_YESMERGED/AgentIterator.h | 54 +++ .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 403 ++++-------------- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 27 +- SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp | 11 +- SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.h | 2 +- SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile | 4 +- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 223 ++++++++++ SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h | 54 +++ SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 403 ++++-------------- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h | 27 +- SMTI/3_NOBIN_1STA_YESMERGED/main.cpp | 15 +- SMTI/3_NOBIN_1STA_YESMERGED/main.h | 2 +- SMTI/3_NOBIN_1STA_YESMERGED/makefile | 8 +- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 223 ++++++++++ SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h | 54 +++ SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 403 ++++-------------- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h | 27 +- SMTI/4_YESBIN_1STA_YESMERGED/main.cpp | 11 +- SMTI/4_YESBIN_1STA_YESMERGED/main.h | 2 +- SMTI/4_YESBIN_1STA_YESMERGED/makefile | 8 +- 24 files changed, 1115 insertions(+), 1076 deletions(-) create mode 100644 SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp create mode 100644 SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp index e196e56..31da961 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp @@ -286,6 +286,7 @@ void Allocation::polish(){ } void Allocation::reduction(int mode){ + total_reduced = 0; int i = 0; int num = 0; do{ @@ -293,6 +294,7 @@ void Allocation::reduction(int mode){ num += reductionMine(false, mode); cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; + total_reduced += num; }while(num != 0); } @@ -306,7 +308,7 @@ void Allocation::printSol(){ void Allocation::printInfo(const string& pathAndFileout){ string nameFile = pathAndFileout; std::ofstream file(nameFile.c_str(), std::ios::out | std::ios::app); - file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t"<< infos.LB << "\t" << infos.UB << "\t" << infos.altInfo << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ + file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t" << total_reduced << "\t"<< infos.LB << "\t" << infos.UB << "\t" << infos.altInfo << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ << "\t" << infos.contUB2 << "\t" << infos.nbVar2 << "\t" << infos.nbCons2 << "\t" << infos.nbNZ2 << endl; file.close(); } diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h index 6397216..8f374de 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h @@ -62,6 +62,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector > grades; vector children; diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile index f1f248e..92551af 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/makefile @@ -1,7 +1,7 @@ SYSTEM = x86-64_sles10_4.1 LIBFORMAT = static_pic -GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 +GUROBI_DIR = /users/grad/wpette/opt/gurobi752/linux64 CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 INC = $(GUROBI_DIR)/include/ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp new file mode 100644 index 0000000..48e688f --- /dev/null +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -0,0 +1,223 @@ +#include "AgentIterator.h" + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return _group == other.get_group() && _position == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(_group, _position); +} + +AgentIterator& AgentIterator::operator++() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return *this; +} + +AgentIterator AgentIterator::operator++(int) { + AgentIterator ret = *this; + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = -1; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return ret; +} + +AgentIterator AgentIterator::begin() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); +} + +AgentIterator AgentIterator::end() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); +} + +int AgentIterator::get_group() const { + return _group; +} + +int AgentIterator::get_position() const { + return _position; +} + + +template +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +template +SkipBigIterator& SkipBigIterator::operator++() { + int num_added; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return *this; +} + +template +SkipBigIterator SkipBigIterator::operator++(int) { + SkipBigIterator ret = *this; + int num_added = 0; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return ret; +} + +template class SkipBigIterator<5>; + + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +BestIterator& BestIterator::operator++() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return *this; +} + +BestIterator BestIterator::operator++(int) { + BestIterator ret = *this; + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return ret; +} diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h new file mode 100644 index 0000000..d866b4d --- /dev/null +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -0,0 +1,54 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + + class AgentIterator : public std::iterator, ptrdiff_t> { + public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++(); + AgentIterator operator++(int); + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + + protected: + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; + }; + +template +class SkipBigIterator : public AgentIterator { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + SkipBigIterator& operator++(); + SkipBigIterator operator++(int); +}; + +class BestIterator : public AgentIterator { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + BestIterator& operator++(); + BestIterator operator++(int); +}; + + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 9d5dec4..eedcdbf 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -1,4 +1,5 @@ #include "Allocation.h" +#include "AgentIterator.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -18,24 +19,6 @@ void Child::print(){ cout << endl; } -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - /* ************************************************************************************* ********************************** ALLOCATION *************************************** ************************************************************************************* */ @@ -163,312 +146,83 @@ void Allocation::printProb(){ } } -int Allocation::reductionFam1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + int number_here = nbChildren; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + } else { + thesep = &families; + otherp = &children; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + unsigned int count = 0; + AgentIterator *iter; + switch (mode) { + default: + case 0: + iter = new AgentIterator(these[i], candidates, positions, these, other); + break; + case 1: + iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); + break; + case 2: + iter = new BestIterator(these[i], candidates, positions, these, other); break; - } } - } - - for(int i=0; i p: *iter) { + int j = p.first; + int k = p.second; + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi2(){ - - int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j= candidates.size()) { + for (int k = j + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } } - } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + these[i].nbPref = j + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } + delete iter; } - - for(int i=0; i class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -31,21 +31,6 @@ void print(); }; -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - /* ************************************************************************************* ************************************* INFO ****************************************** ************************************************************************************* */ @@ -77,6 +62,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector > grades; vector children; @@ -90,16 +76,13 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp index b211b18..acee890 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp @@ -12,12 +12,13 @@ int main(int argc, char **argv){ string path = argv[1]; string pathAndFileout = argv[3]; int minGrade = atoi(argv[4]); + int mode = atoi(argv[5]); // functions allo.load(path,filein,minGrade); - allo.printProb(); + //allo.printProb(); - manlove(allo); + manlove(allo, mode); allo.printSol(); allo.checkSolution(); @@ -25,13 +26,13 @@ int main(int argc, char **argv){ } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(); - allo.printProb(); + allo.reduction(mode); + //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; // Model diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile index d362afe..762822f 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile @@ -8,9 +8,9 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_1STA_NOMERGED $(OBJECTS) $(GUROBI_OPTS) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp new file mode 100644 index 0000000..48e688f --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -0,0 +1,223 @@ +#include "AgentIterator.h" + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return _group == other.get_group() && _position == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(_group, _position); +} + +AgentIterator& AgentIterator::operator++() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return *this; +} + +AgentIterator AgentIterator::operator++(int) { + AgentIterator ret = *this; + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = -1; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return ret; +} + +AgentIterator AgentIterator::begin() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); +} + +AgentIterator AgentIterator::end() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); +} + +int AgentIterator::get_group() const { + return _group; +} + +int AgentIterator::get_position() const { + return _position; +} + + +template +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +template +SkipBigIterator& SkipBigIterator::operator++() { + int num_added; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return *this; +} + +template +SkipBigIterator SkipBigIterator::operator++(int) { + SkipBigIterator ret = *this; + int num_added = 0; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return ret; +} + +template class SkipBigIterator<5>; + + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +BestIterator& BestIterator::operator++() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return *this; +} + +BestIterator BestIterator::operator++(int) { + BestIterator ret = *this; + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return ret; +} diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h new file mode 100644 index 0000000..d866b4d --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h @@ -0,0 +1,54 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + + class AgentIterator : public std::iterator, ptrdiff_t> { + public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++(); + AgentIterator operator++(int); + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + + protected: + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; + }; + +template +class SkipBigIterator : public AgentIterator { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + SkipBigIterator& operator++(); + SkipBigIterator operator++(int); +}; + +class BestIterator : public AgentIterator { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + BestIterator& operator++(); + BestIterator operator++(int); +}; + + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index 44a6851..91f10dd 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -1,4 +1,5 @@ #include "Allocation.h" +#include "AgentIterator.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -18,24 +19,6 @@ void Child::print(){ cout << endl; } -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - /* ************************************************************************************* ********************************** ALLOCATION *************************************** ************************************************************************************* */ @@ -237,312 +220,83 @@ void Allocation::printProb(){ } } -int Allocation::reductionFam1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - +int Allocation::reductionMine(bool children_side, int mode) { int nbTotRem = 0; - - for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + int number_here = nbChildren; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + } else { + thesep = &families; + otherp = &children; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + unsigned int count = 0; + AgentIterator *iter; + switch (mode) { + default: + case 0: + iter = new AgentIterator(these[i], candidates, positions, these, other); + break; + case 1: + iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); + break; + case 2: + iter = new BestIterator(these[i], candidates, positions, these, other); break; - } } - } - - for(int i=0; i p: *iter) { + int j = p.first; + int k = p.second; + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi2(){ - - int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j= candidates.size()) { + for (int k = j + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } } - } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + these[i].nbPref = j + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } + delete iter; } - - for(int i=0; i class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -31,21 +31,6 @@ void print(); }; -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - /* ************************************************************************************* ************************************* INFO ****************************************** ************************************************************************************* */ @@ -76,6 +61,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector children; vector families; @@ -88,16 +74,13 @@ void load(const string& path, const string& filein); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp index 143da32..892a257 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp @@ -11,14 +11,15 @@ int main(int argc, char **argv){ string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); // functions allo.load(path,filein); - allo.printProb(); - allo.reduction(); - allo.printProb(); + //allo.printProb(); + //allo.reduction(); + //allo.printProb(); - manlove(allo); + manlove(allo, mode); allo.printSol(); allo.checkSolution(); @@ -26,13 +27,13 @@ int main(int argc, char **argv){ } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(); - allo.printProb(); + allo.reduction(mode); + //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; // Model diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/main.h b/SMTI/3_NOBIN_1STA_YESMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/main.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/makefile b/SMTI/3_NOBIN_1STA_YESMERGED/makefile index 662a970..f0fc99d 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/makefile +++ b/SMTI/3_NOBIN_1STA_YESMERGED/makefile @@ -8,15 +8,15 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o exec : $(OBJECTS) - $(CC) $(CFLAGS) -o MANLOVE_REDUCTION $(OBJECTS) $(GUROBI_OPTS) + $(CC) $(CFLAGS) -o 3_NOBIN_1STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) .cpp.o : $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : - rm -f $(OBJECTS) MANLOVE_REDUCTION + rm -f $(OBJECTS) 3_NOBIN_1STA_YESMERGED diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp new file mode 100644 index 0000000..48e688f --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -0,0 +1,223 @@ +#include "AgentIterator.h" + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return _group == other.get_group() && _position == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(_group, _position); +} + +AgentIterator& AgentIterator::operator++() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return *this; +} + +AgentIterator AgentIterator::operator++(int) { + AgentIterator ret = *this; + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = -1; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } + return ret; +} + +AgentIterator AgentIterator::begin() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); +} + +AgentIterator AgentIterator::end() { + return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); +} + +int AgentIterator::get_group() const { + return _group; +} + +int AgentIterator::get_position() const { + return _position; +} + + +template +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +template +SkipBigIterator& SkipBigIterator::operator++() { + int num_added; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return *this; +} + +template +SkipBigIterator SkipBigIterator::operator++(int) { + SkipBigIterator ret = *this; + int num_added = 0; + do { + AgentIterator::operator++(); + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + for(auto group: _other[other_id].preferences) { + bool found = false; + for(auto pref: group) { + if (_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + } while ((*this != end()) && num_added > step); + return ret; +} + +template class SkipBigIterator<5>; + + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIterator(agent, candidates, positions, these, other, group, posn) { + } + +BestIterator& BestIterator::operator++() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return *this; +} + +BestIterator BestIterator::operator++(int) { + BestIterator ret = *this; + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool found = false; + for(auto & other_group: _other[other_id].preferences) { + for(auto other_pref: other_group) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == _agent.id) { + found = true; + } + } + if (found) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = -1; + } + return ret; +} diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h new file mode 100644 index 0000000..d866b4d --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -0,0 +1,54 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + + class AgentIterator : public std::iterator, ptrdiff_t> { + public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++(); + AgentIterator operator++(int); + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + + protected: + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; + }; + +template +class SkipBigIterator : public AgentIterator { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + SkipBigIterator& operator++(); + SkipBigIterator operator++(int); +}; + +class BestIterator : public AgentIterator { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + BestIterator& operator++(); + BestIterator operator++(int); +}; + + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 44a6851..91f10dd 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -1,4 +1,5 @@ #include "Allocation.h" +#include "AgentIterator.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -18,24 +19,6 @@ void Child::print(){ cout << endl; } -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - /* ************************************************************************************* ********************************** ALLOCATION *************************************** ************************************************************************************* */ @@ -237,312 +220,83 @@ void Allocation::printProb(){ } } -int Allocation::reductionFam1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - +int Allocation::reductionMine(bool children_side, int mode) { int nbTotRem = 0; - - for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + int number_here = nbChildren; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + } else { + thesep = &families; + otherp = &children; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + unsigned int count = 0; + AgentIterator *iter; + switch (mode) { + default: + case 0: + iter = new AgentIterator(these[i], candidates, positions, these, other); + break; + case 1: + iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); + break; + case 2: + iter = new BestIterator(these[i], candidates, positions, these, other); break; - } } - } - - for(int i=0; i p: *iter) { + int j = p.first; + int k = p.second; + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi2(){ - - int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j= candidates.size()) { + for (int k = j + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } } - } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + these[i].nbPref = j + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } + delete iter; } - - for(int i=0; i class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -31,21 +31,6 @@ void print(); }; -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - /* ************************************************************************************* ************************************* INFO ****************************************** ************************************************************************************* */ @@ -76,6 +61,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector children; vector families; @@ -88,16 +74,13 @@ void load(const string& path, const string& filein); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp index b2bd404..7c6d0d7 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp @@ -11,12 +11,13 @@ int main(int argc, char **argv){ string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); // functions allo.load(path,filein); - allo.printProb(); + //allo.printProb(); - manlove(allo); + manlove(allo, mode); allo.printSol(); allo.checkSolution(); @@ -24,13 +25,13 @@ int main(int argc, char **argv){ } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(); - allo.printProb(); + allo.reduction(mode); + //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; // Model diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/main.h b/SMTI/4_YESBIN_1STA_YESMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/main.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/makefile b/SMTI/4_YESBIN_1STA_YESMERGED/makefile index c209696..dc2d4f3 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/makefile +++ b/SMTI/4_YESBIN_1STA_YESMERGED/makefile @@ -8,15 +8,15 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o exec : $(OBJECTS) - $(CC) $(CFLAGS) -o NOBIN_1STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) + $(CC) $(CFLAGS) -o YESBIN_1STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) .cpp.o : $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : - rm -f $(OBJECTS) NOBIN_1STA_YESMERGED + rm -f $(OBJECTS) YESBIN_1STA_YESMERGED From be0b51cc6a257f4c5e6de2d1a58e9efa26e4c231 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 8 Feb 2019 17:32:29 +0000 Subject: [PATCH 04/48] Preprocess rework There is one Iterator class, which has a pointer to a (polymorphic) base structure which can do different types of preprocessing. --- .../1_NOBIN_1STA_NOMERGED/AgentIterator.cpp | 241 +++++++++++------- .../1_NOBIN_1STA_NOMERGED/AgentIterator.h | 113 +++++--- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp | 34 ++- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h | 2 +- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 241 +++++++++++------- .../4_YESBIN_1STA_YESMERGED/AgentIterator.h | 113 +++++--- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 29 +-- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 241 +++++++++++------- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h | 113 +++++--- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 29 +-- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h | 2 +- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 241 +++++++++++------- SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h | 113 +++++--- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 29 +-- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- 16 files changed, 985 insertions(+), 560 deletions(-) diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp index 48e688f..dfff70c 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp @@ -1,6 +1,6 @@ #include "AgentIterator.h" -AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : _agent(agent), @@ -14,19 +14,35 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat _position = posn; } -bool AgentIterator::operator==(const AgentIterator & other) { - return _group == other.get_group() && _position == other.get_position(); +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; } -bool AgentIterator::operator!=(const AgentIterator & other) { - return ! (*this == other); +int AgentIteratorBase::get_position() const { + return _position; } -const std::pair AgentIterator::operator*() { - return std::pair(_group, _position); +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; } -AgentIterator& AgentIterator::operator++() { +void AgentIteratorBase::regularIncrement() { _position++; if (_agent.preferences[_group].size() == _position) { _position = 0; @@ -35,107 +51,171 @@ AgentIterator& AgentIterator::operator++() { _group = -1; } } - return *this; } -AgentIterator AgentIterator::operator++(int) { - AgentIterator ret = *this; - _position++; - if (_agent.preferences[_group].size() == _position) { - _position = -1; - _group++; - if (_agent.preferences.size() == _group) { - _group = -1; - } - } - return ret; +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); } AgentIterator AgentIterator::begin() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; } AgentIterator AgentIterator::end() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; } int AgentIterator::get_group() const { - return _group; + return base->get_group(); } int AgentIterator::get_position() const { - return _position; + return base->get_position(); } +int AgentIterator::get_mode() const { + return _mode; +} -template -SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -template -SkipBigIterator& SkipBigIterator::operator++() { - int num_added; - do { - AgentIterator::operator++(); +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return *this; + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } } -template -SkipBigIterator SkipBigIterator::operator++(int) { - SkipBigIterator ret = *this; +void SkipBigIterator::increment() { int num_added = 0; do { - AgentIterator::operator++(); + regularIncrement(); + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return ret; + } while (num_added > _skip); } -template class SkipBigIterator<5>; - - BestIterator::BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -BestIterator& BestIterator::operator++() { +void BestIterator::increment() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -147,18 +227,12 @@ BestIterator& BestIterator::operator++() { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -171,15 +245,14 @@ BestIterator& BestIterator::operator++() { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return *this; } -BestIterator BestIterator::operator++(int) { - BestIterator ret = *this; +void BestIterator::begin() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -191,18 +264,12 @@ BestIterator BestIterator::operator++(int) { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -215,9 +282,9 @@ BestIterator BestIterator::operator++(int) { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return ret; } diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h index d866b4d..64ac38d 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h @@ -5,49 +5,96 @@ #include "Allocation.h" - class AgentIterator : public std::iterator, ptrdiff_t> { +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { public: - AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, - const std::vector & these, const std::vector & other, int group=0, int posn=0); - bool operator==(const AgentIterator& other); - bool operator!=(const AgentIterator& other); - const std::pair operator*(); - AgentIterator& operator++(); - AgentIterator operator++(int); - - AgentIterator begin(); - AgentIterator end(); - - int get_position() const; - int get_group() const; - - protected: - const Child & _agent; - int _group; - int _position; - const std::vector & _these; - const std::vector & _other; - const std::set & _positions; - const std::set & _candidates; - }; - -template -class SkipBigIterator : public AgentIterator { + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { public: SkipBigIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, - const std::vector & other, int group=0, int posn=0); - SkipBigIterator& operator++(); - SkipBigIterator operator++(int); + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; }; -class BestIterator : public AgentIterator { +class BestIterator : public AgentIteratorBase { public: BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group=0, int posn=0); - BestIterator& operator++(); - BestIterator operator++(int); + ~BestIterator() {} + void increment(); + void begin(); }; diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp index 31da961..b56c3d1 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp @@ -5,8 +5,12 @@ *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i candidates; set positions; unsigned int count = 0; - AgentIterator *iter; - switch (mode) { - default: - case 0: - iter = new AgentIterator(these[i], candidates, positions, these, other); - break; - case 1: - iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); - break; - case 2: - iter = new BestIterator(these[i], candidates, positions, these, other); - break; - } - for(std::pair p: *iter) { + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { int j = p.first; int k = p.second; int idxFam = these[i].preferences[j][k]; @@ -194,6 +186,11 @@ int Allocation::reductionMine(bool children_side, int mode) { if (count >= candidates.size()) { for (int k = j + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); + std::cout << "Removing from " << i << " : ["; + for(auto pref: these[i].preferences[k]) { + std::cout << pref << ", "; + } + std::cout << "]" << std::endl; these[i].nbTotPref -= these[i].preferences[k].size(); for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { int idxFam = these[i].preferences[k][l]; @@ -221,7 +218,6 @@ int Allocation::reductionMine(bool children_side, int mode) { break; } } - delete iter; } polish(); return nbTotRem; diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h index 8f374de..70732c1 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.h @@ -28,7 +28,7 @@ vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index 48e688f..dfff70c 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -1,6 +1,6 @@ #include "AgentIterator.h" -AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : _agent(agent), @@ -14,19 +14,35 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat _position = posn; } -bool AgentIterator::operator==(const AgentIterator & other) { - return _group == other.get_group() && _position == other.get_position(); +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; } -bool AgentIterator::operator!=(const AgentIterator & other) { - return ! (*this == other); +int AgentIteratorBase::get_position() const { + return _position; } -const std::pair AgentIterator::operator*() { - return std::pair(_group, _position); +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; } -AgentIterator& AgentIterator::operator++() { +void AgentIteratorBase::regularIncrement() { _position++; if (_agent.preferences[_group].size() == _position) { _position = 0; @@ -35,107 +51,171 @@ AgentIterator& AgentIterator::operator++() { _group = -1; } } - return *this; } -AgentIterator AgentIterator::operator++(int) { - AgentIterator ret = *this; - _position++; - if (_agent.preferences[_group].size() == _position) { - _position = -1; - _group++; - if (_agent.preferences.size() == _group) { - _group = -1; - } - } - return ret; +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); } AgentIterator AgentIterator::begin() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; } AgentIterator AgentIterator::end() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; } int AgentIterator::get_group() const { - return _group; + return base->get_group(); } int AgentIterator::get_position() const { - return _position; + return base->get_position(); } +int AgentIterator::get_mode() const { + return _mode; +} -template -SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -template -SkipBigIterator& SkipBigIterator::operator++() { - int num_added; - do { - AgentIterator::operator++(); +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return *this; + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } } -template -SkipBigIterator SkipBigIterator::operator++(int) { - SkipBigIterator ret = *this; +void SkipBigIterator::increment() { int num_added = 0; do { - AgentIterator::operator++(); + regularIncrement(); + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return ret; + } while (num_added > _skip); } -template class SkipBigIterator<5>; - - BestIterator::BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -BestIterator& BestIterator::operator++() { +void BestIterator::increment() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -147,18 +227,12 @@ BestIterator& BestIterator::operator++() { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -171,15 +245,14 @@ BestIterator& BestIterator::operator++() { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return *this; } -BestIterator BestIterator::operator++(int) { - BestIterator ret = *this; +void BestIterator::begin() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -191,18 +264,12 @@ BestIterator BestIterator::operator++(int) { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -215,9 +282,9 @@ BestIterator BestIterator::operator++(int) { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return ret; } diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h index d866b4d..64ac38d 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -5,49 +5,96 @@ #include "Allocation.h" - class AgentIterator : public std::iterator, ptrdiff_t> { +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { public: - AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, - const std::vector & these, const std::vector & other, int group=0, int posn=0); - bool operator==(const AgentIterator& other); - bool operator!=(const AgentIterator& other); - const std::pair operator*(); - AgentIterator& operator++(); - AgentIterator operator++(int); - - AgentIterator begin(); - AgentIterator end(); - - int get_position() const; - int get_group() const; - - protected: - const Child & _agent; - int _group; - int _position; - const std::vector & _these; - const std::vector & _other; - const std::set & _positions; - const std::set & _candidates; - }; - -template -class SkipBigIterator : public AgentIterator { + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { public: SkipBigIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, - const std::vector & other, int group=0, int posn=0); - SkipBigIterator& operator++(); - SkipBigIterator operator++(int); + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; }; -class BestIterator : public AgentIterator { +class BestIterator : public AgentIteratorBase { public: BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group=0, int posn=0); - BestIterator& operator++(); - BestIterator operator++(int); + ~BestIterator() {} + void increment(); + void begin(); }; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index eedcdbf..80f7e49 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -5,8 +5,12 @@ *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i candidates; set positions; unsigned int count = 0; - AgentIterator *iter; - switch (mode) { - default: - case 0: - iter = new AgentIterator(these[i], candidates, positions, these, other); - break; - case 1: - iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); - break; - case 2: - iter = new BestIterator(these[i], candidates, positions, these, other); - break; - } - for(std::pair p: *iter) { + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { int j = p.first; int k = p.second; int idxFam = these[i].preferences[j][k]; @@ -221,7 +213,6 @@ int Allocation::reductionMine(bool children_side, int mode) { break; } } - delete iter; } polish(); return nbTotRem; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h index 8f374de..70732c1 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -28,7 +28,7 @@ vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp index 48e688f..dfff70c 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -1,6 +1,6 @@ #include "AgentIterator.h" -AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : _agent(agent), @@ -14,19 +14,35 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat _position = posn; } -bool AgentIterator::operator==(const AgentIterator & other) { - return _group == other.get_group() && _position == other.get_position(); +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; } -bool AgentIterator::operator!=(const AgentIterator & other) { - return ! (*this == other); +int AgentIteratorBase::get_position() const { + return _position; } -const std::pair AgentIterator::operator*() { - return std::pair(_group, _position); +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; } -AgentIterator& AgentIterator::operator++() { +void AgentIteratorBase::regularIncrement() { _position++; if (_agent.preferences[_group].size() == _position) { _position = 0; @@ -35,107 +51,171 @@ AgentIterator& AgentIterator::operator++() { _group = -1; } } - return *this; } -AgentIterator AgentIterator::operator++(int) { - AgentIterator ret = *this; - _position++; - if (_agent.preferences[_group].size() == _position) { - _position = -1; - _group++; - if (_agent.preferences.size() == _group) { - _group = -1; - } - } - return ret; +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); } AgentIterator AgentIterator::begin() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; } AgentIterator AgentIterator::end() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; } int AgentIterator::get_group() const { - return _group; + return base->get_group(); } int AgentIterator::get_position() const { - return _position; + return base->get_position(); } +int AgentIterator::get_mode() const { + return _mode; +} -template -SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -template -SkipBigIterator& SkipBigIterator::operator++() { - int num_added; - do { - AgentIterator::operator++(); +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return *this; + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } } -template -SkipBigIterator SkipBigIterator::operator++(int) { - SkipBigIterator ret = *this; +void SkipBigIterator::increment() { int num_added = 0; do { - AgentIterator::operator++(); + regularIncrement(); + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return ret; + } while (num_added > _skip); } -template class SkipBigIterator<5>; - - BestIterator::BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -BestIterator& BestIterator::operator++() { +void BestIterator::increment() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -147,18 +227,12 @@ BestIterator& BestIterator::operator++() { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -171,15 +245,14 @@ BestIterator& BestIterator::operator++() { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return *this; } -BestIterator BestIterator::operator++(int) { - BestIterator ret = *this; +void BestIterator::begin() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -191,18 +264,12 @@ BestIterator BestIterator::operator++(int) { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -215,9 +282,9 @@ BestIterator BestIterator::operator++(int) { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return ret; } diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h index d866b4d..64ac38d 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h @@ -5,49 +5,96 @@ #include "Allocation.h" - class AgentIterator : public std::iterator, ptrdiff_t> { +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { public: - AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, - const std::vector & these, const std::vector & other, int group=0, int posn=0); - bool operator==(const AgentIterator& other); - bool operator!=(const AgentIterator& other); - const std::pair operator*(); - AgentIterator& operator++(); - AgentIterator operator++(int); - - AgentIterator begin(); - AgentIterator end(); - - int get_position() const; - int get_group() const; - - protected: - const Child & _agent; - int _group; - int _position; - const std::vector & _these; - const std::vector & _other; - const std::set & _positions; - const std::set & _candidates; - }; - -template -class SkipBigIterator : public AgentIterator { + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { public: SkipBigIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, - const std::vector & other, int group=0, int posn=0); - SkipBigIterator& operator++(); - SkipBigIterator operator++(int); + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; }; -class BestIterator : public AgentIterator { +class BestIterator : public AgentIteratorBase { public: BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group=0, int posn=0); - BestIterator& operator++(); - BestIterator operator++(int); + ~BestIterator() {} + void increment(); + void begin(); }; diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index 91f10dd..741554d 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -5,8 +5,12 @@ *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i candidates; set positions; unsigned int count = 0; - AgentIterator *iter; - switch (mode) { - default: - case 0: - iter = new AgentIterator(these[i], candidates, positions, these, other); - break; - case 1: - iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); - break; - case 2: - iter = new BestIterator(these[i], candidates, positions, these, other); - break; - } - for(std::pair p: *iter) { + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { int j = p.first; int k = p.second; int idxFam = these[i].preferences[j][k]; @@ -295,7 +287,6 @@ int Allocation::reductionMine(bool children_side, int mode) { break; } } - delete iter; } polish(); return nbTotRem; diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h index 23121ae..b2be73f 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h @@ -28,7 +28,7 @@ vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index 48e688f..dfff70c 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -1,6 +1,6 @@ #include "AgentIterator.h" -AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : _agent(agent), @@ -14,19 +14,35 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat _position = posn; } -bool AgentIterator::operator==(const AgentIterator & other) { - return _group == other.get_group() && _position == other.get_position(); +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; } -bool AgentIterator::operator!=(const AgentIterator & other) { - return ! (*this == other); +int AgentIteratorBase::get_position() const { + return _position; } -const std::pair AgentIterator::operator*() { - return std::pair(_group, _position); +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; } -AgentIterator& AgentIterator::operator++() { +void AgentIteratorBase::regularIncrement() { _position++; if (_agent.preferences[_group].size() == _position) { _position = 0; @@ -35,107 +51,171 @@ AgentIterator& AgentIterator::operator++() { _group = -1; } } - return *this; } -AgentIterator AgentIterator::operator++(int) { - AgentIterator ret = *this; - _position++; - if (_agent.preferences[_group].size() == _position) { - _position = -1; - _group++; - if (_agent.preferences.size() == _group) { - _group = -1; - } - } - return ret; +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); } AgentIterator AgentIterator::begin() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, 0, 0); + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; } AgentIterator AgentIterator::end() { - return AgentIterator(_agent, _candidates, _positions, _these, _other, -1, 0); + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 4, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; } int AgentIterator::get_group() const { - return _group; + return base->get_group(); } int AgentIterator::get_position() const { - return _position; + return base->get_position(); } +int AgentIterator::get_mode() const { + return _mode; +} -template -SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -template -SkipBigIterator& SkipBigIterator::operator++() { - int num_added; - do { - AgentIterator::operator++(); +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return *this; + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } } -template -SkipBigIterator SkipBigIterator::operator++(int) { - SkipBigIterator ret = *this; +void SkipBigIterator::increment() { int num_added = 0; do { - AgentIterator::operator++(); + regularIncrement(); + if (get_group() == -1) { + break; + } num_added = 0; int other_id = _agent.preferences[_group][_position]; - for(auto group: _other[other_id].preferences) { - bool found = false; - for(auto pref: group) { + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(pref) == 0) { num_added++; } - if (pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } - } while ((*this != end()) && num_added > step); - return ret; + } while (num_added > _skip); } -template class SkipBigIterator<5>; - - BestIterator::BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group, int posn) : - AgentIterator(agent, candidates, positions, these, other, group, posn) { + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { } -BestIterator& BestIterator::operator++() { +void BestIterator::increment() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -147,18 +227,12 @@ BestIterator& BestIterator::operator++() { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -171,15 +245,14 @@ BestIterator& BestIterator::operator++() { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return *this; } -BestIterator BestIterator::operator++(int) { - BestIterator ret = *this; +void BestIterator::begin() { int lowest_added = -1; int best_group = -1; int best_posn = -1; @@ -191,18 +264,12 @@ BestIterator BestIterator::operator++(int) { continue; } int num_added = 0; - bool found = false; - for(auto & other_group: _other[other_id].preferences) { - for(auto other_pref: other_group) { + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { if (_candidates.count(other_pref) == 0) { num_added++; } - if (other_pref == _agent.id) { - found = true; - } - } - if (found) { - break; } } if ((lowest_added == -1) || (num_added < lowest_added)) { @@ -215,9 +282,9 @@ BestIterator BestIterator::operator++(int) { if (lowest_added != -1) { _group = best_group; _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; - _position = -1; + _position = 0; } - return ret; } diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h index d866b4d..64ac38d 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -5,49 +5,96 @@ #include "Allocation.h" - class AgentIterator : public std::iterator, ptrdiff_t> { +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { public: - AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, - const std::vector & these, const std::vector & other, int group=0, int posn=0); - bool operator==(const AgentIterator& other); - bool operator!=(const AgentIterator& other); - const std::pair operator*(); - AgentIterator& operator++(); - AgentIterator operator++(int); - - AgentIterator begin(); - AgentIterator end(); - - int get_position() const; - int get_group() const; - - protected: - const Child & _agent; - int _group; - int _position; - const std::vector & _these; - const std::vector & _other; - const std::set & _positions; - const std::set & _candidates; - }; - -template -class SkipBigIterator : public AgentIterator { + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { public: SkipBigIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, - const std::vector & other, int group=0, int posn=0); - SkipBigIterator& operator++(); - SkipBigIterator operator++(int); + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; }; -class BestIterator : public AgentIterator { +class BestIterator : public AgentIteratorBase { public: BestIterator(const Child & agent, const std::set & candidates, const std::set & positions, const std::vector & these, const std::vector & other, int group=0, int posn=0); - BestIterator& operator++(); - BestIterator operator++(int); + ~BestIterator() {} + void increment(); + void begin(); }; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 91f10dd..741554d 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -5,8 +5,12 @@ *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i candidates; set positions; unsigned int count = 0; - AgentIterator *iter; - switch (mode) { - default: - case 0: - iter = new AgentIterator(these[i], candidates, positions, these, other); - break; - case 1: - iter = new SkipBigIterator<5>(these[i], candidates, positions, these, other); - break; - case 2: - iter = new BestIterator(these[i], candidates, positions, these, other); - break; - } - for(std::pair p: *iter) { + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { int j = p.first; int k = p.second; int idxFam = these[i].preferences[j][k]; @@ -295,7 +287,6 @@ int Allocation::reductionMine(bool children_side, int mode) { break; } } - delete iter; } polish(); return nbTotRem; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h index 23121ae..b2be73f 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -28,7 +28,7 @@ vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* From 7b4a21f318f5f1c6e5634b54cf790a3855f324a1 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 11 Feb 2019 09:28:31 +0000 Subject: [PATCH 05/48] Remove debugging output --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index dfff70c..bc325ce 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -245,7 +245,6 @@ void BestIterator::increment() { if (lowest_added != -1) { _group = best_group; _position = best_posn; - std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; _position = 0; @@ -282,7 +281,6 @@ void BestIterator::begin() { if (lowest_added != -1) { _group = best_group; _position = best_posn; - std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; _position = 0; From 88e48bd7f447ca00ffda3cda1b12bcfd7f74646e Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 11 Feb 2019 09:34:24 +0000 Subject: [PATCH 06/48] preprocessing fixes Don't optimise if preprocessing takes > MAXTIME, which is now #defined for easier modification. Also introduces 2 new SkipBig iterators, with steps of sizes 15 and 50. --- .../1_NOBIN_1STA_NOMERGED/AgentIterator.cpp | 26 +++++++++++++++++-- SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp | 20 ++++++++++---- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 26 +++++++++++++++++-- SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp | 20 ++++++++++---- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 6 +++++ SMTI/3_NOBIN_1STA_YESMERGED/main.cpp | 11 +++++++- .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 26 +++++++++++++++++-- SMTI/4_YESBIN_1STA_YESMERGED/main.cpp | 20 ++++++++++---- 8 files changed, 133 insertions(+), 22 deletions(-) diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp index dfff70c..71b0671 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp @@ -89,6 +89,12 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 2: base = new BestIterator(agent, candidates, positions, these, other, 0, 0); break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; } } @@ -102,12 +108,20 @@ AgentIterator::AgentIterator(AgentIterator *other) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), other->get_group(), other->get_position()); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; } } @@ -120,12 +134,20 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, group, posn); + other->get_these(), other->get_other(), 5, group, posn); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), group, posn); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; } } diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp index 20473db..fafedef 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -18,10 +20,11 @@ int main(int argc, char **argv){ allo.load(path,filein,minGrade); //allo.printProb(); - manlove(allo, mode); - - allo.printSol(); - allo.checkSolution(); + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } allo.printInfo(pathAndFileout); } @@ -33,6 +36,13 @@ int manlove(Allocation& allo, int reduction_mode){ allo.reduction(reduction_mode); allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } // Model try{ @@ -112,7 +122,7 @@ int manlove(Allocation& allo, int reduction_mode){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index bc325ce..db4bb03 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -89,6 +89,12 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 2: base = new BestIterator(agent, candidates, positions, these, other, 0, 0); break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; } } @@ -102,12 +108,20 @@ AgentIterator::AgentIterator(AgentIterator *other) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), other->get_group(), other->get_position()); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; } } @@ -120,12 +134,20 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, group, posn); + other->get_these(), other->get_other(), 5, group, posn); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), group, posn); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; } } diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp index acee890..4ba6ae9 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -18,10 +20,11 @@ int main(int argc, char **argv){ allo.load(path,filein,minGrade); //allo.printProb(); - manlove(allo, mode); - - allo.printSol(); - allo.checkSolution(); + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } allo.printInfo(pathAndFileout); } @@ -34,6 +37,13 @@ int manlove(Allocation& allo, int mode){ allo.reduction(mode); //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } // Model try{ @@ -128,7 +138,7 @@ int manlove(Allocation& allo, int mode){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp index dfff70c..0e6bc70 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -89,6 +89,12 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 2: base = new BestIterator(agent, candidates, positions, these, other, 0, 0); break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; } } diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp index 892a257..8fe372f 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -35,6 +37,13 @@ int manlove(Allocation& allo, int mode){ allo.reduction(mode); //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over MAXTIME seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } // Model try{ @@ -115,7 +124,7 @@ int manlove(Allocation& allo, int mode){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index dfff70c..71b0671 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -89,6 +89,12 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 2: base = new BestIterator(agent, candidates, positions, these, other, 0, 0); break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; } } @@ -102,12 +108,20 @@ AgentIterator::AgentIterator(AgentIterator *other) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), other->get_group(), other->get_position()); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; } } @@ -120,12 +134,20 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, group, posn); + other->get_these(), other->get_other(), 5, group, posn); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), group, posn); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; } } diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp index 7c6d0d7..20faac7 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -17,10 +19,11 @@ int main(int argc, char **argv){ allo.load(path,filein); //allo.printProb(); - manlove(allo, mode); - - allo.printSol(); - allo.checkSolution(); + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } allo.printInfo(pathAndFileout); } @@ -33,6 +36,13 @@ int manlove(Allocation& allo, int mode){ allo.reduction(mode); //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } // Model try{ @@ -127,7 +137,7 @@ int manlove(Allocation& allo, int mode){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); From 58362e680567928c003da39bf7c5ad5645eddb91 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 11 Feb 2019 09:35:20 +0000 Subject: [PATCH 07/48] Hide debug output --- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp index 0e6bc70..e6952b3 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -251,7 +251,6 @@ void BestIterator::increment() { if (lowest_added != -1) { _group = best_group; _position = best_posn; - std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; _position = 0; @@ -288,7 +287,6 @@ void BestIterator::begin() { if (lowest_added != -1) { _group = best_group; _position = best_posn; - std::cout << "Using " << _group << ", " << _position << std::endl; } else { _group = -1; _position = 0; From ceb43e4e63b821dca0240b2f8f685d4345ee3cd5 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 13 Feb 2019 08:50:12 +0000 Subject: [PATCH 08/48] Fix missed preprocessing constructors --- SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp index e6952b3..db4bb03 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -108,12 +108,20 @@ AgentIterator::AgentIterator(AgentIterator *other) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, other->get_group(), other->get_position()); + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), other->get_group(), other->get_position()); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; } } @@ -126,12 +134,20 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : break; case 1: base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), - other->get_these(), other->get_other(), 4, group, posn); + other->get_these(), other->get_other(), 5, group, posn); break; case 2: base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), group, posn); break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; } } From d84110172bfc08d1d9bc1ef502bb37f98903268f Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 14 Feb 2019 17:26:24 +0000 Subject: [PATCH 09/48] Fix FindBestIterator FindBestIterator loses the guarantee that the last-added position will be the one this agent considers "worst", so we now keep track of what the worst rank is. --- SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp | 8 ++++++-- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 8 ++++++-- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 8 ++++++-- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 8 ++++++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp index b56c3d1..b77e5e2 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/Allocation.cpp @@ -168,11 +168,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + int worst_rank = 0; unsigned int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } int idxFam = these[i].preferences[j][k]; int idxRank = these[i].ranks[j][k]; positions.insert(idxFam); @@ -184,7 +188,7 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { - for (int k = j + 1; k < these[i].nbPref; k++) { + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); std::cout << "Removing from " << i << " : ["; for(auto pref: these[i].preferences[k]) { @@ -211,7 +215,7 @@ int Allocation::reductionMine(bool children_side, int mode) { other[idxFam].preferences[idxRank].begin() + idxPos); } } - these[i].nbPref = j + 1; + these[i].nbPref = worst_rank + 1; these[i].preferences.resize(these[i].nbPref); these[i].ranks.resize(these[i].nbPref); these[i].positions.resize(these[i].nbPref); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 80f7e49..e1f321a 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -168,11 +168,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + int worst_rank = 0; unsigned int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } int idxFam = these[i].preferences[j][k]; int idxRank = these[i].ranks[j][k]; positions.insert(idxFam); @@ -184,7 +188,7 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { - for (int k = j + 1; k < these[i].nbPref; k++) { + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { @@ -206,7 +210,7 @@ int Allocation::reductionMine(bool children_side, int mode) { other[idxFam].preferences[idxRank].begin() + idxPos); } } - these[i].nbPref = j + 1; + these[i].nbPref = worst_rank + 1; these[i].preferences.resize(these[i].nbPref); these[i].ranks.resize(these[i].nbPref); these[i].positions.resize(these[i].nbPref); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index 741554d..c43d3d0 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -242,11 +242,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + int worst_rank = 0; unsigned int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } int idxFam = these[i].preferences[j][k]; int idxRank = these[i].ranks[j][k]; positions.insert(idxFam); @@ -258,7 +262,7 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { - for (int k = j + 1; k < these[i].nbPref; k++) { + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { @@ -280,7 +284,7 @@ int Allocation::reductionMine(bool children_side, int mode) { other[idxFam].preferences[idxRank].begin() + idxPos); } } - these[i].nbPref = j + 1; + these[i].nbPref = worst_rank + 1; these[i].preferences.resize(these[i].nbPref); these[i].ranks.resize(these[i].nbPref); these[i].positions.resize(these[i].nbPref); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 741554d..c43d3d0 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -242,11 +242,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + int worst_rank = 0; unsigned int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } int idxFam = these[i].preferences[j][k]; int idxRank = these[i].ranks[j][k]; positions.insert(idxFam); @@ -258,7 +262,7 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { - for (int k = j + 1; k < these[i].nbPref; k++) { + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { @@ -280,7 +284,7 @@ int Allocation::reductionMine(bool children_side, int mode) { other[idxFam].preferences[idxRank].begin() + idxPos); } } - these[i].nbPref = j + 1; + these[i].nbPref = worst_rank + 1; these[i].preferences.resize(these[i].nbPref); these[i].ranks.resize(these[i].nbPref); these[i].positions.resize(these[i].nbPref); From 52098b6034699ab31009f2414c5a576f3afbd85f Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 15 Feb 2019 16:44:45 +0000 Subject: [PATCH 10/48] BestGroupIterator: New iterator Finds the best position to add in the current group/rank of the current agent. --- .../1_NOBIN_1STA_NOMERGED/AgentIterator.cpp | 92 +++++++++++++++++++ .../1_NOBIN_1STA_NOMERGED/AgentIterator.h | 9 ++ .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 92 +++++++++++++++++++ .../4_YESBIN_1STA_YESMERGED/AgentIterator.h | 9 ++ SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp | 92 +++++++++++++++++++ SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h | 9 ++ .../4_YESBIN_1STA_YESMERGED/AgentIterator.cpp | 92 +++++++++++++++++++ SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h | 9 ++ 8 files changed, 404 insertions(+) diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp index 71b0671..88ceb8e 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.cpp @@ -95,6 +95,9 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 4: base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; } } @@ -122,6 +125,10 @@ AgentIterator::AgentIterator(AgentIterator *other) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; } } @@ -148,6 +155,10 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, group, posn); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; } } @@ -310,3 +321,84 @@ void BestIterator::begin() { _position = 0; } } + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h index 64ac38d..48b96c6 100644 --- a/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h +++ b/SMTI-GRP/1_NOBIN_1STA_NOMERGED/AgentIterator.h @@ -97,5 +97,14 @@ class BestIterator : public AgentIteratorBase { void begin(); }; +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; #endif /* AGENTITERATOR_H */ diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index db4bb03..6210288 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -95,6 +95,9 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 4: base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; } } @@ -122,6 +125,10 @@ AgentIterator::AgentIterator(AgentIterator *other) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; } } @@ -148,6 +155,10 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, group, posn); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; } } @@ -308,3 +319,84 @@ void BestIterator::begin() { _position = 0; } } + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h index 64ac38d..48b96c6 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -97,5 +97,14 @@ class BestIterator : public AgentIteratorBase { void begin(); }; +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; #endif /* AGENTITERATOR_H */ diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp index db4bb03..6210288 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.cpp @@ -95,6 +95,9 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 4: base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; } } @@ -122,6 +125,10 @@ AgentIterator::AgentIterator(AgentIterator *other) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; } } @@ -148,6 +155,10 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, group, posn); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; } } @@ -308,3 +319,84 @@ void BestIterator::begin() { _position = 0; } } + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h index 64ac38d..48b96c6 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/AgentIterator.h @@ -97,5 +97,14 @@ class BestIterator : public AgentIteratorBase { void begin(); }; +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; #endif /* AGENTITERATOR_H */ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp index 71b0671..88ceb8e 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.cpp @@ -95,6 +95,9 @@ AgentIterator::AgentIterator(const Child & agent, const std::set & candidat case 4: base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; } } @@ -122,6 +125,10 @@ AgentIterator::AgentIterator(AgentIterator *other) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; } } @@ -148,6 +155,10 @@ AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), other->get_these(), other->get_other(), 50, group, posn); break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; } } @@ -310,3 +321,84 @@ void BestIterator::begin() { _position = 0; } } + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h index 64ac38d..48b96c6 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/AgentIterator.h @@ -97,5 +97,14 @@ class BestIterator : public AgentIteratorBase { void begin(); }; +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; #endif /* AGENTITERATOR_H */ From 24a41a17b9bfb638465684ac3fbe6f475c75affb Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 14 Mar 2019 16:12:55 +0000 Subject: [PATCH 11/48] Initial implementation of graph algorithm for preprocessing --- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 128 ++++++++++++++- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 1 + SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp | 148 ++++++++++++++++++ SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h | 60 +++++++ SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile | 4 +- 5 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp create mode 100644 SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index e1f321a..0ccd759 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -1,5 +1,6 @@ #include "Allocation.h" #include "AgentIterator.h" +#include "Graph.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -150,7 +151,7 @@ void Allocation::printProb(){ } } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionExact(bool children_side) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; @@ -158,9 +159,119 @@ int Allocation::reductionMine(bool children_side, int mode) { if (children_side) { thesep = &children; otherp = &families; + number_here = nbChildren; } else { thesep = &families; otherp = &children; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + for (int i = 0; i < number_here; i++) { + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph> g; + int n_1 = 0; + // We do nbPref - 1 here because there is no point to preprocessing when we + // reach the last rank + for(int rank = 0; rank < these[i].nbPref - 1; rank++) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + int idxRank = these[i].ranks[rank][ind]; + for(int l = 0; l <= idxRank; l++) { + for(size_t k = 0; k < other[position].preferences[l].size(); k++) { + int other_cand = other[position].preferences[l][k]; + if (other_cand == i) { // Don't add the current candidate to the graph + continue; + } + std::pair other_cand_vert = std::make_pair(0, other_cand); + if (! g.containsVertex(other_cand_vert)) { + g.addVertex(other_cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, other_cand_vert); + } + } + } + // If n_1 is sufficiently small, then the largest matching must also be + // small, as the matching can use each vertex from n_1 at most once, so + // we don't even need to try to find a bigger matching. + bool matching_cant_exist = (2*n_1 + 1 <= g.size()); + if (! matching_cant_exist) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.augment(pos_vert); + } + } + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << std::endl; +#ifdef DEBUG +// if ((children_side) and (i == 87)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); +// } +#endif /* DEBUG */ + + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +int Allocation::reductionMine(bool children_side, int mode) { + int nbTotRem = 0; + int number_here; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + number_here = nbFamilies; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -218,7 +329,9 @@ int Allocation::reductionMine(bool children_side, int mode) { } } } - polish(); + if (nbTotRem > 0) { + polish(); + } return nbTotRem; } @@ -285,8 +398,15 @@ void Allocation::reduction(int mode){ int i = 0; int num = 0; do{ - num = reductionMine(true, mode); - num += reductionMine(false, mode); + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; total_reduced += num; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h index 70732c1..a6a6445 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -77,6 +77,7 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); int reductionMine(bool children_side=true, int mode=0); + int reductionExact(bool children_side); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp new file mode 100644 index 0000000..3206f4a --- /dev/null +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -0,0 +1,148 @@ +#include +#include "Graph.h" + + + +template +Graph::Graph() { +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +template +void Graph::addVertex(t_name name, bool open) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG + std::cout << "Add vertex " << name << std::endl; +#endif /* DEBUG */ + this->_adjacents.emplace_back(); +} + +template +t_name Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +template +bool Graph::containsVertex(t_name name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +template +void Graph::addEdge(t_name v1, t_name v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + _adjacents[i1].push_back(i2); + _adjacents[i2].push_back(i1); +} + +template +int Graph::size() const { + return _names.size(); +} + +template +int Graph::matchingSize() const { + // for a matched edge (a,b), our _matching map stores both _matching[a] = b + // and _matching[b] = a. + return _matching.size() / 2; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +template +void Graph::augment(t_name name) { + int start = this->_names[name]; +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(size(), false); + path.push_back(start); + internal_augment(start, visited, path); +} + +#ifdef DEBUG +template +void Graph::printGraph() { + for(size_t ind = 0; ind < _adjacents.size(); ++ind) { + std::cout << _indices[ind] << ":"; + for(auto adj: _adjacents[ind]) { + std::cout << " " << _indices[adj]; + } + std::cout << std::endl; + } +} + +template +void Graph::printMatching() const { + for(auto p: _matching) { + int a = p.first; + int b = p.second; + if (a <= b) { + std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; + } + } +} + +#endif /* DEBUG */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +template +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[now]) { + if (visited[next]) { + continue; + } + auto matched = _matching.find(next); + if (matched == _matching.end()) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[right] = left; + _matching[left] = right; + } + + return true; + } + int next2 = matched->second; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + +template class Graph>; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h new file mode 100644 index 0000000..cdbbec7 --- /dev/null +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +template +class Graph { + public: + Graph(); + void addVertex(t_name name, bool open=false); + bool containsVertex(t_name name) const; + void addEdge(t_name v1, t_name v2); + const std::list adjacent(t_name vertex) const; + int matched(t_name vertex) const; + void augment(t_name vertex); + + int size() const; + int matchingSize() const; + + t_name name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::unordered_map _names; + std::unordered_map _indices; + std::vector> _adjacents; + std::unordered_map _matching; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile index 762822f..0e198a3 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/makefile @@ -10,12 +10,12 @@ GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o AgentIterator.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_1STA_NOMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +.cpp.o : $< $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : From 9dbf5d9a587a4a00a0c1d192f1076099ae933c15 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 18 Mar 2019 13:12:48 +0000 Subject: [PATCH 12/48] Add new preprocessing method This new mode (7), first runs skip5 until it cannot find anything, before moving onto the exact algorithm. --- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 0ccd759..af328a6 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -397,20 +397,37 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; - do{ - if (mode == 6) { - // True means preprocess childrens' lists, removing families. - // False means preprocess families' lists, removing children. + if (mode == 7) { + do { + num = reductionMine(false, 1); + num += reductionMine(true, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { num = reductionExact(false); num += reductionExact(true); - } else { - num = reductionMine(false, mode); - num += reductionMine(true, mode); - } - cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; - i++; - total_reduced += num; - }while(num != 0); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + } else { + do{ + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } + cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; + i++; + total_reduced += num; + }while(num != 0); + } } void Allocation::printSol(){ From 3288986009882afd540632899a250b0a02fafa58 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 21 Mar 2019 10:19:27 +0000 Subject: [PATCH 13/48] Add complete-exact method reductionExact now takes a supp parameter, defaulting to false. If set to true, then we also look at positions which are always filled when looking to find sets C, P, and P'. --- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 102 +++++++++++++++--- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 9 +- 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index af328a6..43b21f6 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -77,7 +77,8 @@ void Allocation::load(const string& path, const string& filein, const int& thres for (int j = 0; j < nbChildren; j++){ if(grades[i][j] >= threshold) grade.insert(grades[i][j]); } - Family f; f.id = i; f.nbPref = grade.size(); f.nbTotPref = 0; f.preferences.resize(f.nbPref); f.ranks.resize(f.nbPref); f.positions.resize(f.nbPref); + Family f; f.id = i; f.nbPref = grade.size(); f.nbTotPref = 0; f.preferences.resize(f.nbPref); f.ranks.resize(f.nbPref); f.positions.resize(f.nbPref); + f.mustBeAllocated = false; vector gradeVector(grade.begin(), grade.end()); reverse(gradeVector.begin(),gradeVector.end()); for (int j = 0; j < nbChildren; j++){ @@ -99,7 +100,8 @@ void Allocation::load(const string& path, const string& filein, const int& thres for (int j = 0; j < nbFamilies; j++){ if(grades[j][i] >= threshold) grade.insert(grades[j][i]); } - Child c; c.id = i; c.nbPref = grade.size(); c.nbTotPref = 0; c.preferences.resize(c.nbPref); c.ranks.resize(c.nbPref); c.positions.resize(c.nbPref); + Child c; c.id = i; c.nbPref = grade.size(); c.nbTotPref = 0; c.preferences.resize(c.nbPref); c.ranks.resize(c.nbPref); c.positions.resize(c.nbPref); + c.mustBeAllocated = false; vector gradeVector(grade.begin(), grade.end()); reverse(gradeVector.begin(),gradeVector.end()); for (int j = 0; j < nbFamilies; j++){ @@ -151,30 +153,73 @@ void Allocation::printProb(){ } } -int Allocation::reductionExact(bool children_side) { +int Allocation::reductionExact(bool children_side, bool supp) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; if (children_side) { + // Processing the lists of the children, removing families thesep = &children; otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; number_here = nbChildren; } else { thesep = &families; otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; number_here = nbFamilies; } std::vector & these = (*thesep); std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) Graph> g; int n_1 = 0; - // We do nbPref - 1 here because there is no point to preprocessing when we - // reach the last rank - for(int rank = 0; rank < these[i].nbPref - 1; rank++) { + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, cand_vert); + } + } + g.augment(pos_vert); + } + for(int rank = 0; rank < these[i].nbPref; rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == these[i].nbPref - 1) && (these[i].mustBeAllocated || !supp)) { + continue; + } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; auto pos_vert = std::make_pair(1, position); @@ -208,23 +253,32 @@ int Allocation::reductionExact(bool children_side) { } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! - if (children_side) { - std::cout << "child "; - } else { - std::cout << "family "; + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; } - std::cout << "worst rank of " << i << " is " << rank << std::endl; #ifdef DEBUG -// if ((children_side) and (i == 87)) { + if ((!children_side) and (i == 6)) { std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); std::cout << ", n_1 = " << n_1 << std::endl; g.printGraph(); g.printMatching(); -// } + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; #endif /* DEBUG */ - for (int k = rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ these[i].nbTotPref -= these[i].preferences[k].size(); for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { int idxFam = these[i].preferences[k][l]; @@ -249,6 +303,9 @@ int Allocation::reductionExact(bool children_side) { these[i].preferences.resize(these[i].nbPref); these[i].ranks.resize(these[i].nbPref); these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ break; } } @@ -299,6 +356,14 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); @@ -419,6 +484,15 @@ void Allocation::reduction(int mode){ // False means preprocess families' lists, removing children. num = reductionExact(false); num += reductionExact(true); + } else if (mode == 8) { + num = reductionExact(true); + num += reductionExact(false); + } else if (mode == 9) { + num = reductionExact(false, true); + num += reductionExact(true, true); + } else if (mode == 10) { + num = reductionExact(true, true); + num += reductionExact(false, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h index a6a6445..1d1bf0d 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -24,7 +25,8 @@ public: int id; int nbPref; - int nbTotPref; + int nbTotPref; + bool mustBeAllocated; vector > preferences; vector > ranks; vector > positions; @@ -72,12 +74,15 @@ vector assignmentByChild; vector assignmentByFamily; + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + Info infos; void load(const string& path, const string& filein, const int& threshold); void printProb(); int reductionMine(bool children_side=true, int mode=0); - int reductionExact(bool children_side); + int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); void printSol(); From b76ea773632da70dfab9312be7763db88b216afd Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 21 Mar 2019 10:35:34 +0000 Subject: [PATCH 14/48] Add preprocessing for other model --- .../8_YESBIN_2STA_YESMERGED/AgentIterator.cpp | 402 ++++++++++++ .../8_YESBIN_2STA_YESMERGED/AgentIterator.h | 110 ++++ .../8_YESBIN_2STA_YESMERGED/Allocation.cpp | 591 ++++++++---------- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h | 35 +- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp | 148 +++++ SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h | 60 ++ SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp | 29 +- SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.h | 2 +- SMTI-GRP/8_YESBIN_2STA_YESMERGED/makefile | 6 +- 9 files changed, 1030 insertions(+), 353 deletions(-) create mode 100644 SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp create mode 100644 SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.h create mode 100644 SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp create mode 100644 SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp new file mode 100644 index 0000000..6210288 --- /dev/null +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp @@ -0,0 +1,402 @@ +#include "AgentIterator.h" + +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; +} + +int AgentIteratorBase::get_position() const { + return _position; +} + +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; +} + +void AgentIteratorBase::regularIncrement() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); +} + +AgentIterator AgentIterator::begin() { + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; +} + +AgentIterator AgentIterator::end() { + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; +} + +int AgentIterator::get_group() const { + return base->get_group(); +} + +int AgentIterator::get_position() const { + return base->get_position(); +} + +int AgentIterator::get_mode() const { + return _mode; +} + +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } +} + +void SkipBigIterator::increment() { + int num_added = 0; + do { + regularIncrement(); + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + } while (num_added > _skip); +} + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.h new file mode 100644 index 0000000..48b96c6 --- /dev/null +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/AgentIterator.h @@ -0,0 +1,110 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { + public: + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; +}; + +class BestIterator : public AgentIteratorBase { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestIterator() {} + void increment(); + void begin(); +}; + +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 9d5dec4..43b21f6 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -1,29 +1,17 @@ #include "Allocation.h" +#include "AgentIterator.h" +#include "Graph.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i= threshold) grade.insert(grades[i][j]); } - Family f; f.id = i; f.nbPref = grade.size(); f.nbTotPref = 0; f.preferences.resize(f.nbPref); f.ranks.resize(f.nbPref); f.positions.resize(f.nbPref); + Family f; f.id = i; f.nbPref = grade.size(); f.nbTotPref = 0; f.preferences.resize(f.nbPref); f.ranks.resize(f.nbPref); f.positions.resize(f.nbPref); + f.mustBeAllocated = false; vector gradeVector(grade.begin(), grade.end()); reverse(gradeVector.begin(),gradeVector.end()); for (int j = 0; j < nbChildren; j++){ @@ -111,7 +100,8 @@ void Allocation::load(const string& path, const string& filein, const int& thres for (int j = 0; j < nbFamilies; j++){ if(grades[j][i] >= threshold) grade.insert(grades[j][i]); } - Child c; c.id = i; c.nbPref = grade.size(); c.nbTotPref = 0; c.preferences.resize(c.nbPref); c.ranks.resize(c.nbPref); c.positions.resize(c.nbPref); + Child c; c.id = i; c.nbPref = grade.size(); c.nbTotPref = 0; c.preferences.resize(c.nbPref); c.ranks.resize(c.nbPref); c.positions.resize(c.nbPref); + c.mustBeAllocated = false; vector gradeVector(grade.begin(), grade.end()); reverse(gradeVector.begin(),gradeVector.end()); for (int j = 0; j < nbFamilies; j++){ @@ -156,320 +146,257 @@ void Allocation::load(const string& path, const string& filein, const int& thres void Allocation::printProb(){ cout << "Instance " << name << endl; for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - +int Allocation::reductionExact(bool children_side, bool supp) { int nbTotRem = 0; - - for(int i=0; i * thesep; + std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph> g; + int n_1 = 0; + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); - } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); } - else{ - (*it).second.push_back(j); + if (isAcceptable) { + continue; } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, cand_vert); } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; } + g.augment(pos_vert); } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i other_cand_vert = std::make_pair(0, other_cand); + if (! g.containsVertex(other_cand_vert)) { + g.addVertex(other_cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, other_cand_vert); + } } - children[idxChi].nbTotPref--; - children[idxChi].positions[idxRank].erase(children[idxChi].positions[idxRank].begin() + idxPos); - children[idxChi].ranks[idxRank].erase(children[idxChi].ranks[idxRank].begin() + idxPos); - children[idxChi].preferences[idxRank].erase(children[idxChi].preferences[idxRank].begin() + idxPos); } - } - families[i].nbPref = worstRank[i] + 1; - families[i].preferences.resize(families[i].nbPref); - families[i].ranks.resize(families[i].nbPref); - families[i].positions.resize(families[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionFam2(){ - - int nbTotRem = 0; - vector worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ break; } } } - - for(int i=0; i 0) { + polish(); } - - polish(); return nbTotRem; } -int Allocation::reductionChi2(){ - +int Allocation::reductionMine(bool children_side, int mode) { int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + int worst_rank = 0; + unsigned int count = 0; + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { + int j = p.first; + int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + if (count >= candidates.size()) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = worst_rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } } - - for(int i=0; i 0) { + polish(); } - - polish(); return nbTotRem; } @@ -531,20 +458,50 @@ void Allocation::polish(){ } } -void Allocation::reduction(){ - int nbRed1 = 0; - int nbRed2 = 0; - int nbRed3 = 0; - int nbRed4 = 0; +void Allocation::reduction(int mode){ + total_reduced = 0; int i = 0; - do{ - nbRed1 = reductionFam1(); - nbRed2 = reductionChi1(); - nbRed3 = reductionFam2(); - nbRed4 = reductionChi2(); - cout << "Reduction iteration " << i << " reductionFam1 " << nbRed1 << " reductionChi1 " << nbRed2 << " reductionFam2 " << nbRed3 << " reductionChi2 " << nbRed4 << endl; - i++; - }while(nbRed1 + nbRed2 + nbRed3 + nbRed4 != 0); + int num = 0; + if (mode == 7) { + do { + num = reductionMine(false, 1); + num += reductionMine(true, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(false); + num += reductionExact(true); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + } else { + do{ + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else if (mode == 8) { + num = reductionExact(true); + num += reductionExact(false); + } else if (mode == 9) { + num = reductionExact(false, true); + num += reductionExact(true, true); + } else if (mode == 10) { + num = reductionExact(true, true); + num += reductionExact(false, true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } + cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; + i++; + total_reduced += num; + }while(num != 0); + } } void Allocation::printSol(){ @@ -557,7 +514,7 @@ void Allocation::printSol(){ void Allocation::printInfo(const string& pathAndFileout){ string nameFile = pathAndFileout; std::ofstream file(nameFile.c_str(), std::ios::out | std::ios::app); - file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t"<< infos.LB << "\t" << infos.UB << "\t" << infos.altInfo << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ + file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t" << total_reduced << "\t" << infos.LB << "\t" << infos.UB << "\t" << infos.altInfo << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ << "\t" << infos.contUB2 << "\t" << infos.nbVar2 << "\t" << infos.nbCons2 << "\t" << infos.nbNZ2 << endl; file.close(); } diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h index 0077780..1d1bf0d 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -12,7 +13,7 @@ #include class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -21,29 +22,15 @@ ************************************************************************************* */ class Child{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ public: int id; int nbPref; int nbTotPref; + bool mustBeAllocated; vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* @@ -77,6 +64,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector > grades; vector children; @@ -86,20 +74,21 @@ vector assignmentByChild; vector assignmentByFamily; + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + Info infos; void load(const string& path, const string& filein, const int& threshold); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); + int reductionExact(bool children_side, bool supp=false); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp new file mode 100644 index 0000000..3206f4a --- /dev/null +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp @@ -0,0 +1,148 @@ +#include +#include "Graph.h" + + + +template +Graph::Graph() { +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +template +void Graph::addVertex(t_name name, bool open) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG + std::cout << "Add vertex " << name << std::endl; +#endif /* DEBUG */ + this->_adjacents.emplace_back(); +} + +template +t_name Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +template +bool Graph::containsVertex(t_name name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +template +void Graph::addEdge(t_name v1, t_name v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + _adjacents[i1].push_back(i2); + _adjacents[i2].push_back(i1); +} + +template +int Graph::size() const { + return _names.size(); +} + +template +int Graph::matchingSize() const { + // for a matched edge (a,b), our _matching map stores both _matching[a] = b + // and _matching[b] = a. + return _matching.size() / 2; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +template +void Graph::augment(t_name name) { + int start = this->_names[name]; +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(size(), false); + path.push_back(start); + internal_augment(start, visited, path); +} + +#ifdef DEBUG +template +void Graph::printGraph() { + for(size_t ind = 0; ind < _adjacents.size(); ++ind) { + std::cout << _indices[ind] << ":"; + for(auto adj: _adjacents[ind]) { + std::cout << " " << _indices[adj]; + } + std::cout << std::endl; + } +} + +template +void Graph::printMatching() const { + for(auto p: _matching) { + int a = p.first; + int b = p.second; + if (a <= b) { + std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; + } + } +} + +#endif /* DEBUG */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +template +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[now]) { + if (visited[next]) { + continue; + } + auto matched = _matching.find(next); + if (matched == _matching.end()) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[right] = left; + _matching[left] = right; + } + + return true; + } + int next2 = matched->second; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + +template class Graph>; diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h new file mode 100644 index 0000000..cdbbec7 --- /dev/null +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +template +class Graph { + public: + Graph(); + void addVertex(t_name name, bool open=false); + bool containsVertex(t_name name) const; + void addEdge(t_name v1, t_name v2); + const std::list adjacent(t_name vertex) const; + int matched(t_name vertex) const; + void augment(t_name vertex); + + int size() const; + int matchingSize() const; + + t_name name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::unordered_map _names; + std::unordered_map _indices; + std::vector> _adjacents; + std::unordered_map _matching; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp index 839cefc..050cf82 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -12,27 +14,36 @@ int main(int argc, char **argv){ string path = argv[1]; string pathAndFileout = argv[3]; int minGrade = atoi(argv[4]); + int mode = atoi(argv[5]); // functions allo.load(path,filein,minGrade); - allo.printProb(); + //allo.printProb(); - manlove(allo); - - allo.printSol(); - allo.checkSolution(); + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } allo.printInfo(pathAndFileout); } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(); - allo.printProb(); + allo.reduction(mode); + //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } // Model try{ @@ -140,7 +151,7 @@ int manlove(Allocation& allo){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.h +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/makefile b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/makefile index 9b4aeb1..82b1239 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/makefile +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/makefile @@ -8,14 +8,14 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_2STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +.cpp.o : $< $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : From b130ec0af0c74276a83cd3c7dfed68f823fb0061 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 21 Mar 2019 10:56:55 +0000 Subject: [PATCH 15/48] Preprocessing updates for SMTI --- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 229 ++++++- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h | 8 +- SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp | 148 +++++ SMTI/4_YESBIN_1STA_YESMERGED/Graph.h | 60 ++ SMTI/4_YESBIN_1STA_YESMERGED/makefile | 4 +- .../8_YESBIN_2STA_YESMERGED/AgentIterator.cpp | 402 ++++++++++++ SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.h | 110 ++++ SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 587 ++++++++---------- SMTI/8_YESBIN_2STA_YESMERGED/Allocation.h | 35 +- SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp | 148 +++++ SMTI/8_YESBIN_2STA_YESMERGED/Graph.h | 60 ++ SMTI/8_YESBIN_2STA_YESMERGED/main.cpp | 29 +- SMTI/8_YESBIN_2STA_YESMERGED/main.h | 2 +- SMTI/8_YESBIN_2STA_YESMERGED/makefile | 6 +- 14 files changed, 1465 insertions(+), 363 deletions(-) create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED/Graph.h create mode 100644 SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp create mode 100644 SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.h create mode 100644 SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp create mode 100644 SMTI/8_YESBIN_2STA_YESMERGED/Graph.h diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index c43d3d0..d1b1c3b 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -1,5 +1,6 @@ #include "Allocation.h" #include "AgentIterator.h" +#include "Graph.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -59,6 +60,7 @@ void Allocation::load(const string& path, const string& filein){ // Read the preferences of each child for (int i = 0; i < nbChildren; i++){ Child c; + c.mustBeAllocated = false; int temp; allRanksC[i].resize(nbFamilies,-1); allPreferencesC[i].resize(nbFamilies,-1); @@ -117,6 +119,7 @@ void Allocation::load(const string& path, const string& filein){ // Read the preferences of each family for (int i = 0; i < nbFamilies; i++){ Family f; + f.mustBeAllocated = false; int temp; allRanksF[i].resize(nbChildren,-1); allPreferencesF[i].resize(nbChildren,-1); @@ -224,17 +227,182 @@ void Allocation::printProb(){ } } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionExact(bool children_side, bool supp) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph> g; + int n_1 = 0; + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, cand_vert); + } + } + g.augment(pos_vert); + } + for(int rank = 0; rank < these[i].nbPref; rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == these[i].nbPref - 1) && (these[i].mustBeAllocated || !supp)) { + continue; + } + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + int idxRank = these[i].ranks[rank][ind]; + for(int l = 0; l <= idxRank; l++) { + for(size_t k = 0; k < other[position].preferences[l].size(); k++) { + int other_cand = other[position].preferences[l][k]; + if (other_cand == i) { // Don't add the current candidate to the graph + continue; + } + std::pair other_cand_vert = std::make_pair(0, other_cand); + if (! g.containsVertex(other_cand_vert)) { + g.addVertex(other_cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, other_cand_vert); + } + } + } + // If n_1 is sufficiently small, then the largest matching must also be + // small, as the matching can use each vertex from n_1 at most once, so + // we don't even need to try to find a bigger matching. + bool matching_cant_exist = (2*n_1 + 1 <= g.size()); + if (! matching_cant_exist) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.augment(pos_vert); + } + } + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +int Allocation::reductionMine(bool children_side, int mode) { + int nbTotRem = 0; + int number_here; + std::vector * thesep; + std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; + number_here = nbChildren; } else { thesep = &families; otherp = &children; + number_here = nbFamilies; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -262,6 +430,14 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); @@ -292,7 +468,9 @@ int Allocation::reductionMine(bool children_side, int mode) { } } } - polish(); + if (nbTotRem > 0) { + polish(); + } return nbTotRem; } @@ -358,13 +536,46 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; - do{ - num = reductionMine(true, mode); - num += reductionMine(false, mode); - cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; - i++; - total_reduced += num; - }while(num != 0); + if (mode == 7) { + do { + num = reductionMine(false, 1); + num += reductionMine(true, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(false); + num += reductionExact(true); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + } else { + do{ + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else if (mode == 8) { + num = reductionExact(true); + num += reductionExact(false); + } else if (mode == 9) { + num = reductionExact(false, true); + num += reductionExact(true, true); + } else if (mode == 10) { + num = reductionExact(true, true); + num += reductionExact(false, true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } + cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; + i++; + total_reduced += num; + }while(num != 0); + } } void Allocation::printSol(){ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h index b2be73f..f4436b4 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -24,7 +25,8 @@ public: int id; int nbPref; - int nbTotPref; + int nbTotPref; + bool mustBeAllocated; vector > preferences; vector > ranks; vector > positions; @@ -70,11 +72,15 @@ vector assignmentByChild; vector assignmentByFamily; + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + Info infos; void load(const string& path, const string& filein); void printProb(); int reductionMine(bool children_side=true, int mode=0); + int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp new file mode 100644 index 0000000..3206f4a --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -0,0 +1,148 @@ +#include +#include "Graph.h" + + + +template +Graph::Graph() { +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +template +void Graph::addVertex(t_name name, bool open) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG + std::cout << "Add vertex " << name << std::endl; +#endif /* DEBUG */ + this->_adjacents.emplace_back(); +} + +template +t_name Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +template +bool Graph::containsVertex(t_name name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +template +void Graph::addEdge(t_name v1, t_name v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + _adjacents[i1].push_back(i2); + _adjacents[i2].push_back(i1); +} + +template +int Graph::size() const { + return _names.size(); +} + +template +int Graph::matchingSize() const { + // for a matched edge (a,b), our _matching map stores both _matching[a] = b + // and _matching[b] = a. + return _matching.size() / 2; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +template +void Graph::augment(t_name name) { + int start = this->_names[name]; +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(size(), false); + path.push_back(start); + internal_augment(start, visited, path); +} + +#ifdef DEBUG +template +void Graph::printGraph() { + for(size_t ind = 0; ind < _adjacents.size(); ++ind) { + std::cout << _indices[ind] << ":"; + for(auto adj: _adjacents[ind]) { + std::cout << " " << _indices[adj]; + } + std::cout << std::endl; + } +} + +template +void Graph::printMatching() const { + for(auto p: _matching) { + int a = p.first; + int b = p.second; + if (a <= b) { + std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; + } + } +} + +#endif /* DEBUG */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +template +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[now]) { + if (visited[next]) { + continue; + } + auto matched = _matching.find(next); + if (matched == _matching.end()) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[right] = left; + _matching[left] = right; + } + + return true; + } + int next2 = matched->second; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + +template class Graph>; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h new file mode 100644 index 0000000..cdbbec7 --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +template +class Graph { + public: + Graph(); + void addVertex(t_name name, bool open=false); + bool containsVertex(t_name name) const; + void addEdge(t_name v1, t_name v2); + const std::list adjacent(t_name vertex) const; + int matched(t_name vertex) const; + void augment(t_name vertex); + + int size() const; + int matchingSize() const; + + t_name name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::unordered_map _names; + std::unordered_map _indices; + std::vector> _adjacents; + std::unordered_map _matching; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/makefile b/SMTI/4_YESBIN_1STA_YESMERGED/makefile index dc2d4f3..3398d88 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/makefile +++ b/SMTI/4_YESBIN_1STA_YESMERGED/makefile @@ -10,12 +10,12 @@ GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o AgentIterator.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_1STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +.cpp.o : $< $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp new file mode 100644 index 0000000..6210288 --- /dev/null +++ b/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.cpp @@ -0,0 +1,402 @@ +#include "AgentIterator.h" + +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; +} + +int AgentIteratorBase::get_position() const { + return _position; +} + +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; +} + +void AgentIteratorBase::regularIncrement() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); +} + +AgentIterator AgentIterator::begin() { + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; +} + +AgentIterator AgentIterator::end() { + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; +} + +int AgentIterator::get_group() const { + return base->get_group(); +} + +int AgentIterator::get_position() const { + return base->get_position(); +} + +int AgentIterator::get_mode() const { + return _mode; +} + +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } +} + +void SkipBigIterator::increment() { + int num_added = 0; + do { + regularIncrement(); + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + } while (num_added > _skip); +} + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.h b/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.h new file mode 100644 index 0000000..48b96c6 --- /dev/null +++ b/SMTI/8_YESBIN_2STA_YESMERGED/AgentIterator.h @@ -0,0 +1,110 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { + public: + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; +}; + +class BestIterator : public AgentIteratorBase { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestIterator() {} + void increment(); + void begin(); +}; + +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 44a6851..d1b1c3b 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -1,29 +1,17 @@ #include "Allocation.h" +#include "AgentIterator.h" +#include "Graph.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** ************************************************************************************* */ -void Child::print(){ - cout << "Child " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; - for(int i=0; i 0) cout << " "; - cout << preferences[i][j]; - cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; - } - cout << ") "; - } - cout << endl; -} - -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - -void Family::print(){ - cout << "Family " << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbChildren,0); - if(families[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } - -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << families[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbChildren); - for(int i=0;i= families[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < families[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(families[(*it).second[j]].ranks[0][i]); - } - // cout << "worstRank of " << families[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[families[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, families[(*it).second[0]].preferences[0].size() - 1); - worstRank[families[(*it).second[0]].preferences[0][i]]=min(worstRank[families[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[families[(*it).second[0]].preferences[0][i]] << endl; - } - } - } - - // Step 3 -- Remove families after worst rank from child's preferences - +int Allocation::reductionExact(bool children_side, bool supp) { int nbTotRem = 0; - - for(int i=0; i * thesep; + std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph> g; + int n_1 = 0; + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } } - families[idxFam].nbTotPref--; - families[idxFam].positions[idxRank].erase(families[idxFam].positions[idxRank].begin() + idxPos); - families[idxFam].ranks[idxRank].erase(families[idxFam].ranks[idxRank].begin() + idxPos); - families[idxFam].preferences[idxRank].erase(families[idxFam].preferences[idxRank].begin() + idxPos); } - } - children[i].nbPref = worstRank[i] + 1; - children[i].preferences.resize(children[i].nbPref); - children[i].ranks.resize(children[i].nbPref); - children[i].positions.resize(children[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionChi1(){ - - // Step 1 -- Create map - - int count = 0; - map, vector >::iterator it; - map, vector > mapFirstChoice; - for(int j=0; j temp(nbFamilies,0); - if(children[j].nbPref > 0){ - for(int k=0;k, vector > add; - add.first = temp; - add.second.push_back(j); - mapFirstChoice.insert(add); - } - else{ - (*it).second.push_back(j); - } - } - else count++; - } -/* for(it = mapFirstChoice.begin(); it!= mapFirstChoice.end(); ++it){ - cout << (*it).second.size() << " x (" << children[(*it).second[0]].preferences[0].size() << ") ["; - for(int i=0;i<(*it).second.size();i++){ - cout << (*it).second[i] << " "; - } - cout << "] == ["; - for(int i=0;i<(*it).first.size();i++){ - cout << (*it).first[i] << " "; - } - cout << "]" << endl; - } - - cout << "Count = " << count << endl;*/ - - // Step 2 -- See worst rank - - vector worstRank(nbFamilies); - for(int i=0;i= children[(*it).second[0]].preferences[0].size() ){ - // cout << "Updates from " << co << endl;; co++; - for(int i=0; i < children[(*it).second[0]].preferences[0].size();i++){ - multiset orderedRanks; - multiset::iterator it2; - for(int j=0; j<(*it).second.size();j++){ - orderedRanks.insert(children[(*it).second[j]].ranks[0][i]); + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, cand_vert); } - // cout << "worstRank of " << children[(*it).second[0]].preferences[0][i] << " updated from " << worstRank[children[(*it).second[0]].preferences[0][i]]; - it2 = orderedRanks.begin(); - advance(it2, children[(*it).second[0]].preferences[0].size() - 1); - worstRank[children[(*it).second[0]].preferences[0][i]]=min(worstRank[children[(*it).second[0]].preferences[0][i]], *(it2)); - // cout << " to " << worstRank[children[(*it).second[0]].preferences[0][i]] << endl; } + g.augment(pos_vert); } - } - - // Step 3 -- Remove families after worst rank from child's preferences - - int nbTotRem = 0; - - for(int i=0; i other_cand_vert = std::make_pair(0, other_cand); + if (! g.containsVertex(other_cand_vert)) { + g.addVertex(other_cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, other_cand_vert); + } } - children[idxChi].nbTotPref--; - children[idxChi].positions[idxRank].erase(children[idxChi].positions[idxRank].begin() + idxPos); - children[idxChi].ranks[idxRank].erase(children[idxChi].ranks[idxRank].begin() + idxPos); - children[idxChi].preferences[idxRank].erase(children[idxChi].preferences[idxRank].begin() + idxPos); } - } - families[i].nbPref = worstRank[i] + 1; - families[i].preferences.resize(families[i].nbPref); - families[i].ranks.resize(families[i].nbPref); - families[i].positions.resize(families[i].nbPref); - } - - polish(); - return nbTotRem; -} - -int Allocation::reductionFam2(){ - - int nbTotRem = 0; - vector worstRank(nbChildren); - for(int i=0;i allChildren; - int count = 0; - for(int j=0; j= allChildren.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ break; } } } - - for(int i=0; i 0) { + polish(); } - - polish(); return nbTotRem; } -int Allocation::reductionChi2(){ - +int Allocation::reductionMine(bool children_side, int mode) { int nbTotRem = 0; - vector worstRank(nbFamilies); - for(int i=0;i allFamilies; - int count = 0; - for(int j=0; j * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + int worst_rank = 0; + unsigned int count = 0; + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { + int j = p.first; + int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + candidates.insert(other[idxFam].preferences[l][m]); } } - if(count >= allFamilies.size()){ - worstRank[i] = j; - // cout << "worst rank of " << i << " is " << j << endl; + if (count >= candidates.size()) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = worst_rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); break; } } } - - for(int i=0; i 0) { + polish(); } - - polish(); return nbTotRem; } @@ -605,20 +532,50 @@ void Allocation::polish(){ } } -void Allocation::reduction(){ - int nbRed1 = 0; - int nbRed2 = 0; - int nbRed3 = 0; - int nbRed4 = 0; +void Allocation::reduction(int mode){ + total_reduced = 0; int i = 0; - do{ - nbRed1 = reductionFam1(); - nbRed2 = reductionChi1(); - nbRed3 = reductionFam2(); - nbRed4 = reductionChi2(); - cout << "Reduction iteration " << i << " reductionFam1 " << nbRed1 << " reductionChi1 " << nbRed2 << " reductionFam2 " << nbRed3 << " reductionChi2 " << nbRed4 << endl; - i++; - }while(nbRed1 + nbRed2 + nbRed3 + nbRed4 != 0); + int num = 0; + if (mode == 7) { + do { + num = reductionMine(false, 1); + num += reductionMine(true, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(false); + num += reductionExact(true); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + } else { + do{ + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else if (mode == 8) { + num = reductionExact(true); + num += reductionExact(false); + } else if (mode == 9) { + num = reductionExact(false, true); + num += reductionExact(true, true); + } else if (mode == 10) { + num = reductionExact(true, true); + num += reductionExact(false, true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } + cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; + i++; + total_reduced += num; + }while(num != 0); + } } void Allocation::printSol(){ @@ -631,7 +588,7 @@ void Allocation::printSol(){ void Allocation::printInfo(const string& pathAndFileout){ string nameFile = pathAndFileout; std::ofstream file(nameFile.c_str(), std::ios::out | std::ios::app); - file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t"<< infos.LB << "\t" << infos.UB << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ + file << name << "\t" << infos.opt << "\t" << infos.timeCPU << "\t" << infos.timeCPUPP << "\t" << total_reduced << "\t"<< infos.LB << "\t" << infos.UB << "\t" << infos.contUB << "\t" << infos.nbVar << "\t" << infos.nbCons << "\t" << infos.nbNZ << "\t" << infos.contUB2 << "\t" << infos.nbVar2 << "\t" << infos.nbCons2 << "\t" << infos.nbNZ2 << endl; file.close(); } diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.h b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.h index dcd6046..def9c6e 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.h +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -12,7 +13,7 @@ #include class Child; - class Family; + typedef Child Family; class Assignment; class Allocation; @@ -21,29 +22,15 @@ ************************************************************************************* */ class Child{ - public: - int id; - int nbPref; - int nbTotPref; - vector > preferences; - vector > ranks; - vector > positions; - void print(); - }; - -/* ************************************************************************************* - *********************************** HOSPITAL **************************************** - ************************************************************************************* */ - - class Family{ public: int id; int nbPref; int nbTotPref; + bool mustBeAllocated; vector > preferences; vector > ranks; vector > positions; - void print(); + void print(bool); }; /* ************************************************************************************* @@ -76,6 +63,7 @@ string name; int nbChildren; int nbFamilies; + int total_reduced; vector children; vector families; @@ -84,20 +72,21 @@ vector assignmentByChild; vector assignmentByFamily; + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + Info infos; void load(const string& path, const string& filein); void printProb(); - int reductionFam1(); - int reductionChi1(); - int reductionFam2(); - int reductionChi2(); + int reductionMine(bool children_side=true, int mode=0); + int reductionExact(bool children_side=true, bool supp=false); void polish(); - void reduction(); + void reduction(int mode); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); }; -#endif \ No newline at end of file +#endif diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp new file mode 100644 index 0000000..3206f4a --- /dev/null +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp @@ -0,0 +1,148 @@ +#include +#include "Graph.h" + + + +template +Graph::Graph() { +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +template +void Graph::addVertex(t_name name, bool open) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG + std::cout << "Add vertex " << name << std::endl; +#endif /* DEBUG */ + this->_adjacents.emplace_back(); +} + +template +t_name Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +template +bool Graph::containsVertex(t_name name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +template +void Graph::addEdge(t_name v1, t_name v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + _adjacents[i1].push_back(i2); + _adjacents[i2].push_back(i1); +} + +template +int Graph::size() const { + return _names.size(); +} + +template +int Graph::matchingSize() const { + // for a matched edge (a,b), our _matching map stores both _matching[a] = b + // and _matching[b] = a. + return _matching.size() / 2; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +template +void Graph::augment(t_name name) { + int start = this->_names[name]; +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(size(), false); + path.push_back(start); + internal_augment(start, visited, path); +} + +#ifdef DEBUG +template +void Graph::printGraph() { + for(size_t ind = 0; ind < _adjacents.size(); ++ind) { + std::cout << _indices[ind] << ":"; + for(auto adj: _adjacents[ind]) { + std::cout << " " << _indices[adj]; + } + std::cout << std::endl; + } +} + +template +void Graph::printMatching() const { + for(auto p: _matching) { + int a = p.first; + int b = p.second; + if (a <= b) { + std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; + } + } +} + +#endif /* DEBUG */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +template +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[now]) { + if (visited[next]) { + continue; + } + auto matched = _matching.find(next); + if (matched == _matching.end()) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[right] = left; + _matching[left] = right; + } + + return true; + } + int next2 = matched->second; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + +template class Graph>; diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h new file mode 100644 index 0000000..cdbbec7 --- /dev/null +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +template +class Graph { + public: + Graph(); + void addVertex(t_name name, bool open=false); + bool containsVertex(t_name name) const; + void addEdge(t_name v1, t_name v2); + const std::list adjacent(t_name vertex) const; + int matched(t_name vertex) const; + void augment(t_name vertex); + + int size() const; + int matchingSize() const; + + t_name name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::unordered_map _names; + std::unordered_map _indices; + std::vector> _adjacents; + std::unordered_map _matching; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp index f4e2ae3..5eadbd9 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp +++ b/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp @@ -1,5 +1,7 @@ #include "main.h" +#define MAXTIME 3600 + /* ************************************************************************************* ************************************* MAIN ***************************************** ************************************************************************************* */ @@ -11,27 +13,36 @@ int main(int argc, char **argv){ string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); // functions allo.load(path, filein); - allo.printProb(); + //allo.printProb(); - manlove(allo); - - allo.printSol(); - allo.checkSolution(); + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } allo.printInfo(pathAndFileout); } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(); - allo.printProb(); + allo.reduction(mode); + //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies, -1); + return -1; + } // Model try{ @@ -139,7 +150,7 @@ int manlove(Allocation& allo){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); model.optimize(); diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/main.h b/SMTI/8_YESBIN_2STA_YESMERGED/main.h index c441859..3bf5282 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/main.h +++ b/SMTI/8_YESBIN_2STA_YESMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/makefile b/SMTI/8_YESBIN_2STA_YESMERGED/makefile index 9b4aeb1..82b1239 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/makefile +++ b/SMTI/8_YESBIN_2STA_YESMERGED/makefile @@ -8,14 +8,14 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_2STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +.cpp.o : $< $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : From e5e0b475fd40c86bc284c2aca2ffd2b84d5c3d56 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 22 Mar 2019 11:30:01 +0000 Subject: [PATCH 16/48] Missed updates to a model --- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 229 ++++++++++++++++++++- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h | 8 +- SMTI/3_NOBIN_1STA_YESMERGED/makefile | 4 +- 3 files changed, 229 insertions(+), 12 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index c43d3d0..d1b1c3b 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -1,5 +1,6 @@ #include "Allocation.h" #include "AgentIterator.h" +#include "Graph.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -59,6 +60,7 @@ void Allocation::load(const string& path, const string& filein){ // Read the preferences of each child for (int i = 0; i < nbChildren; i++){ Child c; + c.mustBeAllocated = false; int temp; allRanksC[i].resize(nbFamilies,-1); allPreferencesC[i].resize(nbFamilies,-1); @@ -117,6 +119,7 @@ void Allocation::load(const string& path, const string& filein){ // Read the preferences of each family for (int i = 0; i < nbFamilies; i++){ Family f; + f.mustBeAllocated = false; int temp; allRanksF[i].resize(nbChildren,-1); allPreferencesF[i].resize(nbChildren,-1); @@ -224,17 +227,182 @@ void Allocation::printProb(){ } } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionExact(bool children_side, bool supp) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph> g; + int n_1 = 0; + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, cand_vert); + } + } + g.augment(pos_vert); + } + for(int rank = 0; rank < these[i].nbPref; rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == these[i].nbPref - 1) && (these[i].mustBeAllocated || !supp)) { + continue; + } + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, false); + int idxRank = these[i].ranks[rank][ind]; + for(int l = 0; l <= idxRank; l++) { + for(size_t k = 0; k < other[position].preferences[l].size(); k++) { + int other_cand = other[position].preferences[l][k]; + if (other_cand == i) { // Don't add the current candidate to the graph + continue; + } + std::pair other_cand_vert = std::make_pair(0, other_cand); + if (! g.containsVertex(other_cand_vert)) { + g.addVertex(other_cand_vert, true); + n_1 += 1; + } + g.addEdge(pos_vert, other_cand_vert); + } + } + } + // If n_1 is sufficiently small, then the largest matching must also be + // small, as the matching can use each vertex from n_1 at most once, so + // we don't even need to try to find a bigger matching. + bool matching_cant_exist = (2*n_1 + 1 <= g.size()); + if (! matching_cant_exist) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + auto pos_vert = std::make_pair(1, position); + g.augment(pos_vert); + } + } + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +int Allocation::reductionMine(bool children_side, int mode) { + int nbTotRem = 0; + int number_here; + std::vector * thesep; + std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; + number_here = nbChildren; } else { thesep = &families; otherp = &children; + number_here = nbFamilies; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -262,6 +430,14 @@ int Allocation::reductionMine(bool children_side, int mode) { } } if (count >= candidates.size()) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ for (int k = worst_rank + 1; k < these[i].nbPref; k++) { nbTotRem += these[i].preferences[k].size(); these[i].nbTotPref -= these[i].preferences[k].size(); @@ -292,7 +468,9 @@ int Allocation::reductionMine(bool children_side, int mode) { } } } - polish(); + if (nbTotRem > 0) { + polish(); + } return nbTotRem; } @@ -358,13 +536,46 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; - do{ - num = reductionMine(true, mode); - num += reductionMine(false, mode); - cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; - i++; - total_reduced += num; - }while(num != 0); + if (mode == 7) { + do { + num = reductionMine(false, 1); + num += reductionMine(true, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(false); + num += reductionExact(true); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + } else { + do{ + if (mode == 6) { + // True means preprocess childrens' lists, removing families. + // False means preprocess families' lists, removing children. + num = reductionExact(false); + num += reductionExact(true); + } else if (mode == 8) { + num = reductionExact(true); + num += reductionExact(false); + } else if (mode == 9) { + num = reductionExact(false, true); + num += reductionExact(true, true); + } else if (mode == 10) { + num = reductionExact(true, true); + num += reductionExact(false, true); + } else { + num = reductionMine(false, mode); + num += reductionMine(true, mode); + } + cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; + i++; + total_reduced += num; + }while(num != 0); + } } void Allocation::printSol(){ diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h index b2be73f..f4436b4 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -24,7 +25,8 @@ public: int id; int nbPref; - int nbTotPref; + int nbTotPref; + bool mustBeAllocated; vector > preferences; vector > ranks; vector > positions; @@ -70,11 +72,15 @@ vector assignmentByChild; vector assignmentByFamily; + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + Info infos; void load(const string& path, const string& filein); void printProb(); int reductionMine(bool children_side=true, int mode=0); + int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/makefile b/SMTI/3_NOBIN_1STA_YESMERGED/makefile index f0fc99d..091fe72 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/makefile +++ b/SMTI/3_NOBIN_1STA_YESMERGED/makefile @@ -10,12 +10,12 @@ GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o AgentIterator.o +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o 3_NOBIN_1STA_YESMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : +.cpp.o : $< $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : From 2e53b641a351d868d1b3138646ff6f55fd7fe628 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 22 Mar 2019 11:31:11 +0000 Subject: [PATCH 17/48] Ooops, missed the graph --- SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp | 148 ++++++++++++++++++++++++++ SMTI/3_NOBIN_1STA_YESMERGED/Graph.h | 60 +++++++++++ 2 files changed, 208 insertions(+) create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED/Graph.h diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp new file mode 100644 index 0000000..3206f4a --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp @@ -0,0 +1,148 @@ +#include +#include "Graph.h" + + + +template +Graph::Graph() { +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +template +void Graph::addVertex(t_name name, bool open) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG + std::cout << "Add vertex " << name << std::endl; +#endif /* DEBUG */ + this->_adjacents.emplace_back(); +} + +template +t_name Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +template +bool Graph::containsVertex(t_name name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +template +void Graph::addEdge(t_name v1, t_name v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + _adjacents[i1].push_back(i2); + _adjacents[i2].push_back(i1); +} + +template +int Graph::size() const { + return _names.size(); +} + +template +int Graph::matchingSize() const { + // for a matched edge (a,b), our _matching map stores both _matching[a] = b + // and _matching[b] = a. + return _matching.size() / 2; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +template +void Graph::augment(t_name name) { + int start = this->_names[name]; +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(size(), false); + path.push_back(start); + internal_augment(start, visited, path); +} + +#ifdef DEBUG +template +void Graph::printGraph() { + for(size_t ind = 0; ind < _adjacents.size(); ++ind) { + std::cout << _indices[ind] << ":"; + for(auto adj: _adjacents[ind]) { + std::cout << " " << _indices[adj]; + } + std::cout << std::endl; + } +} + +template +void Graph::printMatching() const { + for(auto p: _matching) { + int a = p.first; + int b = p.second; + if (a <= b) { + std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; + } + } +} + +#endif /* DEBUG */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +template +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[now]) { + if (visited[next]) { + continue; + } + auto matched = _matching.find(next); + if (matched == _matching.end()) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[right] = left; + _matching[left] = right; + } + + return true; + } + int next2 = matched->second; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + +template class Graph>; diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h new file mode 100644 index 0000000..cdbbec7 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +template +class Graph { + public: + Graph(); + void addVertex(t_name name, bool open=false); + bool containsVertex(t_name name) const; + void addEdge(t_name v1, t_name v2); + const std::list adjacent(t_name vertex) const; + int matched(t_name vertex) const; + void augment(t_name vertex); + + int size() const; + int matchingSize() const; + + t_name name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::unordered_map _names; + std::unordered_map _indices; + std::vector> _adjacents; + std::unordered_map _matching; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ From 3705c6ed376fb72101f3cdcb294837af14f660c1 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 22 Mar 2019 16:13:41 +0000 Subject: [PATCH 18/48] Add mode 11 --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 15 +++++++++++++++ SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 15 +++++++++++++++ SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 15 +++++++++++++++ SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 15 +++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 43b21f6..a06f132 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -477,6 +477,21 @@ void Allocation::reduction(int mode){ i++; total_reduced += num; } while (num != 0); + } else if (mode == 11) { + do { + num = reductionMine(true, 1); + num += reductionMine(false, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(true); + num += reductionExact(false); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); } else { do{ if (mode == 6) { diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 43b21f6..a06f132 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -477,6 +477,21 @@ void Allocation::reduction(int mode){ i++; total_reduced += num; } while (num != 0); + } else if (mode == 11) { + do { + num = reductionMine(true, 1); + num += reductionMine(false, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(true); + num += reductionExact(false); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); } else { do{ if (mode == 6) { diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index d1b1c3b..7b3b0f0 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -551,6 +551,21 @@ void Allocation::reduction(int mode){ i++; total_reduced += num; } while (num != 0); + } else if (mode == 11) { + do { + num = reductionMine(true, 1); + num += reductionMine(false, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(true); + num += reductionExact(false); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); } else { do{ if (mode == 6) { diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index d1b1c3b..7b3b0f0 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -551,6 +551,21 @@ void Allocation::reduction(int mode){ i++; total_reduced += num; } while (num != 0); + } else if (mode == 11) { + do { + num = reductionMine(true, 1); + num += reductionMine(false, 1); + cout << "Iteration " << i << " in heuristic removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); + do { + num = reductionExact(true); + num += reductionExact(false); + cout << "Iteration " << i << " in exact mode removed " << num << std::endl; + i++; + total_reduced += num; + } while (num != 0); } else { do{ if (mode == 6) { From b013d35879cbc5bf8ed60e3bda047df6e2347b17 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 10 Apr 2019 09:29:24 +0100 Subject: [PATCH 19/48] Add preprocessing for HRT --- HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.cpp | 850 +++++++++++++++++++ HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.h | 116 +++ HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp | 470 +++++++++- HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp | 199 +++++ HRT/8_YESBIN_3STA_NOMERGED/Graph.h | 82 ++ HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 16 +- HRT/8_YESBIN_3STA_NOMERGED/makefile | 8 +- 7 files changed, 1711 insertions(+), 30 deletions(-) create mode 100644 HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.cpp create mode 100644 HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.h create mode 100644 HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp create mode 100644 HRT/8_YESBIN_3STA_NOMERGED/Graph.h diff --git a/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.cpp b/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.cpp new file mode 100644 index 0000000..934d411 --- /dev/null +++ b/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.cpp @@ -0,0 +1,850 @@ +#include "AgentIterator.h" +#include "Allocation.h" + +template +AgentIteratorBase::AgentIteratorBase(const t_these& agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +template +AgentIteratorBase::~AgentIteratorBase() { } + +template +int AgentIteratorBase::get_group() const { + return _group; +} + +template +int AgentIteratorBase::get_position() const { + return _position; +} + +template +const t_these & AgentIteratorBase::get_agent() const { + return _agent; +} + +template +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +template +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} + +template +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} + +template +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; +} + +template <> +void AgentIteratorBase::regularIncrement() { + _group++; + if ((int)_agent.preferences.size() == _group) { + _group = -1; + } +} + +template +void AgentIteratorBase::regularIncrement() { + _position++; + if ((int)_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if ((int)_agent.preferences.size() == _group) { + _group = -1; + } + } +} + +template +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +template +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +template +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); +} + +template +AgentIterator AgentIterator::begin() { + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; +} + +template +AgentIterator AgentIterator::end() { + return AgentIterator(this, -1, 0); +} + +template +AgentIterator::AgentIterator(const t_these & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +template +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +template +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +template +AgentIterator::~AgentIterator() { + delete base; +} + +template +int AgentIterator::get_group() const { + return base->get_group(); +} + +template +int AgentIterator::get_position() const { + return base->get_position(); +} + +template +int AgentIterator::get_mode() const { + return _mode; +} + +template +DescendingIterator::DescendingIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +template +void DescendingIterator::begin() { +} + +template +void DescendingIterator::increment() { + this->regularIncrement(); +} + +template +SkipBigIterator::SkipBigIterator(const t_these& agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + +template <> +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group]; + bool break_yet = false; + for(auto & group: this->_other[other_id-1].preferences) { + for(auto pref: group) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + if (pref == this->_agent.id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + if (num_added > _skip) { + this->regularIncrement(); + } else { + break; + } + } +} + +template <> +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group][this->_position]; + for(auto pref: this->_other[other_id-1].preferences) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + if (pref == this->_agent.id) { + break; + } + } + if (num_added > _skip) { + this->regularIncrement(); + } else { + break; + } + } +} + +template +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group][this->_position]; + int other_rank = this->_agent.ranks[this->_group][this->_position]; + bool break_yet = false; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + if (pref == this->_agent.id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + if (num_added > _skip) { + this->regularIncrement(); + } else { + break; + } + } +} + +template <> +void SkipBigIterator::increment() { + int num_added = 0; + do { + this->regularIncrement(); + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group][this->_position]; + for(auto pref: _other[other_id-1].preferences) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + if (pref == this->_agent.id) { + break; + } + } + } while (num_added > _skip); +} + +template<> +void SkipBigIterator::increment() { + int num_added = 0; + do { + this->regularIncrement(); + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group]; + bool break_yet = false; + for(auto & group: _other[other_id-1].preferences) { + for(auto pref: group) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + if (pref == _agent.id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + } while (num_added > _skip); +} + +template +void SkipBigIterator::increment() { + int num_added = 0; + do { + this->regularIncrement(); + if (this->get_group() == -1) { + break; + } + num_added = 0; + int other_id = this->_agent.preferences[this->_group][this->_position]; + int other_rank = this->_agent.ranks[this->_group][this->_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(pref) == 0) { + num_added++; + } + } + } + } while (num_added > _skip); +} + +template +BestIterator::BestIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +template <> +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(size_t group_no = 0; group_no < this->_agent.preferences.size(); ++group_no) { + auto & group = this->_agent.preferences[group_no]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + for(auto other_pref: this->_other[other_id-1].preferences) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template <> +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(size_t posn = 0; posn < this->_agent.preferences.size(); ++posn) { + int other_id = this->_agent.preferences[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool break_yet = false; + for(auto & group: this->_other[other_id-1].preferences) { + for(auto other_pref: group) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break_yet = true; + } + if (break_yet) { + break; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = posn; + best_posn = 0; + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < this->_agent.preferences.size(); ++group_no) { + auto & group = this->_agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = this->_agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template <> +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(size_t group_no = 0; group_no < this->_agent.preferences.size(); ++group_no) { + auto & group = this->_agent.preferences; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool break_yet = false; + for(size_t group_ind = 0; group_ind < this->_other[other_id-1].preferences.size(); group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template <> +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(size_t group_no = 0; group_no < this->_agent.preferences.size(); ++group_no) { + auto & group = this->_agent.preferences[group_no]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + for(auto other_pref: this->_other[other_id-1].preferences) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == other_id) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(size_t group_no = 0; group_no < this->_agent.preferences.size(); ++group_no) { + auto & group = this->_agent.preferences[group_no]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = this->_agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + this->_group = best_group; + this->_position = best_posn; + } else { + this->_group = -1; + this->_position = 0; + } +} + +template +BestGroupIterator::BestGroupIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +template <> +void BestGroupIterator::increment() { + this->_position = 0; + this->_group++; + if (this->_group == (int)this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } +} + +template<> +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + const std::vector & group = this->_agent.preferences[this->_group]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + for(auto other_pref: this->_other[other_id-1].preferences) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + this->_position = best_posn; + } else { + this->_group++; + if (this->_group == (int)this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } else { + increment(); + } + } +} + +template +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = this->_agent.preferences[this->_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = this->_agent.ranks[this->_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + this->_position = best_posn; + } else { + this->_group++; + if (this->_group == this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } else { + increment(); + } + } +} + +template <> +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (this->_group == -1) { + return; + } + auto & group = this->_agent.preferences[this->_group]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + for(auto other_pref: this->_other[other_id-1].preferences) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + this->_position = best_posn; + } else { + this->_group++; + if (this->_group == (int)this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } else { + increment(); + } + } +} + +template <> +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (this->_group == -1) { + return; + } + for(size_t posn = 0; posn < this->_agent.preferences.size(); ++posn) { + int other_id = this->_agent.preferences[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + bool break_yet = false; + for(size_t group_ind = 0; group_ind < this->_other[other_id-1].preferences.size(); group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + if (other_pref == this->_agent.id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + this->_position = best_posn; + } else { + this->_group++; + if (this->_group == (int)this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } else { + increment(); + } + } +} + +template +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (this->_group == -1) { + return; + } + auto & group = this->_agent.preferences[this->_group]; + for(size_t posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (this->_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = this->_agent.ranks[this->_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: this->_other[other_id-1].preferences[group_ind]) { + if (this->_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + this->_position = best_posn; + } else { + this->_group++; + if (this->_group == this->_agent.preferences.size()) { + this->_position = 0; + this->_group = -1; + } else { + increment(); + } + } +} + +template class AgentIterator; +template class AgentIterator; + diff --git a/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.h b/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.h new file mode 100644 index 0000000..85c4a16 --- /dev/null +++ b/HRT/8_YESBIN_3STA_NOMERGED/AgentIterator.h @@ -0,0 +1,116 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + +template +class AgentIteratorBase { +public: + AgentIteratorBase(const t_these & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const t_these & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const t_these & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +template +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const t_these & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const t_these & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +template +class DescendingIterator : public AgentIteratorBase { + public: + DescendingIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +template +class SkipBigIterator : public AgentIteratorBase { + public: + SkipBigIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; +}; + +template +class BestIterator : public AgentIteratorBase { + public: + BestIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestIterator() {} + void increment(); + void begin(); +}; + +template +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const t_these & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; + +#endif /* AGENTITERATOR_H */ diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp index 1705993..d8b050e 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp @@ -1,4 +1,9 @@ +#include + #include "Allocation.h" +#include "AgentIterator.h" +#include "Graph.h" +#include "time.h" /* ************************************************************************************* *********************************** DOCTOR ***************************************** @@ -18,7 +23,7 @@ void Hospital::print(){ cout << "Hospital " << id << "\t Capacity " << cap << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; for(int i=0; i 0) cout << " "; cout << preferences[i][j]; } @@ -169,11 +174,11 @@ int Allocation::reductionHosOff(){ hbm = false; for(int j=0; j candidates; + set positions; + int worst_rank = 0; + unsigned int count = 0; + AgentIterator iter(doctors[i], candidates, positions, doctors, hospitals, mode); + for(std::pair p: iter) { + int j = p.first; + if (j > worst_rank) { + worst_rank = j; + } + int idxHos = doctors[i].preferences[j] - 1; + positions.insert(idxHos+1); + count += hospitals[idxHos].cap; + for (auto & group: hospitals[idxHos].preferences) { + bool break_yet = false; + for(int pref: group) { + candidates.insert(pref); + if (pref == doctors[i].id) { + break_yet = true; + } + } + if (break_yet) { + break; + } + } + if (count >= candidates.size()) { +#ifdef DEBUG + std::cout << "doctor worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < doctors[i].nbPref; k++) { + nbTotRem += 1; + int idxHos = doctors[i].preferences[k] - 1; + for(size_t rank = 0; rank < hospitals[idxHos].preferences.size(); ++rank) { + auto posDoc = std::find(hospitals[idxHos].preferences[rank].begin(), hospitals[idxHos].preferences[rank].end(), i+1); + if (posDoc != hospitals[idxHos].preferences[rank].end()) { + hospitals[idxHos].preferences[rank].erase(posDoc); + hospitals[idxHos].nbTotPref--; + } + } + } + doctors[i].nbPref = worst_rank + 1; + doctors[i].preferences.resize(doctors[i].nbPref); + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +int Allocation::reductionMineHospitals(int mode) { + int nbTotRem = 0; + + for (int i = 0; i < nbHospitals; i++) { + set candidates; + set positions; + unsigned int candidate_cap = 0; + int worst_rank = 0; + unsigned int count = 0; +#ifdef DEBUG + std::cout << "Preprocessing hospital " << i << std::endl; +#endif /* DEBUG */ + AgentIterator iter(hospitals[i], candidates, positions, hospitals, doctors, mode); + for(std::pair p: iter) { + int j = p.first; + int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } + int idxDoc = hospitals[i].preferences[j][k] - 1; + positions.insert(idxDoc+1); + count += 1; + for (int pref: doctors[idxDoc].preferences) { + if (candidates.count(pref) == 0) { + candidates.insert(pref); + candidate_cap += hospitals[pref-1].cap; + } + if (pref == hospitals[i].id) { + break; + } + } + if (count >= candidate_cap) { +#ifdef DEBUG + std::cout << "hospital worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < hospitals[i].nbPref; k++) { + nbTotRem += hospitals[i].preferences[k].size(); + hospitals[i].nbTotPref -= hospitals[i].preferences[k].size(); + for (unsigned int l = 0; l < hospitals[i].preferences[k].size(); l++) { + int idxDoc = hospitals[i].preferences[k][l] - 1; + for (size_t m = 0 ; m < doctors[idxDoc].preferences.size(); ++m) { + if (doctors[idxDoc].preferences[m] == i + 1) { + doctors[idxDoc].preferences.erase(doctors[idxDoc].preferences.begin() + m); + doctors[idxDoc].ranks.erase(doctors[idxDoc].ranks.begin() + m); + doctors[idxDoc].nbPref--; + nbTotRem++; + break; + } + } + } + } + hospitals[i].nbPref = worst_rank + 1; + hospitals[i].preferences.resize(hospitals[i].nbPref); + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + + int Allocation::reductionResApp(){ int nbTotRem = 0; @@ -234,13 +359,13 @@ int Allocation::reductionResApp(){ count += currentAssignmentByHospital[idxHos][k].size(); if(count >= hospitals[idxHos].cap){ for(int l = k+1; l doctor_cand_vert = std::make_pair(0, doctor_cand); + if (! g.containsVertex(doctor_cand_vert)) { + g.addVertex(doctor_cand_vert, true); + } + g.addEdge(pos_vert, doctor_cand_vert); + } + if (break_yet) { + break; + } + } + // max_flow is <= min(g.cap_left(), g.cap_right()), so we can do simple + // checks which might mean we can not bother trying to augment + bool can_def_preprocess = 1 + 2*g.cap_left() <= g.cap_total(); + if (1 + g.cap_left() + g.cap_right() <= g.cap_total()) { + can_def_preprocess = true; + } + if (!can_def_preprocess) { + while (g.augment()) { + // Empty loop on purpose, we keep augmenting while we can keep + // augmenting. + } + } + if (can_def_preprocess || g.can_preprocess()) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !doctors[i].mustBeAllocated) { + doctorsMustBeAllocated.push_back(i); + doctors[i].mustBeAllocated = true; + } +#ifdef DEBUG + if (i == 6) { + //std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + //std::cout << ", n_1 = " << n_1 << std::endl; + //g.printGraph(); + //g.printMatching(); + } + std::cout << "doctor worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < doctors[i].nbPref; k++) { + nbTotRem += 1; +#ifdef DEBUG + remHere += 1; +#endif /* DEBUG */ + int idxHos = doctors[i].preferences[k] - 1; + // remove from idxHos any reference to i. + for(size_t rank = 0 ; rank < hospitals[idxHos].preferences.size(); ++rank) { + auto posDoc = std::find(hospitals[idxHos].preferences[rank].begin(), hospitals[idxHos].preferences[rank].end(), i + 1); + if (posDoc != hospitals[idxHos].preferences[rank].end()) { + hospitals[idxHos].preferences[rank].erase(posDoc); + } + } + } + doctors[i].nbPref = rank + 1; + doctors[i].preferences.resize(doctors[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +/** + * Reduce on the hospital's preference lists, removing doctors. + */ +int Allocation::reductionExactHospital(bool supp) { + int nbTotRem = 0; + for (size_t i = 0; i < (size_t)nbHospitals; i++) { + Graph g(hospitals[i].cap); + // First add all positions that must be filled. + for(int position: doctorsMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(size_t ind = 0; ind < doctors[position].preferences.size(); ++ind) { + if ((doctors[position].preferences[ind] - 1) == (int)i) { + isAcceptable = true; + break; + } + } + if (isAcceptable) { + continue; + } + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, 1); + for(size_t ind = 0; ind < doctors[position].preferences.size(); ++ind) { + int candidate = doctors[position].preferences[ind] - 1; + auto cand_vert = std::make_pair(0, candidate); + if (!g.containsVertex(cand_vert)) { + g.addVertex(cand_vert, hospitals[candidate].cap); + } + g.addEdge(pos_vert, cand_vert); + } + while (g.augment()) { } // Empty loop to keep augmenting while we can + } + for(size_t rank = 0; rank < hospitals[i].preferences.size(); rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == hospitals[i].preferences.size()- 1) && (hospitals[i].mustBeAllocated || !supp)) { + continue; + } + for(size_t ind = 0; ind < hospitals[i].preferences[rank].size(); ind++) { + int position = hospitals[i].preferences[rank][ind] - 1; + auto pos_vert = std::make_pair(1, position); + g.addVertex(pos_vert, 1); + for(size_t k = 0; k < doctors[position].preferences.size(); k++) { + int hosp_cand = doctors[position].preferences[k] - 1; + if (hosp_cand == (int)i) { // Don't add the current candidate to the graph + break; + } + std::pair hosp_cand_vert = std::make_pair(0, hosp_cand); + if (! g.containsVertex(hosp_cand_vert)) { + g.addVertex(hosp_cand_vert, hospitals[hosp_cand].cap); + } + g.addEdge(pos_vert, hosp_cand_vert); + } + } + // max_flow is <= min(g.cap_left(), g.cap_right()), so we can do simple + // checks which might mean we can not bother trying to augment + bool can_def_preprocess = hospitals[i].cap + 2*g.cap_left() <= g.cap_total(); + if (hospitals[i].cap + g.cap_left() + g.cap_right() <= g.cap_total()) { + can_def_preprocess = true; + } + if (!can_def_preprocess) { + while (g.augment()) { + // Empty loop on purpose, we keep augmenting while we can keep + // augmenting. + } + } + if (can_def_preprocess || g.can_preprocess()) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !hospitals[i].mustBeAllocated) { + hospitalsMustBeAllocated.push_back(i); + hospitals[i].mustBeAllocated = true; + } +#ifdef DEBUG + if (i == 0) { + //std::cout << "g.cap_original() = " << hospitals[i].cap << ", g.cap_left() = " << g.cap_left(); + //std::cout << ", cap_total = " << g.cap_total() << ", g.maxFlow() = " << g.maxFlow() << std::endl; + //g.printGraph(); + //g.printMatching(); + } + std::cout << "hospital worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < hospitals[i].nbPref; k++) { + nbTotRem += hospitals[i].preferences[k].size(); +#ifdef DEBUG + remHere += hospitals[i].preferences[k].size(); +#endif /* DEBUG */ + hospitals[i].nbTotPref -= hospitals[i].preferences[k].size(); + for (unsigned int l = 0; l < hospitals[i].preferences[k].size(); l++) { + int idxDoc = hospitals[i].preferences[k][l] - 1; + for(size_t n=0; n < doctors[idxDoc].preferences.size();n++){ + if(doctors[idxDoc].preferences[n]-1 == (int)i){ + doctors[idxDoc].preferences.erase(doctors[idxDoc].preferences.begin() + n); + doctors[idxDoc].ranks.erase(doctors[idxDoc].ranks.begin() + n); + doctors[idxDoc].nbPref--; + nbTotRem++; + } + } + } + } + hospitals[i].nbPref = rank + 1; + hospitals[i].preferences.resize(hospitals[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + void Allocation::polish(){ // Remove unused groups for(int j=0; j MAXTIME) { + cout << "Time elapsed, breaking"; + break; + } + }while(this_time != 0); + } polish(); } @@ -307,7 +739,7 @@ void Allocation::printSol(){ cout << "Allocation by hospitals" << endl; for(int i=0; i 1){ cout << "Allocation error: doctor " << assignmentByHospital[i][j] << " is allocated " << doctorAllocated[assignmentByHospital[i][j] - 1] << " times " << endl; diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp new file mode 100644 index 0000000..66f7de0 --- /dev/null +++ b/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp @@ -0,0 +1,199 @@ +#include +#include +#include "Graph.h" + + +Graph::Graph(int cap_original) : _cap_original(cap_original), _cap_total(0), + _left_total(0), max_flow(0) { +#ifdef DEBUG_GRAPH + std::cout << "New graph" << std::endl; +#endif /* DEBUG_GRAPH */ + this->addVertex(std::make_pair(2, 0), 1); // SOURCE + this->addVertex(std::make_pair(2, 1), 1); // SINK +} + +void Graph::addVertex(Vertex name, int capacity) { + int index = size(); + this->_names[name] = index; + this->_indices[index] = name; +#ifdef DEBUG_GRAPH + std::cout << "Add vertex " << name << " with cap " << capacity << std::endl; +#endif /* DEBUG_GRAPH */ + this->_adjacents[index] = std::map(); + if (name.first != 2) { + Edge e1, e2; + _cap_total += capacity; + if (name.first == 0) { // left side + e1.id = index; + e1.flow = 0; + e1.cap = capacity; + e2.id = Graph::SOURCE; + e2.flow = 0; + e2.cap = capacity; + _left_total += capacity; + } else if (name.first == 1) { // right side + e1.id = index; + e1.flow = 0; + e1.cap = capacity; + e2.id = Graph::SINK; + e2.flow = 0; + e2.cap = capacity; + } + this->_adjacents[e1.id][e2.id] = e2; + this->_adjacents[e2.id][e1.id] = e1; + } +} + +Vertex Graph::name(int vert_index) { + return this->_indices[vert_index]; +} + +bool Graph::containsVertex(Vertex name) const { + return _names.find(name) != _names.end(); +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +void Graph::addEdge(Vertex v1, Vertex v2) { + int i1 = this->_names[v1]; + int i2 = this->_names[v2]; + Edge e1, e2; + e1.id = i1; + e1.cap = std::numeric_limits::max(); + e1.flow = 0; + e2.id = i2; + e2.cap = std::numeric_limits::max(); + e2.flow = 0; + _adjacents[i1][i2] = e2; + _adjacents[i2][i1] = e1; +} + +int Graph::size() const { + return _names.size(); +} + +int Graph::maxFlow() const { + return max_flow; +} + +bool Graph::can_preprocess() { + return _cap_original + _left_total <= _cap_total - max_flow; +} + +int Graph::cap_left() const { + return _left_total; +} + +int Graph::cap_right() const { + return _cap_total - _left_total; +} + +int Graph::cap_total() const { + return _cap_total; +} + +/** + * Augment the flow. + */ +bool Graph::augment() { +#ifdef DEBUG_GRAPH + std::cout << "Augmenting" << std::endl; + this->printGraph(); +#endif /* DEBUG_GRAPH */ + std::list path; + std::vector visited(size(), false); + visited[Graph::SOURCE] = true; + path.push_back(Graph::SOURCE); + return internal_augment(Graph::SOURCE, visited, path); +} + +#ifdef DEBUG_GRAPH +void Graph::printGraph() { + for(auto & tuple : _adjacents) { + int ind = tuple.first; + std::cout << _indices[ind] << ":"; + for(auto & inner_tuple: tuple.second) { + const Edge & adj = inner_tuple.second; + std::cout << " " << _indices[adj.id] << "{" << adj.flow << "/" << adj.cap << "}"; + } + std::cout << std::endl; + } +} + +#endif /* DEBUG_GRAPH */ + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(auto & tuple: _adjacents[now]) { + Edge & next_edge = tuple.second; + if (visited[next_edge.id]) { + continue; + } + // Can't add any more flow to this edge. + if (next_edge.flow >= next_edge.cap) { + continue; + } + //std::cout << "Considering " << _indices[next_edge.id] << " which has " << next_edge.flow << "/" << next_edge.cap << std::endl; + if (next_edge.id == Graph::SINK) { + // Found an augmenting flow. Modify flows used. +#ifdef DEBUG_GRAPH + std::cout << "New flow found." << std::endl; +#endif /* DEBUG_GRAPH */ + path.push_back(next_edge.id); + int start = Graph::SOURCE; + int total_flow = std::numeric_limits::max(); +#ifdef DEBUG_GRAPH + std::cout << "Path is "; +#endif /* DEBUG_GRAPH */ + for(auto p: path) { + if (p != Graph::SOURCE) { + int new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + if (_adjacents[start][p].flow < 0 && _adjacents[start][p].cap == std::numeric_limits::max()) { + new_flow = std::numeric_limits::max(); + } + total_flow = std::min(total_flow, new_flow); + } +#ifdef DEBUG_GRAPH + if (p != Graph::SOURCE) { + int new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + if (_adjacents[start][p].flow < 0 && _adjacents[start][p].cap == std::numeric_limits::max()) { + new_flow = std::numeric_limits::max(); + } + std::cout << "f" << new_flow; + } + std::cout << " " << _indices.at(p); +#endif /* DEBUG_GRAPH */ + start = p; + } +#ifdef DEBUG_GRAPH + std::cout << " with flow " << total_flow << std::endl; +#endif /* DEBUG_GRAPH */ + start = Graph::SOURCE; + while(!path.empty()) { + int next = path.front(); + path.pop_front(); + if (next == Graph::SOURCE) { + continue; + } + _adjacents[start][next].flow += total_flow; + _adjacents[next][start].flow -= total_flow; + start = next; + } + max_flow += total_flow; + return true; + } + path.push_back(next_edge.id); + visited[next_edge.id] = true; + if (internal_augment(next_edge.id, visited, path)) { + return true; + } + path.pop_back(); + } + return false; +} + diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Graph.h b/HRT/8_YESBIN_3STA_NOMERGED/Graph.h new file mode 100644 index 0000000..9bc494a --- /dev/null +++ b/HRT/8_YESBIN_3STA_NOMERGED/Graph.h @@ -0,0 +1,82 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG_GRAPH +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG_GRAPH */ + +struct Edge { + int id; + int cap; + int flow; +}; + +typedef std::pair Vertex; + +class Graph { + public: + Graph(int cap_right); + void addVertex(Vertex name, int capacity); + bool containsVertex(Vertex name) const; + void addEdge(Vertex v1, Vertex v2); + const std::list adjacent(Vertex vertex) const; + int matched(Vertex vertex) const; + bool augment(); + + bool can_preprocess(); + + int size() const; + int maxFlow() const; + + int cap_total() const; + int cap_left() const; + int cap_right() const; + + Vertex name(int vert_index); + + constexpr static int SOURCE = 0; + constexpr static int SINK = 1; + +#ifdef DEBUG_GRAPH + void printGraph(); +#endif /* DEBUG_GRAPH */ + + private: + int _cap_original; + int _cap_total; + int _left_total; + int max_flow; + std::unordered_map _names; + std::unordered_map _indices; + // Each adjacent is a triple containing (other_vertex, capacity, + // current_flow) + std::map> _adjacents; + + Edge & getEdge(int a, int b) { return _adjacents[a][b]; } + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index b5014fa..ad2a43d 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -11,23 +11,25 @@ int main(int argc, char **argv){ string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); // functions allo.load(path,filein); allo.printProb(); + allo.pp_mode = mode; - manlove(allo); + manlove(allo, mode); allo.printSol(); allo.checkSolution(); allo.printInfo(pathAndFileout); } -int manlove(Allocation& allo){ +int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); - allo.reduction(); + allo.reduction(mode); allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; @@ -141,7 +143,7 @@ int manlove(Allocation& allo){ } // Setting of Gurobi - model.getEnv().set(GRB_DoubleParam_TimeLimit, 3600 - (getCPUTime() - initTimeModelCPU)); + model.getEnv().set(GRB_DoubleParam_TimeLimit, MAXTIME - (getCPUTime() - initTimeModelCPU)); model.getEnv().set(GRB_IntParam_Threads, 1); model.getEnv().set(GRB_DoubleParam_MIPGap, 0); @@ -207,9 +209,9 @@ int manlove(Allocation& allo){ cout << "Error code = " << e.getErrorCode() << endl; cout << e.getMessage() << endl; } - catch (...) { - cout << "Exception during optimization" << endl; - } +// catch (...) { +// cout << "Exception during optimization" << endl; +// } // End diff --git a/HRT/8_YESBIN_3STA_NOMERGED/makefile b/HRT/8_YESBIN_3STA_NOMERGED/makefile index 8540bcd..12ac583 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/makefile +++ b/HRT/8_YESBIN_3STA_NOMERGED/makefile @@ -8,15 +8,15 @@ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 CC = g++ -CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++17 DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD -OBJECTS = main.o Allocation.o time.o +OBJECTS = main.o Allocation.o time.o Graph.o AgentIterator.o exec : $(OBJECTS) $(CC) $(CFLAGS) -o YESBIN_3STA_NOMERGED $(OBJECTS) $(GUROBI_OPTS) -.cpp.o : - $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ +.cpp.o : $< Allocation.h Graph.h + $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ clean : rm -f $(OBJECTS) YESBIN_3STA_NOMERGED \ No newline at end of file From ce0ce7b8bd1b4789d975a006d1b4d61a51c6629e Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 10 Apr 2019 09:30:03 +0100 Subject: [PATCH 20/48] Rest of preprocessing fixes --- HRT/8_YESBIN_3STA_NOMERGED/Allocation.h | 22 ++++++++++++++++++++-- HRT/8_YESBIN_3STA_NOMERGED/main.h | 2 +- HRT/8_YESBIN_3STA_NOMERGED/time.h | 3 +++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h index 581cf1c..392a1f7 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h @@ -4,6 +4,7 @@ using namespace std; #include #include +#include #include #include #include @@ -24,8 +25,11 @@ int nbPref; vector preferences; vector ranks; + bool mustBeAllocated; void print(); + + Doctor() : mustBeAllocated(true) { } }; /* ************************************************************************************* @@ -38,9 +42,12 @@ int cap; int nbPref; int nbTotPref; + bool mustBeAllocated; vector > preferences; - + void print(); + + Hospital() : mustBeAllocated(true) { } }; /* ************************************************************************************* @@ -74,9 +81,16 @@ int nbDoctors; int nbHospitals; + + int total_removed; + int pp_mode; + vector doctors; vector hospitals; + std::list doctorsMustBeAllocated; + std::list hospitalsMustBeAllocated; + // Given by the ILP model vector assignmentByDoctor; vector > assignmentByHospital; @@ -87,7 +101,11 @@ int reductionHosOff(); int reductionResApp(); void polish(); - void reduction(); + void reduction(int mode); + int reductionMineDoctors(int mode); + int reductionMineHospitals(int mode); + int reductionExactHospital(bool supp); + int reductionExactDoctor(bool supp); void printSol(); void printInfo(const string& pathAndFileout); void checkSolution(); diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.h b/HRT/8_YESBIN_3STA_NOMERGED/main.h index 56e7b5d..01d0055 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.h @@ -11,6 +11,6 @@ float EPSILON = 0.001; - int manlove(Allocation& allo); + int manlove(Allocation& allo, int reduction_mode); #endif diff --git a/HRT/8_YESBIN_3STA_NOMERGED/time.h b/HRT/8_YESBIN_3STA_NOMERGED/time.h index 6f1cb4f..bbac2cd 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/time.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/time.h @@ -12,4 +12,7 @@ double getWallTime(); double getCPUTime(); +static const int MAXTIME = 3600; + + #endif From 3beefe9a187735d14486d04853ba078ab40df12a Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 2 May 2019 15:01:41 +0100 Subject: [PATCH 21/48] Tweaks to Graph structure --- .../8_YESBIN_2STA_YESMERGED/Allocation.cpp | 84 +++++++------- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp | 109 ++++++------------ SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h | 24 ++-- 3 files changed, 90 insertions(+), 127 deletions(-) diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index a06f132..17e40e2 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -181,39 +181,8 @@ int Allocation::reductionExact(bool children_side, bool supp) { for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) - Graph> g; + Graph g; int n_1 = 0; - // First add all positions that must be filled. - for(int position: otherMustBeAllocated) { - // If position is acceptable to i, then skip it. - bool isAcceptable = false; - for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - if (other[position].preferences[otherRank][ind] == i) { - isAcceptable = true; - break; - } - } - } - if (isAcceptable) { - continue; - } - - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); - for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - int candidate = other[position].preferences[otherRank][ind]; - auto cand_vert = std::make_pair(0, candidate); - if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); - n_1 += 1; - } - g.addEdge(pos_vert, cand_vert); - } - } - g.augment(pos_vert); - } for(int rank = 0; rank < these[i].nbPref; rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care @@ -222,8 +191,7 @@ int Allocation::reductionExact(bool children_side, bool supp) { } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(1, position); int idxRank = these[i].ranks[rank][ind]; for(int l = 0; l <= idxRank; l++) { for(size_t k = 0; k < other[position].preferences[l].size(); k++) { @@ -231,12 +199,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (other_cand == i) { // Don't add the current candidate to the graph continue; } - std::pair other_cand_vert = std::make_pair(0, other_cand); - if (! g.containsVertex(other_cand_vert)) { - g.addVertex(other_cand_vert, true); + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); n_1 += 1; } - g.addEdge(pos_vert, other_cand_vert); + g.addEdge(position, other_cand); } } } @@ -247,10 +214,47 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (! matching_cant_exist) { for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.augment(pos_vert); + g.augment(position); } } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! // Firstly, they must be allocated, so mark as such (if we're in that diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp index 3206f4a..3bcccb0 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp @@ -2,112 +2,72 @@ #include "Graph.h" - -template -Graph::Graph() { +// Expected biggest graph, to save on allocations +const size_t expected_size = 2048; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); #ifdef DEBUG std::cout << "New graph" << std::endl; #endif /* DEBUG */ } -template -void Graph::addVertex(t_name name, bool open) { - int index = size(); - this->_names[name] = index; - this->_indices[index] = name; -#ifdef DEBUG - std::cout << "Add vertex " << name << std::endl; -#endif /* DEBUG */ - this->_adjacents.emplace_back(); -} - -template -t_name Graph::name(int vert_index) { - return this->_indices[vert_index]; +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; } -template -bool Graph::containsVertex(t_name name) const { - return _names.find(name) != _names.end(); +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; } /** * Adds an edge to the graph. Note that this edge must always be added in the * form (right, left) for things to work. */ -template -void Graph::addEdge(t_name v1, t_name v2) { - int i1 = this->_names[v1]; - int i2 = this->_names[v2]; - _adjacents[i1].push_back(i2); - _adjacents[i2].push_back(i1); +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); } -template -int Graph::size() const { - return _names.size(); +int Graph::size() const { + return _size; } -template -int Graph::matchingSize() const { - // for a matched edge (a,b), our _matching map stores both _matching[a] = b - // and _matching[b] = a. - return _matching.size() / 2; +int Graph::matchingSize() const { + return _matching_size; } /** * Augment the matching, starting at vertex name which is on the right. */ -template -void Graph::augment(t_name name) { - int start = this->_names[name]; +void Graph::augment(int name) { #ifdef DEBUG std::cout << "Augmenting on " << _indices.at(start) << std::endl; this->printGraph(); #endif /* DEBUG */ std::list path; - std::vector visited(size(), false); - path.push_back(start); - internal_augment(start, visited, path); + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); } -#ifdef DEBUG -template -void Graph::printGraph() { - for(size_t ind = 0; ind < _adjacents.size(); ++ind) { - std::cout << _indices[ind] << ":"; - for(auto adj: _adjacents[ind]) { - std::cout << " " << _indices[adj]; - } - std::cout << std::endl; - } -} - -template -void Graph::printMatching() const { - for(auto p: _matching) { - int a = p.first; - int b = p.second; - if (a <= b) { - std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; - } - } -} - -#endif /* DEBUG */ - /** * Continues an augmentation, on vertex now, which is on the right. */ -template -bool Graph::internal_augment(int now, std::vector & visited, +bool Graph::internal_augment(int now, std::vector & visited, std::list & path) { - for(int next: _adjacents[now]) { + for(int next: _adjacents[1][now]) { + // next is on the left if (visited[next]) { continue; } - auto matched = _matching.find(next); - if (matched == _matching.end()) { + if (_matching[0][next] == -1) { // Found an augmenting path. Switch edges and return true. #ifdef DEBUG std::cout << "New matching found." << std::endl; @@ -126,13 +86,13 @@ bool Graph::internal_augment(int now, std::vector & visited, path.pop_front(); int left = path.front(); path.pop_front(); - _matching[right] = left; - _matching[left] = right; + _matching[1][right] = left; + _matching[0][left] = right; } - + _matching_size += 1; return true; } - int next2 = matched->second; + int next2 = _matching[0][next]; path.push_back(next); path.push_back(next2); visited[next] = true; @@ -145,4 +105,3 @@ bool Graph::internal_augment(int now, std::vector & visited, return false; } -template class Graph>; diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h index cdbbec7..5d07f00 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.h @@ -27,21 +27,19 @@ inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { #endif /* DEBUG */ -template class Graph { public: Graph(); - void addVertex(t_name name, bool open=false); - bool containsVertex(t_name name) const; - void addEdge(t_name v1, t_name v2); - const std::list adjacent(t_name vertex) const; - int matched(t_name vertex) const; - void augment(t_name vertex); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); int size() const; int matchingSize() const; - t_name name(int vert_index); + int name(int vert_index); #ifdef DEBUG void printGraph(); @@ -49,10 +47,12 @@ class Graph { #endif /* DEBUG */ private: - std::unordered_map _names; - std::unordered_map _indices; - std::vector> _adjacents; - std::unordered_map _matching; + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; bool internal_augment(int now, std::vector & visited, std::list & path); }; From 425f136e061090350d0223ef7098899fef247783 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 2 May 2019 15:02:33 +0100 Subject: [PATCH 22/48] Tweaks to Graph --- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 84 +++++++------- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp | 109 ++++++------------ SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h | 24 ++-- 3 files changed, 90 insertions(+), 127 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index a06f132..17e40e2 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -181,39 +181,8 @@ int Allocation::reductionExact(bool children_side, bool supp) { for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) - Graph> g; + Graph g; int n_1 = 0; - // First add all positions that must be filled. - for(int position: otherMustBeAllocated) { - // If position is acceptable to i, then skip it. - bool isAcceptable = false; - for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - if (other[position].preferences[otherRank][ind] == i) { - isAcceptable = true; - break; - } - } - } - if (isAcceptable) { - continue; - } - - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); - for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - int candidate = other[position].preferences[otherRank][ind]; - auto cand_vert = std::make_pair(0, candidate); - if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); - n_1 += 1; - } - g.addEdge(pos_vert, cand_vert); - } - } - g.augment(pos_vert); - } for(int rank = 0; rank < these[i].nbPref; rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care @@ -222,8 +191,7 @@ int Allocation::reductionExact(bool children_side, bool supp) { } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(1, position); int idxRank = these[i].ranks[rank][ind]; for(int l = 0; l <= idxRank; l++) { for(size_t k = 0; k < other[position].preferences[l].size(); k++) { @@ -231,12 +199,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (other_cand == i) { // Don't add the current candidate to the graph continue; } - std::pair other_cand_vert = std::make_pair(0, other_cand); - if (! g.containsVertex(other_cand_vert)) { - g.addVertex(other_cand_vert, true); + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); n_1 += 1; } - g.addEdge(pos_vert, other_cand_vert); + g.addEdge(position, other_cand); } } } @@ -247,10 +214,47 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (! matching_cant_exist) { for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.augment(pos_vert); + g.augment(position); } } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! // Firstly, they must be allocated, so mark as such (if we're in that diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp index 3206f4a..3bcccb0 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -2,112 +2,72 @@ #include "Graph.h" - -template -Graph::Graph() { +// Expected biggest graph, to save on allocations +const size_t expected_size = 2048; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); #ifdef DEBUG std::cout << "New graph" << std::endl; #endif /* DEBUG */ } -template -void Graph::addVertex(t_name name, bool open) { - int index = size(); - this->_names[name] = index; - this->_indices[index] = name; -#ifdef DEBUG - std::cout << "Add vertex " << name << std::endl; -#endif /* DEBUG */ - this->_adjacents.emplace_back(); -} - -template -t_name Graph::name(int vert_index) { - return this->_indices[vert_index]; +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; } -template -bool Graph::containsVertex(t_name name) const { - return _names.find(name) != _names.end(); +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; } /** * Adds an edge to the graph. Note that this edge must always be added in the * form (right, left) for things to work. */ -template -void Graph::addEdge(t_name v1, t_name v2) { - int i1 = this->_names[v1]; - int i2 = this->_names[v2]; - _adjacents[i1].push_back(i2); - _adjacents[i2].push_back(i1); +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); } -template -int Graph::size() const { - return _names.size(); +int Graph::size() const { + return _size; } -template -int Graph::matchingSize() const { - // for a matched edge (a,b), our _matching map stores both _matching[a] = b - // and _matching[b] = a. - return _matching.size() / 2; +int Graph::matchingSize() const { + return _matching_size; } /** * Augment the matching, starting at vertex name which is on the right. */ -template -void Graph::augment(t_name name) { - int start = this->_names[name]; +void Graph::augment(int name) { #ifdef DEBUG std::cout << "Augmenting on " << _indices.at(start) << std::endl; this->printGraph(); #endif /* DEBUG */ std::list path; - std::vector visited(size(), false); - path.push_back(start); - internal_augment(start, visited, path); + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); } -#ifdef DEBUG -template -void Graph::printGraph() { - for(size_t ind = 0; ind < _adjacents.size(); ++ind) { - std::cout << _indices[ind] << ":"; - for(auto adj: _adjacents[ind]) { - std::cout << " " << _indices[adj]; - } - std::cout << std::endl; - } -} - -template -void Graph::printMatching() const { - for(auto p: _matching) { - int a = p.first; - int b = p.second; - if (a <= b) { - std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; - } - } -} - -#endif /* DEBUG */ - /** * Continues an augmentation, on vertex now, which is on the right. */ -template -bool Graph::internal_augment(int now, std::vector & visited, +bool Graph::internal_augment(int now, std::vector & visited, std::list & path) { - for(int next: _adjacents[now]) { + for(int next: _adjacents[1][now]) { + // next is on the left if (visited[next]) { continue; } - auto matched = _matching.find(next); - if (matched == _matching.end()) { + if (_matching[0][next] == -1) { // Found an augmenting path. Switch edges and return true. #ifdef DEBUG std::cout << "New matching found." << std::endl; @@ -126,13 +86,13 @@ bool Graph::internal_augment(int now, std::vector & visited, path.pop_front(); int left = path.front(); path.pop_front(); - _matching[right] = left; - _matching[left] = right; + _matching[1][right] = left; + _matching[0][left] = right; } - + _matching_size += 1; return true; } - int next2 = matched->second; + int next2 = _matching[0][next]; path.push_back(next); path.push_back(next2); visited[next] = true; @@ -145,4 +105,3 @@ bool Graph::internal_augment(int now, std::vector & visited, return false; } -template class Graph>; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h index cdbbec7..5d07f00 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.h @@ -27,21 +27,19 @@ inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { #endif /* DEBUG */ -template class Graph { public: Graph(); - void addVertex(t_name name, bool open=false); - bool containsVertex(t_name name) const; - void addEdge(t_name v1, t_name v2); - const std::list adjacent(t_name vertex) const; - int matched(t_name vertex) const; - void augment(t_name vertex); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); int size() const; int matchingSize() const; - t_name name(int vert_index); + int name(int vert_index); #ifdef DEBUG void printGraph(); @@ -49,10 +47,12 @@ class Graph { #endif /* DEBUG */ private: - std::unordered_map _names; - std::unordered_map _indices; - std::vector> _adjacents; - std::unordered_map _matching; + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; bool internal_augment(int now, std::vector & visited, std::list & path); }; From 4f7cbff00eba74ead3dfd818a8b63d9c838adb79 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 2 May 2019 15:03:08 +0100 Subject: [PATCH 23/48] Tweaks to Graph --- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 84 ++++++++------- SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp | 109 ++++++-------------- SMTI/4_YESBIN_1STA_YESMERGED/Graph.h | 24 ++--- 3 files changed, 90 insertions(+), 127 deletions(-) diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 7b3b0f0..e416a58 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -255,39 +255,8 @@ int Allocation::reductionExact(bool children_side, bool supp) { for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) - Graph> g; + Graph g; int n_1 = 0; - // First add all positions that must be filled. - for(int position: otherMustBeAllocated) { - // If position is acceptable to i, then skip it. - bool isAcceptable = false; - for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - if (other[position].preferences[otherRank][ind] == i) { - isAcceptable = true; - break; - } - } - } - if (isAcceptable) { - continue; - } - - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); - for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - int candidate = other[position].preferences[otherRank][ind]; - auto cand_vert = std::make_pair(0, candidate); - if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); - n_1 += 1; - } - g.addEdge(pos_vert, cand_vert); - } - } - g.augment(pos_vert); - } for(int rank = 0; rank < these[i].nbPref; rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care @@ -296,8 +265,7 @@ int Allocation::reductionExact(bool children_side, bool supp) { } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(1, position); int idxRank = these[i].ranks[rank][ind]; for(int l = 0; l <= idxRank; l++) { for(size_t k = 0; k < other[position].preferences[l].size(); k++) { @@ -305,12 +273,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (other_cand == i) { // Don't add the current candidate to the graph continue; } - std::pair other_cand_vert = std::make_pair(0, other_cand); - if (! g.containsVertex(other_cand_vert)) { - g.addVertex(other_cand_vert, true); + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); n_1 += 1; } - g.addEdge(pos_vert, other_cand_vert); + g.addEdge(position, other_cand); } } } @@ -321,10 +288,47 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (! matching_cant_exist) { for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.augment(pos_vert); + g.augment(position); } } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! // Firstly, they must be allocated, so mark as such (if we're in that diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp index 3206f4a..3bcccb0 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -2,112 +2,72 @@ #include "Graph.h" - -template -Graph::Graph() { +// Expected biggest graph, to save on allocations +const size_t expected_size = 2048; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); #ifdef DEBUG std::cout << "New graph" << std::endl; #endif /* DEBUG */ } -template -void Graph::addVertex(t_name name, bool open) { - int index = size(); - this->_names[name] = index; - this->_indices[index] = name; -#ifdef DEBUG - std::cout << "Add vertex " << name << std::endl; -#endif /* DEBUG */ - this->_adjacents.emplace_back(); -} - -template -t_name Graph::name(int vert_index) { - return this->_indices[vert_index]; +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; } -template -bool Graph::containsVertex(t_name name) const { - return _names.find(name) != _names.end(); +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; } /** * Adds an edge to the graph. Note that this edge must always be added in the * form (right, left) for things to work. */ -template -void Graph::addEdge(t_name v1, t_name v2) { - int i1 = this->_names[v1]; - int i2 = this->_names[v2]; - _adjacents[i1].push_back(i2); - _adjacents[i2].push_back(i1); +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); } -template -int Graph::size() const { - return _names.size(); +int Graph::size() const { + return _size; } -template -int Graph::matchingSize() const { - // for a matched edge (a,b), our _matching map stores both _matching[a] = b - // and _matching[b] = a. - return _matching.size() / 2; +int Graph::matchingSize() const { + return _matching_size; } /** * Augment the matching, starting at vertex name which is on the right. */ -template -void Graph::augment(t_name name) { - int start = this->_names[name]; +void Graph::augment(int name) { #ifdef DEBUG std::cout << "Augmenting on " << _indices.at(start) << std::endl; this->printGraph(); #endif /* DEBUG */ std::list path; - std::vector visited(size(), false); - path.push_back(start); - internal_augment(start, visited, path); + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); } -#ifdef DEBUG -template -void Graph::printGraph() { - for(size_t ind = 0; ind < _adjacents.size(); ++ind) { - std::cout << _indices[ind] << ":"; - for(auto adj: _adjacents[ind]) { - std::cout << " " << _indices[adj]; - } - std::cout << std::endl; - } -} - -template -void Graph::printMatching() const { - for(auto p: _matching) { - int a = p.first; - int b = p.second; - if (a <= b) { - std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; - } - } -} - -#endif /* DEBUG */ - /** * Continues an augmentation, on vertex now, which is on the right. */ -template -bool Graph::internal_augment(int now, std::vector & visited, +bool Graph::internal_augment(int now, std::vector & visited, std::list & path) { - for(int next: _adjacents[now]) { + for(int next: _adjacents[1][now]) { + // next is on the left if (visited[next]) { continue; } - auto matched = _matching.find(next); - if (matched == _matching.end()) { + if (_matching[0][next] == -1) { // Found an augmenting path. Switch edges and return true. #ifdef DEBUG std::cout << "New matching found." << std::endl; @@ -126,13 +86,13 @@ bool Graph::internal_augment(int now, std::vector & visited, path.pop_front(); int left = path.front(); path.pop_front(); - _matching[right] = left; - _matching[left] = right; + _matching[1][right] = left; + _matching[0][left] = right; } - + _matching_size += 1; return true; } - int next2 = matched->second; + int next2 = _matching[0][next]; path.push_back(next); path.push_back(next2); visited[next] = true; @@ -145,4 +105,3 @@ bool Graph::internal_augment(int now, std::vector & visited, return false; } -template class Graph>; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h index cdbbec7..5d07f00 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.h @@ -27,21 +27,19 @@ inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { #endif /* DEBUG */ -template class Graph { public: Graph(); - void addVertex(t_name name, bool open=false); - bool containsVertex(t_name name) const; - void addEdge(t_name v1, t_name v2); - const std::list adjacent(t_name vertex) const; - int matched(t_name vertex) const; - void augment(t_name vertex); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); int size() const; int matchingSize() const; - t_name name(int vert_index); + int name(int vert_index); #ifdef DEBUG void printGraph(); @@ -49,10 +47,12 @@ class Graph { #endif /* DEBUG */ private: - std::unordered_map _names; - std::unordered_map _indices; - std::vector> _adjacents; - std::unordered_map _matching; + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; bool internal_augment(int now, std::vector & visited, std::list & path); }; From b62c8064a5e72de2788aa462226fa71c7b64d7f5 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 2 May 2019 15:03:36 +0100 Subject: [PATCH 24/48] Tweaks to Graph --- SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 84 ++++++++------- SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp | 109 ++++++-------------- SMTI/8_YESBIN_2STA_YESMERGED/Graph.h | 24 ++--- 3 files changed, 90 insertions(+), 127 deletions(-) diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp index d1b1c3b..2687110 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -255,39 +255,8 @@ int Allocation::reductionExact(bool children_side, bool supp) { for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) - Graph> g; + Graph g; int n_1 = 0; - // First add all positions that must be filled. - for(int position: otherMustBeAllocated) { - // If position is acceptable to i, then skip it. - bool isAcceptable = false; - for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - if (other[position].preferences[otherRank][ind] == i) { - isAcceptable = true; - break; - } - } - } - if (isAcceptable) { - continue; - } - - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); - for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - int candidate = other[position].preferences[otherRank][ind]; - auto cand_vert = std::make_pair(0, candidate); - if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); - n_1 += 1; - } - g.addEdge(pos_vert, cand_vert); - } - } - g.augment(pos_vert); - } for(int rank = 0; rank < these[i].nbPref; rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care @@ -296,8 +265,7 @@ int Allocation::reductionExact(bool children_side, bool supp) { } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(1, position); int idxRank = these[i].ranks[rank][ind]; for(int l = 0; l <= idxRank; l++) { for(size_t k = 0; k < other[position].preferences[l].size(); k++) { @@ -305,12 +273,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (other_cand == i) { // Don't add the current candidate to the graph continue; } - std::pair other_cand_vert = std::make_pair(0, other_cand); - if (! g.containsVertex(other_cand_vert)) { - g.addVertex(other_cand_vert, true); + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); n_1 += 1; } - g.addEdge(pos_vert, other_cand_vert); + g.addEdge(position, other_cand); } } } @@ -321,10 +288,47 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (! matching_cant_exist) { for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.augment(pos_vert); + g.augment(position); } } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! // Firstly, they must be allocated, so mark as such (if we're in that diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp index 3206f4a..3bcccb0 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.cpp @@ -2,112 +2,72 @@ #include "Graph.h" - -template -Graph::Graph() { +// Expected biggest graph, to save on allocations +const size_t expected_size = 2048; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); #ifdef DEBUG std::cout << "New graph" << std::endl; #endif /* DEBUG */ } -template -void Graph::addVertex(t_name name, bool open) { - int index = size(); - this->_names[name] = index; - this->_indices[index] = name; -#ifdef DEBUG - std::cout << "Add vertex " << name << std::endl; -#endif /* DEBUG */ - this->_adjacents.emplace_back(); -} - -template -t_name Graph::name(int vert_index) { - return this->_indices[vert_index]; +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; } -template -bool Graph::containsVertex(t_name name) const { - return _names.find(name) != _names.end(); +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; } /** * Adds an edge to the graph. Note that this edge must always be added in the * form (right, left) for things to work. */ -template -void Graph::addEdge(t_name v1, t_name v2) { - int i1 = this->_names[v1]; - int i2 = this->_names[v2]; - _adjacents[i1].push_back(i2); - _adjacents[i2].push_back(i1); +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); } -template -int Graph::size() const { - return _names.size(); +int Graph::size() const { + return _size; } -template -int Graph::matchingSize() const { - // for a matched edge (a,b), our _matching map stores both _matching[a] = b - // and _matching[b] = a. - return _matching.size() / 2; +int Graph::matchingSize() const { + return _matching_size; } /** * Augment the matching, starting at vertex name which is on the right. */ -template -void Graph::augment(t_name name) { - int start = this->_names[name]; +void Graph::augment(int name) { #ifdef DEBUG std::cout << "Augmenting on " << _indices.at(start) << std::endl; this->printGraph(); #endif /* DEBUG */ std::list path; - std::vector visited(size(), false); - path.push_back(start); - internal_augment(start, visited, path); + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); } -#ifdef DEBUG -template -void Graph::printGraph() { - for(size_t ind = 0; ind < _adjacents.size(); ++ind) { - std::cout << _indices[ind] << ":"; - for(auto adj: _adjacents[ind]) { - std::cout << " " << _indices[adj]; - } - std::cout << std::endl; - } -} - -template -void Graph::printMatching() const { - for(auto p: _matching) { - int a = p.first; - int b = p.second; - if (a <= b) { - std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; - } - } -} - -#endif /* DEBUG */ - /** * Continues an augmentation, on vertex now, which is on the right. */ -template -bool Graph::internal_augment(int now, std::vector & visited, +bool Graph::internal_augment(int now, std::vector & visited, std::list & path) { - for(int next: _adjacents[now]) { + for(int next: _adjacents[1][now]) { + // next is on the left if (visited[next]) { continue; } - auto matched = _matching.find(next); - if (matched == _matching.end()) { + if (_matching[0][next] == -1) { // Found an augmenting path. Switch edges and return true. #ifdef DEBUG std::cout << "New matching found." << std::endl; @@ -126,13 +86,13 @@ bool Graph::internal_augment(int now, std::vector & visited, path.pop_front(); int left = path.front(); path.pop_front(); - _matching[right] = left; - _matching[left] = right; + _matching[1][right] = left; + _matching[0][left] = right; } - + _matching_size += 1; return true; } - int next2 = matched->second; + int next2 = _matching[0][next]; path.push_back(next); path.push_back(next2); visited[next] = true; @@ -145,4 +105,3 @@ bool Graph::internal_augment(int now, std::vector & visited, return false; } -template class Graph>; diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h index cdbbec7..5d07f00 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h +++ b/SMTI/8_YESBIN_2STA_YESMERGED/Graph.h @@ -27,21 +27,19 @@ inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { #endif /* DEBUG */ -template class Graph { public: Graph(); - void addVertex(t_name name, bool open=false); - bool containsVertex(t_name name) const; - void addEdge(t_name v1, t_name v2); - const std::list adjacent(t_name vertex) const; - int matched(t_name vertex) const; - void augment(t_name vertex); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); int size() const; int matchingSize() const; - t_name name(int vert_index); + int name(int vert_index); #ifdef DEBUG void printGraph(); @@ -49,10 +47,12 @@ class Graph { #endif /* DEBUG */ private: - std::unordered_map _names; - std::unordered_map _indices; - std::vector> _adjacents; - std::unordered_map _matching; + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; bool internal_augment(int now, std::vector & visited, std::list & path); }; From 99725aac5b776e615541c9d24fbb0ce7c4ead41a Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 2 May 2019 17:12:47 +0100 Subject: [PATCH 25/48] Fix SMTI code, make bigger graphs --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp | 2 +- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp | 2 +- SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp | 109 +++++++-------------- SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp | 2 +- 4 files changed, 37 insertions(+), 78 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp index 3bcccb0..028c15d 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -3,7 +3,7 @@ // Expected biggest graph, to save on allocations -const size_t expected_size = 2048; +const size_t expected_size = 4096; Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { _exists[0] = std::vector(expected_size, false); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp index 3bcccb0..028c15d 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Graph.cpp @@ -3,7 +3,7 @@ // Expected biggest graph, to save on allocations -const size_t expected_size = 2048; +const size_t expected_size = 4096; Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { _exists[0] = std::vector(expected_size, false); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp index 3206f4a..6e28936 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp @@ -2,112 +2,72 @@ #include "Graph.h" - -template -Graph::Graph() { +// Expected biggest graph, to save on allocations +const size_t expected_size = 25000; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); #ifdef DEBUG std::cout << "New graph" << std::endl; #endif /* DEBUG */ } -template -void Graph::addVertex(t_name name, bool open) { - int index = size(); - this->_names[name] = index; - this->_indices[index] = name; -#ifdef DEBUG - std::cout << "Add vertex " << name << std::endl; -#endif /* DEBUG */ - this->_adjacents.emplace_back(); -} - -template -t_name Graph::name(int vert_index) { - return this->_indices[vert_index]; +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; } -template -bool Graph::containsVertex(t_name name) const { - return _names.find(name) != _names.end(); +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; } /** * Adds an edge to the graph. Note that this edge must always be added in the * form (right, left) for things to work. */ -template -void Graph::addEdge(t_name v1, t_name v2) { - int i1 = this->_names[v1]; - int i2 = this->_names[v2]; - _adjacents[i1].push_back(i2); - _adjacents[i2].push_back(i1); +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); } -template -int Graph::size() const { - return _names.size(); +int Graph::size() const { + return _size; } -template -int Graph::matchingSize() const { - // for a matched edge (a,b), our _matching map stores both _matching[a] = b - // and _matching[b] = a. - return _matching.size() / 2; +int Graph::matchingSize() const { + return _matching_size; } /** * Augment the matching, starting at vertex name which is on the right. */ -template -void Graph::augment(t_name name) { - int start = this->_names[name]; +void Graph::augment(int name) { #ifdef DEBUG std::cout << "Augmenting on " << _indices.at(start) << std::endl; this->printGraph(); #endif /* DEBUG */ std::list path; - std::vector visited(size(), false); - path.push_back(start); - internal_augment(start, visited, path); + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); } -#ifdef DEBUG -template -void Graph::printGraph() { - for(size_t ind = 0; ind < _adjacents.size(); ++ind) { - std::cout << _indices[ind] << ":"; - for(auto adj: _adjacents[ind]) { - std::cout << " " << _indices[adj]; - } - std::cout << std::endl; - } -} - -template -void Graph::printMatching() const { - for(auto p: _matching) { - int a = p.first; - int b = p.second; - if (a <= b) { - std::cout << _indices.at(a) << " is matched to " << _indices.at(b) << std::endl; - } - } -} - -#endif /* DEBUG */ - /** * Continues an augmentation, on vertex now, which is on the right. */ -template -bool Graph::internal_augment(int now, std::vector & visited, +bool Graph::internal_augment(int now, std::vector & visited, std::list & path) { - for(int next: _adjacents[now]) { + for(int next: _adjacents[1][now]) { + // next is on the left if (visited[next]) { continue; } - auto matched = _matching.find(next); - if (matched == _matching.end()) { + if (_matching[0][next] == -1) { // Found an augmenting path. Switch edges and return true. #ifdef DEBUG std::cout << "New matching found." << std::endl; @@ -126,13 +86,13 @@ bool Graph::internal_augment(int now, std::vector & visited, path.pop_front(); int left = path.front(); path.pop_front(); - _matching[right] = left; - _matching[left] = right; + _matching[1][right] = left; + _matching[0][left] = right; } - + _matching_size += 1; return true; } - int next2 = matched->second; + int next2 = _matching[0][next]; path.push_back(next); path.push_back(next2); visited[next] = true; @@ -145,4 +105,3 @@ bool Graph::internal_augment(int now, std::vector & visited, return false; } -template class Graph>; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp index 3bcccb0..6e28936 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -3,7 +3,7 @@ // Expected biggest graph, to save on allocations -const size_t expected_size = 2048; +const size_t expected_size = 25000; Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { _exists[0] = std::vector(expected_size, false); From 687a90ed1ce28190f8ecb093dd9b41c8fb2fd817 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 31 May 2019 13:43:51 +0100 Subject: [PATCH 26/48] Mode 12 is now no preprocessing --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 12 ++++++++++-- SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp | 4 +++- SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp | 4 +++- SMTI/4_YESBIN_1STA_YESMERGED/main.cpp | 4 +++- SMTI/8_YESBIN_2STA_YESMERGED/main.cpp | 4 +++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index ad2a43d..ebcce90 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -29,8 +29,16 @@ int manlove(Allocation& allo, int mode){ double initTimeModelCPU = getCPUTime(); GRBEnv env = GRBEnv(); - allo.reduction(mode); - allo.printProb(); + if (mode != 12) { + allo.reduction(mode); + } + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; // Model diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp index 4ba6ae9..13f5422 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp @@ -34,7 +34,9 @@ int manlove(Allocation& allo, int mode){ GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(mode); + if (mode != 12) { + allo.reduction(mode); + } //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; if (allo.infos.timeCPUPP > MAXTIME) { diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp index 050cf82..2198669 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/main.cpp @@ -34,7 +34,9 @@ int manlove(Allocation& allo, int mode){ GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(mode); + if (mode != 12) { + allo.reduction(mode); + } //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; if (allo.infos.timeCPUPP > MAXTIME) { diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp index 20faac7..326b41f 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp @@ -33,7 +33,9 @@ int manlove(Allocation& allo, int mode){ GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(mode); + if (mode != 12) { + allo.reduction(mode); + } //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; if (allo.infos.timeCPUPP > MAXTIME) { diff --git a/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp b/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp index 5eadbd9..28e6d30 100644 --- a/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp +++ b/SMTI/8_YESBIN_2STA_YESMERGED/main.cpp @@ -33,7 +33,9 @@ int manlove(Allocation& allo, int mode){ GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(mode); + if (mode != 12) { + allo.reduction(mode); + } //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; if (allo.infos.timeCPUPP > MAXTIME) { From 696b4882250df6d8a819aef60aee10d421b2f45a Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 31 May 2019 13:49:34 +0100 Subject: [PATCH 27/48] Tweaks to graph, missed a model --- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 84 +++++++++++----------- SMTI/3_NOBIN_1STA_YESMERGED/Graph.h | 24 +++---- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index 7b3b0f0..e416a58 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -255,39 +255,8 @@ int Allocation::reductionExact(bool children_side, bool supp) { for (int i = 0; i < number_here; i++) { // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) - Graph> g; + Graph g; int n_1 = 0; - // First add all positions that must be filled. - for(int position: otherMustBeAllocated) { - // If position is acceptable to i, then skip it. - bool isAcceptable = false; - for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - if (other[position].preferences[otherRank][ind] == i) { - isAcceptable = true; - break; - } - } - } - if (isAcceptable) { - continue; - } - - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); - for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { - for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { - int candidate = other[position].preferences[otherRank][ind]; - auto cand_vert = std::make_pair(0, candidate); - if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); - n_1 += 1; - } - g.addEdge(pos_vert, cand_vert); - } - } - g.augment(pos_vert); - } for(int rank = 0; rank < these[i].nbPref; rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care @@ -296,8 +265,7 @@ int Allocation::reductionExact(bool children_side, bool supp) { } for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(1, position); int idxRank = these[i].ranks[rank][ind]; for(int l = 0; l <= idxRank; l++) { for(size_t k = 0; k < other[position].preferences[l].size(); k++) { @@ -305,12 +273,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (other_cand == i) { // Don't add the current candidate to the graph continue; } - std::pair other_cand_vert = std::make_pair(0, other_cand); - if (! g.containsVertex(other_cand_vert)) { - g.addVertex(other_cand_vert, true); + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); n_1 += 1; } - g.addEdge(pos_vert, other_cand_vert); + g.addEdge(position, other_cand); } } } @@ -321,10 +288,47 @@ int Allocation::reductionExact(bool children_side, bool supp) { if (! matching_cant_exist) { for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { int position = these[i].preferences[rank][ind]; - auto pos_vert = std::make_pair(1, position); - g.augment(pos_vert); + g.augment(position); } } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { // preprocess on rank! // Firstly, they must be allocated, so mark as such (if we're in that diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h index cdbbec7..5d07f00 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.h @@ -27,21 +27,19 @@ inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { #endif /* DEBUG */ -template class Graph { public: Graph(); - void addVertex(t_name name, bool open=false); - bool containsVertex(t_name name) const; - void addEdge(t_name v1, t_name v2); - const std::list adjacent(t_name vertex) const; - int matched(t_name vertex) const; - void augment(t_name vertex); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); int size() const; int matchingSize() const; - t_name name(int vert_index); + int name(int vert_index); #ifdef DEBUG void printGraph(); @@ -49,10 +47,12 @@ class Graph { #endif /* DEBUG */ private: - std::unordered_map _names; - std::unordered_map _indices; - std::vector> _adjacents; - std::unordered_map _matching; + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; bool internal_augment(int now, std::vector & visited, std::list & path); }; From 9c025eb7972173a856f440aba033b9898f959f85 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 31 May 2019 13:53:42 +0100 Subject: [PATCH 28/48] Fixes to "preprocess takes too long" code --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index ebcce90..992db9c 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -35,8 +35,10 @@ int manlove(Allocation& allo, int mode){ if (allo.infos.timeCPUPP > MAXTIME) { cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; allo.infos.LB = 0; - allo.assignmentByChild.resize(allo.nbChildren, -1); - allo.assignmentByFamily.resize(allo.nbFamilies,-1); + allo.assignmentByDoctor.resize(allo.nbDoctors, -1); + for(int i = 0; i < allo.nbHospitals; ++i) { + allo.assignmentByHospital[i].resize(allo.hospitals[i].cap, -1); + } return -1; } allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; From 6eedc5a29f016308d037496645131b6e8e8925f7 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 31 May 2019 14:18:45 +0100 Subject: [PATCH 29/48] Add no-preprocess mode --- SMTI/3_NOBIN_1STA_YESMERGED/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp index 8fe372f..9212e7a 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp @@ -34,7 +34,9 @@ int manlove(Allocation& allo, int mode){ GRBEnv env = GRBEnv(); double initTimeModelCPUPP = getCPUTime(); - allo.reduction(mode); + if (mode != 12) { + allo.reduction(mode); + } //allo.printProb(); allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; if (allo.infos.timeCPUPP > MAXTIME) { From cf2bf06fd6f4c3e15d9f435f63bb3606bd8d6ab8 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 1 Jul 2019 11:19:25 +0100 Subject: [PATCH 30/48] Add pp mode for descending improved --- .../4_YESBIN_1STA_YESMERGED/Allocation.cpp | 21 +++++++++++++++---- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- .../8_YESBIN_2STA_YESMERGED/Allocation.cpp | 21 +++++++++++++++---- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h | 2 +- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 21 +++++++++++++++---- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h | 2 +- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 21 +++++++++++++++---- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- 8 files changed, 72 insertions(+), 20 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 17e40e2..3287ae0 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -320,19 +320,22 @@ int Allocation::reductionExact(bool children_side, bool supp) { return nbTotRem; } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; + int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; + comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; + comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -340,8 +343,10 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + vector cand_in(comp, false); + int cand_size = 0; int worst_rank = 0; - unsigned int count = 0; + int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; @@ -356,10 +361,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int l = 0; l <= idxRank; l++) { for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); m++) { - candidates.insert(other[idxFam].preferences[l][m]); + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } } } - if (count >= candidates.size()) { + if (count >= cand_size) { #ifdef DEBUG if (children_side) { std::cout << "child "; @@ -512,6 +522,9 @@ void Allocation::reduction(int mode){ } else if (mode == 10) { num = reductionExact(true, true); num += reductionExact(false, true); + } else if (mode == 13) { + num = reductionMine(false, 0, true); + num += reductionMine(true, 0, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h index 1d1bf0d..3633d9a 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -81,7 +81,7 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); - int reductionMine(bool children_side=true, int mode=0); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 17e40e2..3287ae0 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -320,19 +320,22 @@ int Allocation::reductionExact(bool children_side, bool supp) { return nbTotRem; } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; + int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; + comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; + comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -340,8 +343,10 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + vector cand_in(comp, false); + int cand_size = 0; int worst_rank = 0; - unsigned int count = 0; + int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; @@ -356,10 +361,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int l = 0; l <= idxRank; l++) { for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); m++) { - candidates.insert(other[idxFam].preferences[l][m]); + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } } } - if (count >= candidates.size()) { + if (count >= cand_size) { #ifdef DEBUG if (children_side) { std::cout << "child "; @@ -512,6 +522,9 @@ void Allocation::reduction(int mode){ } else if (mode == 10) { num = reductionExact(true, true); num += reductionExact(false, true); + } else if (mode == 13) { + num = reductionMine(false, 0, true); + num += reductionMine(true, 0, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h index 1d1bf0d..3633d9a 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h @@ -81,7 +81,7 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); - int reductionMine(bool children_side=true, int mode=0); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index e416a58..d0481bc 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -394,19 +394,22 @@ int Allocation::reductionExact(bool children_side, bool supp) { return nbTotRem; } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; + int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; + comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; + comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -414,8 +417,10 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + vector cand_in(comp, false); + int cand_size = 0; int worst_rank = 0; - unsigned int count = 0; + int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; @@ -430,10 +435,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int l = 0; l <= idxRank; l++) { for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); m++) { - candidates.insert(other[idxFam].preferences[l][m]); + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } } } - if (count >= candidates.size()) { + if (count >= cand_size) { #ifdef DEBUG if (children_side) { std::cout << "child "; @@ -586,6 +596,9 @@ void Allocation::reduction(int mode){ } else if (mode == 10) { num = reductionExact(true, true); num += reductionExact(false, true); + } else if (mode == 13) { + num = reductionMine(false, 0, true); + num += reductionMine(true, 0, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h index f4436b4..e110020 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h @@ -79,7 +79,7 @@ void load(const string& path, const string& filein); void printProb(); - int reductionMine(bool children_side=true, int mode=0); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index e416a58..d0481bc 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -394,19 +394,22 @@ int Allocation::reductionExact(bool children_side, bool supp) { return nbTotRem; } -int Allocation::reductionMine(bool children_side, int mode) { +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; + int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; + comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; + comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -414,8 +417,10 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int i = 0; i < number_here; i++) { set candidates; set positions; + vector cand_in(comp, false); + int cand_size = 0; int worst_rank = 0; - unsigned int count = 0; + int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); for(std::pair p: iter) { int j = p.first; @@ -430,10 +435,15 @@ int Allocation::reductionMine(bool children_side, int mode) { for (int l = 0; l <= idxRank; l++) { for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); m++) { - candidates.insert(other[idxFam].preferences[l][m]); + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } } } - if (count >= candidates.size()) { + if (count >= cand_size) { #ifdef DEBUG if (children_side) { std::cout << "child "; @@ -586,6 +596,9 @@ void Allocation::reduction(int mode){ } else if (mode == 10) { num = reductionExact(true, true); num += reductionExact(false, true); + } else if (mode == 13) { + num = reductionMine(false, 0, true); + num += reductionMine(true, 0, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h index f4436b4..e110020 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -79,7 +79,7 @@ void load(const string& path, const string& filein); void printProb(); - int reductionMine(bool children_side=true, int mode=0); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); int reductionExact(bool children_side, bool supp=false); void polish(); void reduction(int mode); From 1a5c6b339a8eb8653c8020804c355b63487c82aa Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 1 Jul 2019 14:43:47 +0100 Subject: [PATCH 31/48] Add modes 14/15 Early exits --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 13 ++++++++++++- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 13 ++++++++++++- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h | 2 +- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 13 ++++++++++++- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h | 2 +- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 13 ++++++++++++- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h | 2 +- 8 files changed, 52 insertions(+), 8 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 3287ae0..21a33b5 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -153,7 +153,7 @@ void Allocation::printProb(){ } } -int Allocation::reductionExact(bool children_side, bool supp) { +int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; @@ -179,6 +179,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) Graph g; @@ -525,6 +530,12 @@ void Allocation::reduction(int mode){ } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); + } else if (mode == 14) { + num = reductionExact(false, false, true); + num += reductionExact(true, false, true); + } else if (mode == 15) { + num = reductionExact(true, false, true); + num += reductionExact(false, false, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h index 3633d9a..a1c1da0 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -82,7 +82,7 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); - int reductionExact(bool children_side, bool supp=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 3287ae0..21a33b5 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -153,7 +153,7 @@ void Allocation::printProb(){ } } -int Allocation::reductionExact(bool children_side, bool supp) { +int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; @@ -179,6 +179,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) Graph g; @@ -525,6 +530,12 @@ void Allocation::reduction(int mode){ } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); + } else if (mode == 14) { + num = reductionExact(false, false, true); + num += reductionExact(true, false, true); + } else if (mode == 15) { + num = reductionExact(true, false, true); + num += reductionExact(false, false, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h index 3633d9a..a1c1da0 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.h @@ -82,7 +82,7 @@ void load(const string& path, const string& filein, const int& threshold); void printProb(); int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); - int reductionExact(bool children_side, bool supp=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index d0481bc..cad672f 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -227,7 +227,7 @@ void Allocation::printProb(){ } } -int Allocation::reductionExact(bool children_side, bool supp) { +int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; @@ -253,6 +253,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) Graph g; @@ -599,6 +604,12 @@ void Allocation::reduction(int mode){ } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); + } else if (mode == 14) { + num = reductionExact(false, false, true); + num += reductionExact(true, false, true); + } else if (mode == 15) { + num = reductionExact(true, false, true); + num += reductionExact(false, false, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h index e110020..6e45c0c 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.h @@ -80,7 +80,7 @@ void load(const string& path, const string& filein); void printProb(); int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); - int reductionExact(bool children_side, bool supp=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); void polish(); void reduction(int mode); void printSol(); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index d0481bc..cad672f 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -227,7 +227,7 @@ void Allocation::printProb(){ } } -int Allocation::reductionExact(bool children_side, bool supp) { +int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; std::vector * thesep; @@ -253,6 +253,11 @@ int Allocation::reductionExact(bool children_side, bool supp) { std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } // A graph is "named" with two integers. The first is a 0 for a candidate // (aka these) or a 1 for a position (aka other) Graph g; @@ -599,6 +604,12 @@ void Allocation::reduction(int mode){ } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); + } else if (mode == 14) { + num = reductionExact(false, false, true); + num += reductionExact(true, false, true); + } else if (mode == 15) { + num = reductionExact(true, false, true); + num += reductionExact(false, false, true); } else { num = reductionMine(false, mode); num += reductionMine(true, mode); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h index e110020..6e45c0c 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.h @@ -80,7 +80,7 @@ void load(const string& path, const string& filein); void printProb(); int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); - int reductionExact(bool children_side, bool supp=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); void polish(); void reduction(int mode); void printSol(); From a66146b3a8dfe39343de5857a7a33708f569f8fe Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Tue, 2 Jul 2019 09:08:28 +0100 Subject: [PATCH 32/48] Fix improved descending, and no pp Use correct bound for the improved descending Fixes the no-preprocessing to show 0 pairs removed --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 1 + SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 7 ++----- SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp | 1 + SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 7 ++----- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 7 ++----- SMTI/3_NOBIN_1STA_YESMERGED/main.cpp | 1 + SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 7 ++----- SMTI/4_YESBIN_1STA_YESMERGED/main.cpp | 1 + 8 files changed, 12 insertions(+), 20 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index 992db9c..bf9a4e6 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -8,6 +8,7 @@ int main(int argc, char **argv){ // local variables Allocation allo ; + allo.total_removed = 0; string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 21a33b5..45313c5 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -328,19 +328,16 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; - int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; - comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; - comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -348,8 +345,8 @@ int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { for (int i = 0; i < number_here; i++) { set candidates; set positions; - vector cand_in(comp, false); - int cand_size = 0; + vector cand_in(number_here, false); + int cand_size = 0; int worst_rank = 0; int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp index 13f5422..b344036 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/main.cpp @@ -10,6 +10,7 @@ int main(int argc, char **argv){ // local variables Allocation allo ; + allo.total_reduced = 0; string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 21a33b5..45313c5 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -328,19 +328,16 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; - int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; - comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; - comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -348,8 +345,8 @@ int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { for (int i = 0; i < number_here; i++) { set candidates; set positions; - vector cand_in(comp, false); - int cand_size = 0; + vector cand_in(number_here, false); + int cand_size = 0; int worst_rank = 0; int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index cad672f..ce00aa0 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -402,19 +402,16 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; - int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; - comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; - comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -422,8 +419,8 @@ int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { for (int i = 0; i < number_here; i++) { set candidates; set positions; - vector cand_in(comp, false); - int cand_size = 0; + vector cand_in(number_here, false); + int cand_size = 0; int worst_rank = 0; int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp index 9212e7a..dbf3f29 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/main.cpp @@ -10,6 +10,7 @@ int main(int argc, char **argv){ // local variables Allocation allo ; + allo.total_reduced = 0; string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index cad672f..ce00aa0 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -402,19 +402,16 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { int nbTotRem = 0; int number_here; - int comp; std::vector * thesep; std::vector * otherp; if (children_side) { thesep = &children; otherp = &families; number_here = nbChildren; - comp = nbFamilies; } else { thesep = &families; otherp = &children; number_here = nbFamilies; - comp = nbChildren; } std::vector & these = (*thesep); std::vector & other = (*otherp); @@ -422,8 +419,8 @@ int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { for (int i = 0; i < number_here; i++) { set candidates; set positions; - vector cand_in(comp, false); - int cand_size = 0; + vector cand_in(number_here, false); + int cand_size = 0; int worst_rank = 0; int count = 0; AgentIterator iter(these[i], candidates, positions, these, other, mode); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp index 326b41f..5fb4f9a 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/main.cpp @@ -10,6 +10,7 @@ int main(int argc, char **argv){ // local variables Allocation allo ; + allo.total_reduced = 0; string filein = argv[2]; string path = argv[1]; string pathAndFileout = argv[3]; From dff103df9f715677e4ebed9a81c326b09e9816e2 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Sat, 13 Jul 2019 20:07:10 +0100 Subject: [PATCH 33/48] Only print solution if one is found --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index bf9a4e6..506c880 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -16,14 +16,14 @@ int main(int argc, char **argv){ // functions allo.load(path,filein); - allo.printProb(); + //allo.printProb(); allo.pp_mode = mode; - manlove(allo, mode); - - allo.printSol(); - allo.checkSolution(); - allo.printInfo(pathAndFileout); + if (manlove(allo, mode) >= 0) { + allo.printSol(); + allo.checkSolution(); + } + allo.printInfo(pathAndFileout); } int manlove(Allocation& allo, int mode){ From c58be603648dc9dae6f9817b21c3b646038b6f4c Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Sat, 13 Jul 2019 20:13:47 +0100 Subject: [PATCH 34/48] Fix flow-based graph algorithm Edges going from right to left should subtract flow, not add to it --- HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp | 30 +++++++++++++++++++++++++--- HRT/8_YESBIN_3STA_NOMERGED/Graph.h | 3 ++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp index 66f7de0..bb95fe5 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Graph.cpp @@ -27,17 +27,21 @@ void Graph::addVertex(Vertex name, int capacity) { e1.id = index; e1.flow = 0; e1.cap = capacity; + e1.reverse = false; e2.id = Graph::SOURCE; e2.flow = 0; e2.cap = capacity; + e2.reverse = false; _left_total += capacity; } else if (name.first == 1) { // right side e1.id = index; e1.flow = 0; e1.cap = capacity; + e1.reverse = false; e2.id = Graph::SINK; e2.flow = 0; e2.cap = capacity; + e2.reverse = false; } this->_adjacents[e1.id][e2.id] = e2; this->_adjacents[e2.id][e1.id] = e1; @@ -63,9 +67,11 @@ void Graph::addEdge(Vertex v1, Vertex v2) { e1.id = i1; e1.cap = std::numeric_limits::max(); e1.flow = 0; + e1.reverse = false; e2.id = i2; e2.cap = std::numeric_limits::max(); e2.flow = 0; + e2.reverse = true; _adjacents[i1][i2] = e2; _adjacents[i2][i1] = e1; } @@ -79,7 +85,7 @@ int Graph::maxFlow() const { } bool Graph::can_preprocess() { - return _cap_original + _left_total <= _cap_total - max_flow; + return _cap_original + cap_left() <= _cap_total - max_flow; } int Graph::cap_left() const { @@ -138,6 +144,14 @@ bool Graph::internal_augment(int now, std::vector & visited, if (next_edge.flow >= next_edge.cap) { continue; } + // If we're going "backwards" we need to use up (subtract) flow, so check we + // have some. Note that since we are checking backwards, the flow will also + // be negative + if (next_edge.reverse) { + if (next_edge.flow >= 0) { + continue; + } + } //std::cout << "Considering " << _indices[next_edge.id] << " which has " << next_edge.flow << "/" << next_edge.cap << std::endl; if (next_edge.id == Graph::SINK) { // Found an augmenting flow. Modify flows used. @@ -152,7 +166,12 @@ bool Graph::internal_augment(int now, std::vector & visited, #endif /* DEBUG_GRAPH */ for(auto p: path) { if (p != Graph::SOURCE) { - int new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + int new_flow; + if (next_edge.reverse) { + new_flow = _adjacents[start][p].flow; + } else { + new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + } if (_adjacents[start][p].flow < 0 && _adjacents[start][p].cap == std::numeric_limits::max()) { new_flow = std::numeric_limits::max(); } @@ -160,7 +179,12 @@ bool Graph::internal_augment(int now, std::vector & visited, } #ifdef DEBUG_GRAPH if (p != Graph::SOURCE) { - int new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + int new_flow; + if (next_edge.reverse) { + new_flow = _adjacents[start][p].flow; + } else { + new_flow = _adjacents[start][p].cap - _adjacents[start][p].flow; + } if (_adjacents[start][p].flow < 0 && _adjacents[start][p].cap == std::numeric_limits::max()) { new_flow = std::numeric_limits::max(); } diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Graph.h b/HRT/8_YESBIN_3STA_NOMERGED/Graph.h index 9bc494a..cbba3cb 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Graph.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/Graph.h @@ -19,7 +19,7 @@ struct pairhash { } }; -#ifdef DEBUG_GRAPH +#if defined(DEBUG_GRAPH) || defined(DEBUG) #include inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { o << "(" << x.first << ", " << x.second << ")"; @@ -31,6 +31,7 @@ struct Edge { int id; int cap; int flow; + bool reverse; }; typedef std::pair Vertex; From 05b0f7666cbe2b0653cabb792fc42a95b2c72a28 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Sat, 13 Jul 2019 20:15:57 +0100 Subject: [PATCH 35/48] Print doctor/hospital IDs when debugging --- HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp | 18 +++++++++++++++--- HRT/8_YESBIN_3STA_NOMERGED/Allocation.h | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp index d8b050e..2b17d13 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp @@ -241,10 +241,14 @@ int Allocation::reductionMineDoctors(int mode) { } if (count >= candidates.size()) { #ifdef DEBUG - std::cout << "doctor worst rank of " << i << " is " << worst_rank << std::endl; + std::cout << "doctor worst rank of " << doctors[i].id << " is " << worst_rank << std::endl; + int remHere = 0; #endif /* DEBUG */ for (int k = worst_rank + 1; k < doctors[i].nbPref; k++) { nbTotRem += 1; +#ifdef DEBUG + remHere += 1; +#endif /* DEBUG */ int idxHos = doctors[i].preferences[k] - 1; for(size_t rank = 0; rank < hospitals[idxHos].preferences.size(); ++rank) { auto posDoc = std::find(hospitals[idxHos].preferences[rank].begin(), hospitals[idxHos].preferences[rank].end(), i+1); @@ -254,6 +258,9 @@ int Allocation::reductionMineDoctors(int mode) { } } } +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ doctors[i].nbPref = worst_rank + 1; doctors[i].preferences.resize(doctors[i].nbPref); break; @@ -300,9 +307,13 @@ int Allocation::reductionMineHospitals(int mode) { if (count >= candidate_cap) { #ifdef DEBUG std::cout << "hospital worst rank of " << i << " is " << worst_rank << std::endl; + int remHere = 0; #endif /* DEBUG */ for (int k = worst_rank + 1; k < hospitals[i].nbPref; k++) { nbTotRem += hospitals[i].preferences[k].size(); +#ifdef DEBUG + remHere += hospitals[i].preferences[k].size(); +#endif /* DEBUG */ hospitals[i].nbTotPref -= hospitals[i].preferences[k].size(); for (unsigned int l = 0; l < hospitals[i].preferences[k].size(); l++) { int idxDoc = hospitals[i].preferences[k][l] - 1; @@ -311,7 +322,6 @@ int Allocation::reductionMineHospitals(int mode) { doctors[idxDoc].preferences.erase(doctors[idxDoc].preferences.begin() + m); doctors[idxDoc].ranks.erase(doctors[idxDoc].ranks.begin() + m); doctors[idxDoc].nbPref--; - nbTotRem++; break; } } @@ -319,6 +329,9 @@ int Allocation::reductionMineHospitals(int mode) { } hospitals[i].nbPref = worst_rank + 1; hospitals[i].preferences.resize(hospitals[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ break; } } @@ -609,7 +622,6 @@ int Allocation::reductionExactHospital(bool supp) { doctors[idxDoc].preferences.erase(doctors[idxDoc].preferences.begin() + n); doctors[idxDoc].ranks.erase(doctors[idxDoc].ranks.begin() + n); doctors[idxDoc].nbPref--; - nbTotRem++; } } } diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h index 392a1f7..d66f319 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h @@ -29,7 +29,7 @@ void print(); - Doctor() : mustBeAllocated(true) { } + Doctor() : mustBeAllocated(false) { } }; /* ************************************************************************************* @@ -47,7 +47,7 @@ void print(); - Hospital() : mustBeAllocated(true) { } + Hospital() : mustBeAllocated(false) { } }; /* ************************************************************************************* From 531033e6afb997ab4ef2e0599b335c3801e584bc Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Sat, 13 Jul 2019 20:16:55 +0100 Subject: [PATCH 36/48] Re-run exact methods if new doctors/hospitals now must be filled --- HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp | 56 ++++++++++++++++++----- HRT/8_YESBIN_3STA_NOMERGED/Allocation.h | 3 +- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp index 2b17d13..1c3c6a6 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp @@ -406,6 +406,7 @@ int Allocation::reductionResApp(){ * Reduce on the doctor's preference lists, removing hospitals. */ int Allocation::reductionExactDoctor(bool supp) { + bool newMustBeAllocated = false; int nbTotRem = 0; for (int i = 0; i < nbDoctors; i++) { Graph g(1); @@ -415,7 +416,7 @@ int Allocation::reductionExactDoctor(bool supp) { bool isAcceptable = false; for(size_t rank = 0; (!isAcceptable) && rank < hospitals[position].preferences.size(); ++rank) { for(size_t ind = 0; ind < hospitals[position].preferences[rank].size(); ++ind) { - if (hospitals[position].preferences[rank][ind] == i) { + if (hospitals[position].preferences[rank][ind] == doctors[i].id) { isAcceptable = true; break; } @@ -425,13 +426,13 @@ int Allocation::reductionExactDoctor(bool supp) { continue; } auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(pos_vert, hospitals[position].cap); for(size_t rank = 0; rank < hospitals[position].preferences.size(); ++rank) { for(size_t ind = 0; ind < hospitals[position].preferences[rank].size(); ++ind) { int candidate = hospitals[position].preferences[rank][ind] - 1; auto cand_vert = std::make_pair(0, candidate); if (!g.containsVertex(cand_vert)) { - g.addVertex(cand_vert, true); + g.addVertex(cand_vert, 1); } g.addEdge(pos_vert, cand_vert); } @@ -441,12 +442,12 @@ int Allocation::reductionExactDoctor(bool supp) { for(size_t rank = 0; rank < doctors[i].preferences.size(); rank++) { // No point in checking the last rank if we already know this agent must // be allocated, or if we don't care - if ((rank == doctors[i].preferences.size()- 1) && (doctors[i].mustBeAllocated || !supp)) { + if ((rank == doctors[i].preferences.size() - 1) && (doctors[i].mustBeAllocated || !supp)) { continue; } int position = doctors[i].preferences[rank] - 1; auto pos_vert = std::make_pair(1, position); - g.addVertex(pos_vert, false); + g.addVertex(pos_vert, hospitals[position].cap); bool break_yet = false; for(size_t k = 0; k < hospitals[position].preferences.size(); ++k) { for(size_t l = 0; l < hospitals[position].preferences[k].size(); ++l) { @@ -458,7 +459,7 @@ int Allocation::reductionExactDoctor(bool supp) { } std::pair doctor_cand_vert = std::make_pair(0, doctor_cand); if (! g.containsVertex(doctor_cand_vert)) { - g.addVertex(doctor_cand_vert, true); + g.addVertex(doctor_cand_vert, 1); } g.addEdge(pos_vert, doctor_cand_vert); } @@ -485,6 +486,7 @@ int Allocation::reductionExactDoctor(bool supp) { if (supp && !doctors[i].mustBeAllocated) { doctorsMustBeAllocated.push_back(i); doctors[i].mustBeAllocated = true; + newMustBeAllocated = true; } #ifdef DEBUG if (i == 6) { @@ -522,6 +524,9 @@ int Allocation::reductionExactDoctor(bool supp) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustBeAllocated == true)) { + return -1; + } return nbTotRem; } @@ -529,6 +534,7 @@ int Allocation::reductionExactDoctor(bool supp) { * Reduce on the hospital's preference lists, removing doctors. */ int Allocation::reductionExactHospital(bool supp) { + bool newMustBeAllocated = false; int nbTotRem = 0; for (size_t i = 0; i < (size_t)nbHospitals; i++) { Graph g(hospitals[i].cap); @@ -598,6 +604,7 @@ int Allocation::reductionExactHospital(bool supp) { if (supp && !hospitals[i].mustBeAllocated) { hospitalsMustBeAllocated.push_back(i); hospitals[i].mustBeAllocated = true; + newMustBeAllocated = true; } #ifdef DEBUG if (i == 0) { @@ -638,6 +645,9 @@ int Allocation::reductionExactHospital(bool supp) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustBeAllocated == true)) { + return -1; + } return nbTotRem; } @@ -705,7 +715,9 @@ void Allocation::reduction(int mode){ i++; } while (this_time != 0); } else { + bool keep_going; do{ + keep_going = false; if (mode == 0) { nbRed1 = reductionHosOff(); nbRed2 = reductionResApp(); @@ -724,12 +736,34 @@ void Allocation::reduction(int mode){ this_time += reductionExactHospital(false); total_removed += this_time; } else if (mode == 9) { - this_time = reductionExactHospital(true); - this_time += reductionExactDoctor(true); + int num = reductionExactHospital(true); + if (num == -1) { + keep_going = true; + this_time = 0; + } else { + this_time = num; + } + num = reductionExactDoctor(true); + if (num == -1) { + keep_going = true; + } else { + this_time += num; + } total_removed += this_time; } else if (mode == 10) { - this_time = reductionExactDoctor(true); - this_time += reductionExactHospital(true); + int num = reductionExactDoctor(true); + if (num == -1) { + keep_going = true; + this_time = 0; + } else { + this_time = num; + } + num = reductionExactHospital(true); + if (num == -1) { + keep_going = true; + } else { + this_time += num; + } total_removed += this_time; } else { this_time = reductionMineHospitals(mode); @@ -742,7 +776,7 @@ void Allocation::reduction(int mode){ cout << "Time elapsed, breaking"; break; } - }while(this_time != 0); + }while(keep_going || this_time != 0); } polish(); } diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h index d66f319..348c915 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h @@ -112,4 +112,5 @@ }; -#endif \ No newline at end of file +#endif + From 1061f7f08f108c85a3c030327669f198da5d3b28 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Sat, 13 Jul 2019 20:20:44 +0100 Subject: [PATCH 37/48] Fix complete exact If a new agent is now always matched, we might find more preprocessing --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 17 ++++++++++++++++- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 17 ++++++++++++++++- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 17 ++++++++++++++++- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 17 ++++++++++++++++- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index 45313c5..bab1bb9 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -156,6 +156,7 @@ void Allocation::printProb(){ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; + bool newMustAlways = false; std::vector * thesep; std::vector * otherp; std::list *theseMustBeAllocatedp; @@ -267,6 +268,7 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (supp && !these[i].mustBeAllocated) { theseMustBeAllocated.push_back(i); these[i].mustBeAllocated = true; + newMustAlways = true; } #ifdef DEBUG if ((!children_side) and (i == 6)) { @@ -322,6 +324,9 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } return nbTotRem; } @@ -478,6 +483,7 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; + bool keepGoing; if (mode == 7) { do { num = reductionMine(false, 1); @@ -510,6 +516,7 @@ void Allocation::reduction(int mode){ } while (num != 0); } else { do{ + keepGoing = false; if (mode == 6) { // True means preprocess childrens' lists, removing families. // False means preprocess families' lists, removing children. @@ -520,9 +527,17 @@ void Allocation::reduction(int mode){ num += reductionExact(false); } else if (mode == 9) { num = reductionExact(false, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(true, true); } else if (mode == 10) { num = reductionExact(true, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(false, true); } else if (mode == 13) { num = reductionMine(false, 0, true); @@ -540,7 +555,7 @@ void Allocation::reduction(int mode){ cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; total_reduced += num; - }while(num != 0); + }while(keepGoing || (num != 0)); } } diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index 45313c5..bab1bb9 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -156,6 +156,7 @@ void Allocation::printProb(){ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; + bool newMustAlways = false; std::vector * thesep; std::vector * otherp; std::list *theseMustBeAllocatedp; @@ -267,6 +268,7 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (supp && !these[i].mustBeAllocated) { theseMustBeAllocated.push_back(i); these[i].mustBeAllocated = true; + newMustAlways = true; } #ifdef DEBUG if ((!children_side) and (i == 6)) { @@ -322,6 +324,9 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } return nbTotRem; } @@ -478,6 +483,7 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; + bool keepGoing; if (mode == 7) { do { num = reductionMine(false, 1); @@ -510,6 +516,7 @@ void Allocation::reduction(int mode){ } while (num != 0); } else { do{ + keepGoing = false; if (mode == 6) { // True means preprocess childrens' lists, removing families. // False means preprocess families' lists, removing children. @@ -520,9 +527,17 @@ void Allocation::reduction(int mode){ num += reductionExact(false); } else if (mode == 9) { num = reductionExact(false, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(true, true); } else if (mode == 10) { num = reductionExact(true, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(false, true); } else if (mode == 13) { num = reductionMine(false, 0, true); @@ -540,7 +555,7 @@ void Allocation::reduction(int mode){ cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; total_reduced += num; - }while(num != 0); + }while(keepGoing || (num != 0)); } } diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index ce00aa0..b5011ed 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -230,6 +230,7 @@ void Allocation::printProb(){ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; + bool newMustAlways = false; std::vector * thesep; std::vector * otherp; std::list *theseMustBeAllocatedp; @@ -341,6 +342,7 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (supp && !these[i].mustBeAllocated) { theseMustBeAllocated.push_back(i); these[i].mustBeAllocated = true; + newMustAlways = true; } #ifdef DEBUG if ((!children_side) and (i == 6)) { @@ -396,6 +398,9 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } return nbTotRem; } @@ -552,6 +557,7 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; + bool keepGoing; if (mode == 7) { do { num = reductionMine(false, 1); @@ -584,6 +590,7 @@ void Allocation::reduction(int mode){ } while (num != 0); } else { do{ + keepGoing = false; if (mode == 6) { // True means preprocess childrens' lists, removing families. // False means preprocess families' lists, removing children. @@ -594,9 +601,17 @@ void Allocation::reduction(int mode){ num += reductionExact(false); } else if (mode == 9) { num = reductionExact(false, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(true, true); } else if (mode == 10) { num = reductionExact(true, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(false, true); } else if (mode == 13) { num = reductionMine(false, 0, true); @@ -614,7 +629,7 @@ void Allocation::reduction(int mode){ cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; total_reduced += num; - }while(num != 0); + }while(keepGoing || (num != 0)); } } diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index ce00aa0..b5011ed 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -230,6 +230,7 @@ void Allocation::printProb(){ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { int nbTotRem = 0; int number_here = nbChildren; + bool newMustAlways = false; std::vector * thesep; std::vector * otherp; std::list *theseMustBeAllocatedp; @@ -341,6 +342,7 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (supp && !these[i].mustBeAllocated) { theseMustBeAllocated.push_back(i); these[i].mustBeAllocated = true; + newMustAlways = true; } #ifdef DEBUG if ((!children_side) and (i == 6)) { @@ -396,6 +398,9 @@ int Allocation::reductionExact(bool children_side, bool supp, bool early_exit) { if (nbTotRem > 0) { polish(); } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } return nbTotRem; } @@ -552,6 +557,7 @@ void Allocation::reduction(int mode){ total_reduced = 0; int i = 0; int num = 0; + bool keepGoing; if (mode == 7) { do { num = reductionMine(false, 1); @@ -584,6 +590,7 @@ void Allocation::reduction(int mode){ } while (num != 0); } else { do{ + keepGoing = false; if (mode == 6) { // True means preprocess childrens' lists, removing families. // False means preprocess families' lists, removing children. @@ -594,9 +601,17 @@ void Allocation::reduction(int mode){ num += reductionExact(false); } else if (mode == 9) { num = reductionExact(false, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(true, true); } else if (mode == 10) { num = reductionExact(true, true); + if (num == -1) { + num = 0; + keepGoing = true; + } num += reductionExact(false, true); } else if (mode == 13) { num = reductionMine(false, 0, true); @@ -614,7 +629,7 @@ void Allocation::reduction(int mode){ cout << "Iteration " << i << " in mode " << mode << " removed " << num << std::endl; i++; total_reduced += num; - }while(num != 0); + }while(keepGoing || (num != 0)); } } From 329c69397a8de41ce15a33cf2b8fa3463e8781a3 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 15 Jul 2019 10:01:56 +0100 Subject: [PATCH 38/48] Calculate preprocessing time before comparing it --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index 506c880..b014752 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -33,6 +33,7 @@ int manlove(Allocation& allo, int mode){ if (mode != 12) { allo.reduction(mode); } + allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; if (allo.infos.timeCPUPP > MAXTIME) { cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; allo.infos.LB = 0; @@ -42,7 +43,6 @@ int manlove(Allocation& allo, int mode){ } return -1; } - allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPU; // Model try{ From 28297d6da64c6e30d0c932857c6987a4afd3f6ce Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Mon, 15 Jul 2019 12:14:02 +0100 Subject: [PATCH 39/48] If PP fails in time, set reasonable values --- HRT/8_YESBIN_3STA_NOMERGED/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp index b014752..94041a5 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/main.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/main.cpp @@ -37,7 +37,9 @@ int manlove(Allocation& allo, int mode){ if (allo.infos.timeCPUPP > MAXTIME) { cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; allo.infos.LB = 0; + allo.infos.timeCPU = MAXTIME; allo.assignmentByDoctor.resize(allo.nbDoctors, -1); + allo.assignmentByHospital.resize(allo.nbHospitals); for(int i = 0; i < allo.nbHospitals; ++i) { allo.assignmentByHospital[i].resize(allo.hospitals[i].cap, -1); } From 804faf57b3ccdf9f78d2576b138084a753ff87bd Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Tue, 16 Jul 2019 10:20:46 +0100 Subject: [PATCH 40/48] Let reductions exit early if time is exceeded --- HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp | 10 +++++++++- HRT/8_YESBIN_3STA_NOMERGED/Allocation.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp index 1c3c6a6..991a21e 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp @@ -445,6 +445,10 @@ int Allocation::reductionExactDoctor(bool supp) { if ((rank == doctors[i].preferences.size() - 1) && (doctors[i].mustBeAllocated || !supp)) { continue; } + if ((getCPUTime() - initTimePP) > MAXTIME) { + cout << "Time elapsed, breaking"; + return 0; + } int position = doctors[i].preferences[rank] - 1; auto pos_vert = std::make_pair(1, position); g.addVertex(pos_vert, hospitals[position].cap); @@ -569,6 +573,10 @@ int Allocation::reductionExactHospital(bool supp) { if ((rank == hospitals[i].preferences.size()- 1) && (hospitals[i].mustBeAllocated || !supp)) { continue; } + if ((getCPUTime() - initTimePP) > MAXTIME) { + cout << "Time elapsed, breaking"; + return 0; + } for(size_t ind = 0; ind < hospitals[i].preferences[rank].size(); ind++) { int position = hospitals[i].preferences[rank][ind] - 1; auto pos_vert = std::make_pair(1, position); @@ -683,7 +691,7 @@ void Allocation::reduction(int mode){ int nbRed2 = 0; int i = 0; int this_time = 0; - auto initTimePP = getCPUTime(); + initTimePP = getCPUTime(); if (mode == 7) { do { this_time = reductionMineHospitals(1); diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h index 348c915..34cdf44 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.h @@ -84,6 +84,7 @@ int total_removed; int pp_mode; + double initTimePP; vector doctors; vector hospitals; From a60888889150cb27774d9fed321a704afbfb0ded Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 24 Jul 2019 12:14:05 +0100 Subject: [PATCH 41/48] Fix count of removed preferences --- SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp | 14 ++++++++++++-- SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp index b5011ed..46fae7d 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Allocation.cpp @@ -605,14 +605,24 @@ void Allocation::reduction(int mode){ num = 0; keepGoing = true; } - num += reductionExact(true, true); + int nextNum = reductionExact(true, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 10) { num = reductionExact(true, true); if (num == -1) { num = 0; keepGoing = true; } - num += reductionExact(false, true); + int nextNum = reductionExact(false, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp index b5011ed..46fae7d 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -605,14 +605,24 @@ void Allocation::reduction(int mode){ num = 0; keepGoing = true; } - num += reductionExact(true, true); + int nextNum = reductionExact(true, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 10) { num = reductionExact(true, true); if (num == -1) { num = 0; keepGoing = true; } - num += reductionExact(false, true); + int nextNum = reductionExact(false, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); From 2b1dd5f462ac77e6fd7d655b2af4e7318c7092b2 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 25 Jul 2019 09:55:45 +0100 Subject: [PATCH 42/48] Fix removed pair counting for SMTI-GRP --- SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp | 14 ++++++++++++-- SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp index bab1bb9..7a50885 100644 --- a/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/4_YESBIN_1STA_YESMERGED/Allocation.cpp @@ -531,14 +531,24 @@ void Allocation::reduction(int mode){ num = 0; keepGoing = true; } - num += reductionExact(true, true); + int nextNum = reductionExact(true, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 10) { num = reductionExact(true, true); if (num == -1) { num = 0; keepGoing = true; } - num += reductionExact(false, true); + int nextNum = reductionExact(false, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); diff --git a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp index bab1bb9..7a50885 100644 --- a/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp +++ b/SMTI-GRP/8_YESBIN_2STA_YESMERGED/Allocation.cpp @@ -531,14 +531,24 @@ void Allocation::reduction(int mode){ num = 0; keepGoing = true; } - num += reductionExact(true, true); + int nextNum = reductionExact(true, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 10) { num = reductionExact(true, true); if (num == -1) { num = 0; keepGoing = true; } - num += reductionExact(false, true); + int nextNum = reductionExact(false, true); + if (nextNum == -1) { + nextNum = 0; + keepGoing = true; + } + num += nextNum; } else if (mode == 13) { num = reductionMine(false, 0, true); num += reductionMine(true, 0, true); From 32b24e8042a5a28bd850cb4b6975d7523156fb18 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Thu, 25 Jul 2019 09:56:00 +0100 Subject: [PATCH 43/48] Count removed pairs for HosOff/ResApply --- HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp index 991a21e..4901d58 100644 --- a/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp +++ b/HRT/8_YESBIN_3STA_NOMERGED/Allocation.cpp @@ -731,6 +731,7 @@ void Allocation::reduction(int mode){ nbRed2 = reductionResApp(); i++; this_time = nbRed1 + nbRed2; + total_removed += this_time; } else if (mode == 6) { this_time = reductionExactHospital(false); this_time += reductionExactDoctor(false); From 671f383138b76ed95ade928c5a361ff51f4a1b31 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Tue, 6 Aug 2019 09:53:25 +0100 Subject: [PATCH 44/48] Increase maximum size of graph --- SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp | 2 +- SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp index 6e28936..0e487e7 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED/Graph.cpp @@ -3,7 +3,7 @@ // Expected biggest graph, to save on allocations -const size_t expected_size = 25000; +const size_t expected_size = 50000; Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { _exists[0] = std::vector(expected_size, false); diff --git a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp index 6e28936..0e487e7 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED/Graph.cpp @@ -3,7 +3,7 @@ // Expected biggest graph, to save on allocations -const size_t expected_size = 25000; +const size_t expected_size = 50000; Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { _exists[0] = std::vector(expected_size, false); From 4cda6e65077abb4b321f6a615756e45bffc59da6 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 6 Sep 2019 17:06:06 +0100 Subject: [PATCH 45/48] Add MAX-WT SMTI with scores based inversly on preferences --- .../AgentIterator.cpp | 402 +++++++++ .../AgentIterator.h | 110 +++ .../Allocation.cpp | 763 ++++++++++++++++++ .../3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.h | 92 +++ SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.cpp | 107 +++ SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.h | 60 ++ SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp | 206 +++++ SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.h | 16 + SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile | 22 + SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.cpp | 46 ++ SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.h | 15 + .../AgentIterator.cpp | 404 ++++++++++ .../AgentIterator.h | 110 +++ .../Allocation.cpp | 763 ++++++++++++++++++ .../Allocation.h | 92 +++ SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.cpp | 107 +++ SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.h | 60 ++ SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp | 219 +++++ SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.h | 16 + SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile | 22 + SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.cpp | 46 ++ SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.h | 15 + 22 files changed, 3693 insertions(+) create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.h create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.h create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.h create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.h create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.cpp create mode 100644 SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Allocation.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Allocation.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.h create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.cpp create mode 100644 SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.h diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp new file mode 100644 index 0000000..6210288 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp @@ -0,0 +1,402 @@ +#include "AgentIterator.h" + +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; +} + +int AgentIteratorBase::get_position() const { + return _position; +} + +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; +} + +void AgentIteratorBase::regularIncrement() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); +} + +AgentIterator AgentIterator::begin() { + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; +} + +AgentIterator AgentIterator::end() { + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; +} + +int AgentIterator::get_group() const { + return base->get_group(); +} + +int AgentIterator::get_position() const { + return base->get_position(); +} + +int AgentIterator::get_mode() const { + return _mode; +} + +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } +} + +void SkipBigIterator::increment() { + int num_added = 0; + do { + regularIncrement(); + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + } while (num_added > _skip); +} + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + } else { + _group = -1; + _position = 0; + } +} + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.h b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.h new file mode 100644 index 0000000..48b96c6 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/AgentIterator.h @@ -0,0 +1,110 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { + public: + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; +}; + +class BestIterator : public AgentIteratorBase { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestIterator() {} + void increment(); + void begin(); +}; + +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.cpp new file mode 100644 index 0000000..46fae7d --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Allocation.cpp @@ -0,0 +1,763 @@ +#include "Allocation.h" +#include "AgentIterator.h" +#include "Graph.h" + +/* ************************************************************************************* + *********************************** DOCTOR ***************************************** + ************************************************************************************* */ + +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; + for(int i=0; i 0) cout << " "; + cout << preferences[i][j]; + cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; + } + cout << ") "; + } + cout << endl; +} + +/* ************************************************************************************* + ********************************** ALLOCATION *************************************** + ************************************************************************************* */ + +void Allocation::load(const string& path, const string& filein){ + // Local variables + istringstream iss; + string parser; + string garbage; + string nameFile = path + filein; + vector > allRanksC, allRanksF, allPreferencesC, allPreferencesF; + + // File opening + ifstream file(nameFile.c_str(), ios::in); + + // File lecture + if (file){ + // Name of the instance is filein + name = filein; + + // Skip the first line + getline(file, parser); iss.str(parser); iss >> garbage; iss.clear(); + + // Read the number of doctors + getline(file, parser); iss.str(parser); iss >> nbFamilies; iss.clear(); + + // Read the number of hospitals + getline(file, parser); iss.str(parser); iss >> nbChildren; iss.clear(); + + // Resize allRanks and allPreferences + allRanksC.resize(nbChildren); allPreferencesC.resize(nbChildren); + allRanksF.resize(nbFamilies); allPreferencesF.resize(nbFamilies); + + // Read the preferences of each child + for (int i = 0; i < nbChildren; i++){ + Child c; + c.mustBeAllocated = false; + int temp; + allRanksC[i].resize(nbFamilies,-1); allPreferencesC[i].resize(nbFamilies,-1); + + istringstream tempIss; + string tempString; + c.nbTotPref = 0; + int rank = 0; + + getline(file, parser); + iss.str(parser); + iss >> c.id; + + for(;;){ + char tempChar = iss.get(); + if(iss.eof()) + break; + else{ + if(tempChar == '('){ + int pref = 0; + getline(iss, tempString, ')'); + tempIss.str(tempString); + vector tempPref; + while(tempIss >> temp){ + allRanksC[i][temp-1] = rank; + allPreferencesC[i][temp-1] = pref; + tempPref.push_back(temp-1); + pref++; + } + c.preferences.push_back(tempPref); + c.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + else{ + if((tempChar >= '0') && (tempChar <= '9')){ + iss.putback(tempChar); + vector tempPref; + iss >> temp; + allRanksC[i][temp-1] = rank; + allPreferencesC[i][temp-1] = 0; + tempPref.push_back(temp-1); + c.preferences.push_back(tempPref); + c.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + } + } + } + + c.nbPref = c.preferences.size(); + children.push_back(c); + iss.clear(); + } + + // Read the preferences of each family + for (int i = 0; i < nbFamilies; i++){ + Family f; + f.mustBeAllocated = false; + int temp; + allRanksF[i].resize(nbChildren,-1); allPreferencesF[i].resize(nbChildren,-1); + + istringstream tempIss; + string tempString; + + f.nbTotPref = 0; + int rank = 0; + + getline(file, parser); + iss.str(parser); + iss >> f.id; + iss >> garbage; + + for(;;){ + char tempChar = iss.get(); + //cout << "Just read " << tempChar << endl; + if(iss.eof()) + break; + else{ + if(tempChar == '('){ + int pref = 0; + getline(iss, tempString, ')'); + tempIss.str(tempString); + vector tempPref; + while(tempIss >> temp){ + allRanksF[i][temp-1] = rank; + allPreferencesF[i][temp-1] = pref; + tempPref.push_back(temp-1); + pref++; + } + f.preferences.push_back(tempPref); + f.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + else{ + if((tempChar >= '0') && (tempChar <= '9')){ + iss.putback(tempChar); + vector tempPref; + iss >> temp; + allRanksF[i][temp-1] = rank; + allPreferencesF[i][temp-1] = 0; + tempPref.push_back(temp-1); + f.preferences.push_back(tempPref); + f.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + } + } + } + + f.nbPref = f.preferences.size(); + families.push_back(f); + iss.clear(); + } + + file.close(); + + for (int i = 0; i < nbChildren; i++){ + children[i].ranks = children[i].preferences; + children[i].positions = children[i].preferences; + } + + for (int i = 0; i < nbFamilies; i++){ + families[i].ranks = families[i].preferences; + families[i].positions = families[i].preferences; + } + + // Fill ranks and positions + + for (int i = 0; i < nbChildren; i++){ + for(int k= 0; k < children[i].nbPref; k++){ + for(int l=0; l * thesep; + std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph g; + int n_1 = 0; + for(int rank = 0; rank < these[i].nbPref; rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == these[i].nbPref - 1) && (these[i].mustBeAllocated || !supp)) { + continue; + } + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + g.addVertex(1, position); + int idxRank = these[i].ranks[rank][ind]; + for(int l = 0; l <= idxRank; l++) { + for(size_t k = 0; k < other[position].preferences[l].size(); k++) { + int other_cand = other[position].preferences[l][k]; + if (other_cand == i) { // Don't add the current candidate to the graph + continue; + } + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); + n_1 += 1; + } + g.addEdge(position, other_cand); + } + } + } + // If n_1 is sufficiently small, then the largest matching must also be + // small, as the matching can use each vertex from n_1 at most once, so + // we don't even need to try to find a bigger matching. + bool matching_cant_exist = (2*n_1 + 1 <= g.size()); + if (! matching_cant_exist) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + g.augment(position); + } + } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + newMustAlways = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } + return nbTotRem; +} + +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { + int nbTotRem = 0; + int number_here; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + vector cand_in(number_here, false); + int cand_size = 0; + int worst_rank = 0; + int count = 0; + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { + int j = p.first; + int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } + } + } + if (count >= cand_size) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = worst_rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +void Allocation::polish(){ + // Remove unused groups in families + for(int j=0; j > preferences; + vector > ranks; + vector > positions; + int idxRem = 0; + for(int k=0;k > preferences; + vector > ranks; + vector > positions; + int idxRem = 0; + for(int k=0;k childAllocated (nbChildren, 0); + vector familyAllocated (nbFamilies, 0); + + // Fill the vectors + for(int i=0; i= 0) familyAllocated[assignmentByChild[i]]++; + } + for(int i=0; i= 0) childAllocated[assignmentByFamily[i]]++; + } + + // Rank of the family assigned to children and vice versa + vector rankC(nbChildren, -1); + for(int i=0;i rankF(nbFamilies, -1); + for(int i=0;i 1){ + cout << "Allocation error: child " << i << " is allocated " << childAllocated[i] << " times " << endl; + mistake = true; + } + else sol1 += childAllocated[i]; + } + + // Check for family used twice + int sol2 = 0; + for(int i=0; i 1){ + cout << "Allocation error: family " << i << " is allocated " << familyAllocated[i] << " times " << endl; + mistake = true; + } + else sol2 += familyAllocated[i]; + } + + + // Check for stability by child + for(int i=0; i + #include +#include + #include + #include + #include + #include + #include + #include + + class Child; + typedef Child Family; + class Assignment; + class Allocation; + +/* ************************************************************************************* + *********************************** DOCTOR ***************************************** + ************************************************************************************* */ + + class Child{ + public: + int id; + int nbPref; + int nbTotPref; + bool mustBeAllocated; + vector > preferences; + vector > ranks; + vector > positions; + void print(bool); + }; + +/* ************************************************************************************* + ************************************* INFO ****************************************** + ************************************************************************************* */ + + class Info{ + public: + bool opt; + double timeCPU; + double timeCPUPP; + double LB; + double UB; + float contUB; + int nbCons; + int nbVar; + int nbNZ; + float contUB2; + int nbCons2; + int nbVar2; + int nbNZ2; + }; + +/* ************************************************************************************* + ********************************** ALLOCATION *************************************** + ************************************************************************************* */ + class Allocation{ + public: + // Data read from the file + string name; + int nbChildren; + int nbFamilies; + int total_reduced; + + vector children; + vector families; + + // Given by the ILP model + vector assignmentByChild; + vector assignmentByFamily; + + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + + Info infos; + + void load(const string& path, const string& filein); + void printProb(); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); + void polish(); + void reduction(int mode); + void printSol(); + void printInfo(const string& pathAndFileout); + void checkSolution(); + }; + + +#endif diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.cpp new file mode 100644 index 0000000..0e487e7 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.cpp @@ -0,0 +1,107 @@ +#include +#include "Graph.h" + + +// Expected biggest graph, to save on allocations +const size_t expected_size = 50000; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; +} + +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); +} + +int Graph::size() const { + return _size; +} + +int Graph::matchingSize() const { + return _matching_size; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +void Graph::augment(int name) { +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); +} + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[1][now]) { + // next is on the left + if (visited[next]) { + continue; + } + if (_matching[0][next] == -1) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[1][right] = left; + _matching[0][left] = right; + } + _matching_size += 1; + return true; + } + int next2 = _matching[0][next]; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.h b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.h new file mode 100644 index 0000000..5d07f00 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +class Graph { + public: + Graph(); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); + + int size() const; + int matchingSize() const; + + int name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp new file mode 100644 index 0000000..7e5267c --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp @@ -0,0 +1,206 @@ +#include "main.h" + +#define MAXTIME 3600 + +/* ************************************************************************************* + ************************************* MAIN ***************************************** + ************************************************************************************* */ + +int main(int argc, char **argv){ + + // local variables + Allocation allo ; + allo.total_reduced = 0; + string filein = argv[2]; + string path = argv[1]; + string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); + + // functions + allo.load(path,filein); + //allo.printProb(); + //allo.reduction(); + //allo.printProb(); + + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } + allo.printInfo(pathAndFileout); +} + + +int manlove(Allocation& allo, int mode){ + double initTimeModelCPU = getCPUTime(); + GRBEnv env = GRBEnv(); + + double initTimeModelCPUPP = getCPUTime(); + if (mode != 12) { + allo.reduction(mode); + } + + //allo.printProb(); + allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over MAXTIME seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } + + // Model + try{ + // Local variables + GRBModel model = GRBModel(env); + GRBLinExpr objFun = 0; + + vector > > isChildIAllocatedToFamilyJ (allo.nbChildren); + + vector allocationOfChildI(allo.nbChildren); + vector allocationOfFamilyJ(allo.nbFamilies); + vector > fillingOfFamilyJUpToRankK(allo.nbFamilies); + + // Initialization + for (int i = 0; i < allo.nbChildren; i++){ + allocationOfChildI[i] = 0; + isChildIAllocatedToFamilyJ[i].resize(allo.children[i].nbPref); + for (int j = 0; j + #include + #include + #include "gurobi_c++.h" + #include "time.h" + #include "Allocation.h" + + float EPSILON = 0.001; + + int manlove(Allocation& allo, int reduction_mode); + +#endif diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile new file mode 100644 index 0000000..50c0265 --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile @@ -0,0 +1,22 @@ +SYSTEM = x86-64_sles10_4.1 +LIBFORMAT = static_pic + +GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 +CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 +INC = $(GUROBI_DIR)/include/ +CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) +GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 + +CC = g++ +CFLAGS = -g -Wall -ansi -pedantic -DIL_STD -std=c++11 +DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o + +exec : $(OBJECTS) + $(CC) $(CFLAGS) -o 3_NOBIN_1STA_YESMERGED_MAXWT $(OBJECTS) $(GUROBI_OPTS) + +.cpp.o : $< + $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ + +clean : + rm -f $(OBJECTS) 3_NOBIN_1STA_YESMERGED_MAXWT diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.cpp new file mode 100644 index 0000000..4726bdf --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.cpp @@ -0,0 +1,46 @@ +#include "time.h" + +#ifdef _WIN32 +#include +double getWallTime(){ + LARGE_INTEGER time,freq; + if (!QueryPerformanceFrequency(&freq)){ + // Handle error + return 0; + } + if (!QueryPerformanceCounter(&time)){ + // Handle error + return 0; + } + return (double)time.QuadPart / freq.QuadPart; +} +double getCPUTime(){ + FILETIME a,b,c,d; + if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0){ + // Returns total user time. + // Can be tweaked to include kernel times as well. + return + (double)(d.dwLowDateTime | + ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001; + }else{ + // Handle error + return 0; + } +} + +// Posix/Linux +#else +#include +#include +double getWallTime(){ + struct timeval time; + if (gettimeofday(&time,NULL)){ + // Handle error + return 0; + } + return (double)time.tv_sec + (double)time.tv_usec * .000001; +} +double getCPUTime(){ + return (double)clock() / CLOCKS_PER_SEC; +} +#endif \ No newline at end of file diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.h b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.h new file mode 100644 index 0000000..6f1cb4f --- /dev/null +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/time.h @@ -0,0 +1,15 @@ +#ifndef TIME_H + + #define TIME_H + + #ifdef WIN32 + #include + #else + #include + #include + #endif + + double getWallTime(); + double getCPUTime(); + +#endif diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp new file mode 100644 index 0000000..88ceb8e --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.cpp @@ -0,0 +1,404 @@ +#include "AgentIterator.h" + +AgentIteratorBase::AgentIteratorBase(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + _agent(agent), + _these(these), _other(other), + _positions(positions), _candidates(candidates) { + if (_agent.preferences.size() == 0) { + _group = -1; + } else { + _group = group; + } + _position = posn; +} + +AgentIteratorBase::~AgentIteratorBase() { } + +int AgentIteratorBase::get_group() const { + return _group; +} + +int AgentIteratorBase::get_position() const { + return _position; +} + +const Child & AgentIteratorBase::get_agent() const { + return _agent; +} + +const std::vector & AgentIteratorBase::get_these() const { + return _these; +} + +const std::vector & AgentIteratorBase::get_other() const { + return _other; +} +const std::set & AgentIteratorBase::get_positions() const { + return _positions; +} +const std::set & AgentIteratorBase::get_candidates() const { + return _candidates; +} + +void AgentIteratorBase::regularIncrement() { + _position++; + if (_agent.preferences[_group].size() == _position) { + _position = 0; + _group++; + if (_agent.preferences.size() == _group) { + _group = -1; + } + } +} + +bool AgentIterator::operator==(const AgentIterator & other) { + return get_group() == other.get_group() && get_position() == other.get_position(); +} + +bool AgentIterator::operator!=(const AgentIterator & other) { + return ! (*this == other); +} + +const std::pair AgentIterator::operator*() { + return std::pair(get_group(), get_position()); +} + +AgentIterator AgentIterator::begin() { + AgentIterator starter(this, 0, 0); + starter.base->begin(); + return starter; +} + +AgentIterator AgentIterator::end() { + return AgentIterator(this, -1, 0); +} + +AgentIterator::AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode) : + _mode(mode) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 1: + base = new SkipBigIterator(agent, candidates, positions, these, other, 5, 0, 0); + break; + case 2: + base = new BestIterator(agent, candidates, positions, these, other, 0, 0); + break; + case 3: + base = new SkipBigIterator(agent, candidates, positions, these, other, 15, 0, 0); + break; + case 4: + base = new SkipBigIterator(agent, candidates, positions, these, other, 50, 0, 0); + break; + case 5: + base = new BestGroupIterator(agent, candidates, positions, these, other, 0, 0); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other) : + _mode(other->get_mode()) { + switch (_mode) { + default: + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, other->get_group(), other->get_position()); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, other->get_group(), other->get_position()); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, other->get_group(), other->get_position()); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), other->get_group(), other->get_position()); + break; + } + } + +AgentIterator::AgentIterator(AgentIterator *other, int group, int posn) : + _mode(other->get_mode()) { + switch (_mode) { + case 0: + base = new DescendingIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 1: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 5, group, posn); + break; + case 2: + base = new BestIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + case 3: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 15, group, posn); + break; + case 4: + base = new SkipBigIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), 50, group, posn); + break; + case 5: + base = new BestGroupIterator(other->get_agent(), other->get_candidates(), other->get_positions(), + other->get_these(), other->get_other(), group, posn); + break; + } + } + +AgentIterator::~AgentIterator() { + delete base; +} + +int AgentIterator::get_group() const { + return base->get_group(); +} + +int AgentIterator::get_position() const { + return base->get_position(); +} + +int AgentIterator::get_mode() const { + return _mode; +} + +DescendingIterator::DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void DescendingIterator::begin() { +} + +void DescendingIterator::increment() { + regularIncrement(); +} + +SkipBigIterator::SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) , _skip(skip) { + } + + +void SkipBigIterator::begin() { + int num_added = 0; + while (true) { + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + if (num_added > _skip) { + regularIncrement(); + } else { + break; + } + } +} + +void SkipBigIterator::increment() { + int num_added = 0; + do { + regularIncrement(); + if (get_group() == -1) { + break; + } + num_added = 0; + int other_id = _agent.preferences[_group][_position]; + int other_rank = _agent.ranks[_group][_position]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(pref) == 0) { + num_added++; + } + } + } + } while (num_added > _skip); +} + +BestIterator::BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestIterator::increment() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; + } else { + _group = -1; + _position = 0; + } +} + +void BestIterator::begin() { + int lowest_added = -1; + int best_group = -1; + int best_posn = -1; + for(int group_no = 0; group_no < _agent.preferences.size(); ++group_no) { + auto & group = _agent.preferences[group_no]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[group_no][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_group = group_no; + best_posn = posn; + } + } + } + if (lowest_added != -1) { + _group = best_group; + _position = best_posn; + std::cout << "Using " << _group << ", " << _position << std::endl; + } else { + _group = -1; + _position = 0; + } +} + +BestGroupIterator::BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group, int posn) : + AgentIteratorBase(agent, candidates, positions, these, other, group, posn) { + } + +void BestGroupIterator::increment() { + int lowest_added = -1; + int best_posn = -1; + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} + +void BestGroupIterator::begin() { + int lowest_added = -1; + int best_posn = -1; + if (_group == -1) { + return; + } + auto & group = _agent.preferences[_group]; + for(int posn = 0; posn < group.size(); ++posn) { + int other_id = group[posn]; + if (_positions.count(other_id) != 0) { + continue; + } + int num_added = 0; + int other_rank = _agent.ranks[_group][posn]; + for(int group_ind = 0; group_ind <= other_rank; group_ind++) { + for(auto other_pref: _other[other_id].preferences[group_ind]) { + if (_candidates.count(other_pref) == 0) { + num_added++; + } + } + } + if ((lowest_added == -1) || (num_added < lowest_added)) { + lowest_added = num_added; + best_posn = posn; + } + } + if (lowest_added != -1) { + _position = best_posn; + } else { + _group++; + if (_group == _agent.preferences.size()) { + _position = 0; + _group = -1; + } else { + increment(); + } + } +} diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.h b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.h new file mode 100644 index 0000000..48b96c6 --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/AgentIterator.h @@ -0,0 +1,110 @@ +#ifndef AGENTITERATOR_H +#define AGENTITERATOR_H + +#include + +#include "Allocation.h" + +class AgentIteratorBase { +public: + AgentIteratorBase(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int group=0, int posn=0); + virtual ~AgentIteratorBase() = 0; + virtual void increment() = 0; + virtual void begin() = 0; + + int get_position() const; + int get_group() const; + const Child & get_agent() const; + const std::vector & get_these() const; + const std::vector & get_other() const; + const std::set & get_positions() const; + const std::set & get_candidates() const; +protected: + void regularIncrement(); + + const Child & _agent; + int _group; + int _position; + const std::vector & _these; + const std::vector & _other; + const std::set & _positions; + const std::set & _candidates; +}; + + +class AgentIterator : public std::iterator, ptrdiff_t> { +public: + AgentIterator(const Child & agent, const std::set & candidates, const std::set & positions, + const std::vector & these, const std::vector & other, int mode); + AgentIterator(AgentIterator *other, int group, int posn); + AgentIterator(AgentIterator *other); + ~AgentIterator(); + bool operator==(const AgentIterator& other); + bool operator!=(const AgentIterator& other); + const std::pair operator*(); + AgentIterator& operator++() {base->increment(); return *this; } + AgentIterator operator++(int) {AgentIterator res(this); base->increment(); return res; } + + AgentIterator begin(); + AgentIterator end(); + + int get_position() const; + int get_group() const; + int get_mode() const; + + const Child & get_agent() const { return base->get_agent(); } + const std::vector & get_these() const {return base->get_these(); } + const std::vector & get_other() const {return base->get_other(); } + const std::set & get_positions() const {return base->get_positions(); } + const std::set & get_candidates() const {return base->get_candidates(); } +private: + AgentIteratorBase * base; + int _mode; +}; + + +class DescendingIterator : public AgentIteratorBase { + public: + DescendingIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~DescendingIterator() {} + void increment(); + void begin(); +}; + + +class SkipBigIterator : public AgentIteratorBase { + public: + SkipBigIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int skip, int group, int posn); + ~SkipBigIterator() {} + void increment(); + void begin(); + private: + int _skip; +}; + +class BestIterator : public AgentIteratorBase { + public: + BestIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestIterator() {} + void increment(); + void begin(); +}; + +class BestGroupIterator : public AgentIteratorBase { + public: + BestGroupIterator(const Child & agent, const std::set & candidates, + const std::set & positions, const std::vector & these, + const std::vector & other, int group=0, int posn=0); + ~BestGroupIterator() {} + void increment(); + void begin(); +}; + +#endif /* AGENTITERATOR_H */ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Allocation.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Allocation.cpp new file mode 100644 index 0000000..46fae7d --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Allocation.cpp @@ -0,0 +1,763 @@ +#include "Allocation.h" +#include "AgentIterator.h" +#include "Graph.h" + +/* ************************************************************************************* + *********************************** DOCTOR ***************************************** + ************************************************************************************* */ + +void Child::print(bool family){ + if (family) + cout << "Family "; + else + cout << "Child "; + cout << id << "\t Preferences (" << nbPref << " groups, " << nbTotPref << " in total)\t"; + for(int i=0; i 0) cout << " "; + cout << preferences[i][j]; + cout << "[" << ranks[i][j] << "_" << positions[i][j] << "]"; + } + cout << ") "; + } + cout << endl; +} + +/* ************************************************************************************* + ********************************** ALLOCATION *************************************** + ************************************************************************************* */ + +void Allocation::load(const string& path, const string& filein){ + // Local variables + istringstream iss; + string parser; + string garbage; + string nameFile = path + filein; + vector > allRanksC, allRanksF, allPreferencesC, allPreferencesF; + + // File opening + ifstream file(nameFile.c_str(), ios::in); + + // File lecture + if (file){ + // Name of the instance is filein + name = filein; + + // Skip the first line + getline(file, parser); iss.str(parser); iss >> garbage; iss.clear(); + + // Read the number of doctors + getline(file, parser); iss.str(parser); iss >> nbFamilies; iss.clear(); + + // Read the number of hospitals + getline(file, parser); iss.str(parser); iss >> nbChildren; iss.clear(); + + // Resize allRanks and allPreferences + allRanksC.resize(nbChildren); allPreferencesC.resize(nbChildren); + allRanksF.resize(nbFamilies); allPreferencesF.resize(nbFamilies); + + // Read the preferences of each child + for (int i = 0; i < nbChildren; i++){ + Child c; + c.mustBeAllocated = false; + int temp; + allRanksC[i].resize(nbFamilies,-1); allPreferencesC[i].resize(nbFamilies,-1); + + istringstream tempIss; + string tempString; + c.nbTotPref = 0; + int rank = 0; + + getline(file, parser); + iss.str(parser); + iss >> c.id; + + for(;;){ + char tempChar = iss.get(); + if(iss.eof()) + break; + else{ + if(tempChar == '('){ + int pref = 0; + getline(iss, tempString, ')'); + tempIss.str(tempString); + vector tempPref; + while(tempIss >> temp){ + allRanksC[i][temp-1] = rank; + allPreferencesC[i][temp-1] = pref; + tempPref.push_back(temp-1); + pref++; + } + c.preferences.push_back(tempPref); + c.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + else{ + if((tempChar >= '0') && (tempChar <= '9')){ + iss.putback(tempChar); + vector tempPref; + iss >> temp; + allRanksC[i][temp-1] = rank; + allPreferencesC[i][temp-1] = 0; + tempPref.push_back(temp-1); + c.preferences.push_back(tempPref); + c.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + } + } + } + + c.nbPref = c.preferences.size(); + children.push_back(c); + iss.clear(); + } + + // Read the preferences of each family + for (int i = 0; i < nbFamilies; i++){ + Family f; + f.mustBeAllocated = false; + int temp; + allRanksF[i].resize(nbChildren,-1); allPreferencesF[i].resize(nbChildren,-1); + + istringstream tempIss; + string tempString; + + f.nbTotPref = 0; + int rank = 0; + + getline(file, parser); + iss.str(parser); + iss >> f.id; + iss >> garbage; + + for(;;){ + char tempChar = iss.get(); + //cout << "Just read " << tempChar << endl; + if(iss.eof()) + break; + else{ + if(tempChar == '('){ + int pref = 0; + getline(iss, tempString, ')'); + tempIss.str(tempString); + vector tempPref; + while(tempIss >> temp){ + allRanksF[i][temp-1] = rank; + allPreferencesF[i][temp-1] = pref; + tempPref.push_back(temp-1); + pref++; + } + f.preferences.push_back(tempPref); + f.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + else{ + if((tempChar >= '0') && (tempChar <= '9')){ + iss.putback(tempChar); + vector tempPref; + iss >> temp; + allRanksF[i][temp-1] = rank; + allPreferencesF[i][temp-1] = 0; + tempPref.push_back(temp-1); + f.preferences.push_back(tempPref); + f.nbTotPref+= tempPref.size(); + rank++; + tempIss.clear(); + } + } + } + } + + f.nbPref = f.preferences.size(); + families.push_back(f); + iss.clear(); + } + + file.close(); + + for (int i = 0; i < nbChildren; i++){ + children[i].ranks = children[i].preferences; + children[i].positions = children[i].preferences; + } + + for (int i = 0; i < nbFamilies; i++){ + families[i].ranks = families[i].preferences; + families[i].positions = families[i].preferences; + } + + // Fill ranks and positions + + for (int i = 0; i < nbChildren; i++){ + for(int k= 0; k < children[i].nbPref; k++){ + for(int l=0; l * thesep; + std::vector * otherp; + std::list *theseMustBeAllocatedp; + std::list *otherMustBeAllocatedp; + if (children_side) { + // Processing the lists of the children, removing families + thesep = &children; + otherp = &families; + theseMustBeAllocatedp = &childrenMustBeAllocated; + otherMustBeAllocatedp = &familiesMustBeAllocated; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + theseMustBeAllocatedp = &familiesMustBeAllocated; + otherMustBeAllocatedp = &childrenMustBeAllocated; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + std::list & theseMustBeAllocated = (*theseMustBeAllocatedp); + std::list & otherMustBeAllocated = (*otherMustBeAllocatedp); + for (int i = 0; i < number_here; i++) { + // Early exit! + const float ratio = 0.1; + if (early_exit && (i >= ratio * number_here) && (nbTotRem == 0)) { + return 0; + } + // A graph is "named" with two integers. The first is a 0 for a candidate + // (aka these) or a 1 for a position (aka other) + Graph g; + int n_1 = 0; + for(int rank = 0; rank < these[i].nbPref; rank++) { + // No point in checking the last rank if we already know this agent must + // be allocated, or if we don't care + if ((rank == these[i].nbPref - 1) && (these[i].mustBeAllocated || !supp)) { + continue; + } + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + g.addVertex(1, position); + int idxRank = these[i].ranks[rank][ind]; + for(int l = 0; l <= idxRank; l++) { + for(size_t k = 0; k < other[position].preferences[l].size(); k++) { + int other_cand = other[position].preferences[l][k]; + if (other_cand == i) { // Don't add the current candidate to the graph + continue; + } + if (! g.containsVertex(0, other_cand)) { + g.addVertex(0, other_cand); + n_1 += 1; + } + g.addEdge(position, other_cand); + } + } + } + // If n_1 is sufficiently small, then the largest matching must also be + // small, as the matching can use each vertex from n_1 at most once, so + // we don't even need to try to find a bigger matching. + bool matching_cant_exist = (2*n_1 + 1 <= g.size()); + if (! matching_cant_exist) { + for(size_t ind = 0; ind < these[i].preferences[rank].size(); ind++) { + int position = these[i].preferences[rank][ind]; + g.augment(position); + } + } + // Add P' in this + // Yes, I'm abusing while statements, so I can break out easier. + while (rank == 0) { + // Don't add P' if we don't need to. + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + break; + } + // First add all positions that must be filled. + for(int position: otherMustBeAllocated) { + // If position is acceptable to i, then skip it. + bool isAcceptable = false; + for(int otherRank = 0; (!isAcceptable) && otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + if (other[position].preferences[otherRank][ind] == i) { + isAcceptable = true; + break; + } + } + } + if (isAcceptable) { + continue; + } + g.addVertex(1, position); + for(int otherRank = 0; otherRank < other[position].nbPref; otherRank++) { + for(size_t ind = 0; ind < other[position].preferences[otherRank].size(); ++ind) { + int candidate = other[position].preferences[otherRank][ind]; + if (!g.containsVertex(0, candidate)) { + g.addVertex(0, candidate); + n_1 += 1; + } + g.addEdge(position, candidate); + } + } + g.augment(position); + } + // I'm using a while loop as an if statement, so I need to break out. + break; + } + if (matching_cant_exist || (g.size() - g.matchingSize() >= n_1 + 1)) { + // preprocess on rank! + // Firstly, they must be allocated, so mark as such (if we're in that + // mode) + if (supp && !these[i].mustBeAllocated) { + theseMustBeAllocated.push_back(i); + these[i].mustBeAllocated = true; + newMustAlways = true; + } +#ifdef DEBUG + if ((!children_side) and (i == 6)) { + std::cout << "g.size() = " << g.size() << ", g.matchingSize() = " << g.matchingSize(); + std::cout << ", n_1 = " << n_1 << std::endl; + g.printGraph(); + g.printMatching(); + } + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << rank << " "; + int remHere = 0; +#endif /* DEBUG */ + for (int k = rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); +#ifdef DEBUG + remHere += these[i].preferences[k].size(); +#endif /* DEBUG */ + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); +#ifdef DEBUG + std::cout << "removed " << remHere << std::endl; +#endif /* DEBUG */ + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + if ((nbTotRem == 0) && (newMustAlways)) { + return -1; + } + return nbTotRem; +} + +int Allocation::reductionMine(bool children_side, int mode, bool alt_store) { + int nbTotRem = 0; + int number_here; + std::vector * thesep; + std::vector * otherp; + if (children_side) { + thesep = &children; + otherp = &families; + number_here = nbChildren; + } else { + thesep = &families; + otherp = &children; + number_here = nbFamilies; + } + std::vector & these = (*thesep); + std::vector & other = (*otherp); + + for (int i = 0; i < number_here; i++) { + set candidates; + set positions; + vector cand_in(number_here, false); + int cand_size = 0; + int worst_rank = 0; + int count = 0; + AgentIterator iter(these[i], candidates, positions, these, other, mode); + for(std::pair p: iter) { + int j = p.first; + int k = p.second; + if (j > worst_rank) { + worst_rank = j; + } + int idxFam = these[i].preferences[j][k]; + int idxRank = these[i].ranks[j][k]; + positions.insert(idxFam); + count++; + for (int l = 0; l <= idxRank; l++) { + for (unsigned int m = 0; m < other[idxFam].preferences[l].size(); + m++) { + if ((alt_store && cand_in[other[idxFam].preferences[l][m]] == false) || + (!alt_store && candidates.count(other[idxFam].preferences[l][m]) == 0)) { + candidates.insert(other[idxFam].preferences[l][m]); + cand_in[other[idxFam].preferences[l][m]] = true; + cand_size++; + } + } + } + if (count >= cand_size) { +#ifdef DEBUG + if (children_side) { + std::cout << "child "; + } else { + std::cout << "family "; + } + std::cout << "worst rank of " << i << " is " << worst_rank << std::endl; +#endif /* DEBUG */ + for (int k = worst_rank + 1; k < these[i].nbPref; k++) { + nbTotRem += these[i].preferences[k].size(); + these[i].nbTotPref -= these[i].preferences[k].size(); + for (unsigned int l = 0; l < these[i].preferences[k].size(); l++) { + int idxFam = these[i].preferences[k][l]; + int idxPos = these[i].positions[k][l]; + int idxRank = these[i].ranks[k][l]; + for (unsigned int m = idxPos + 1; + m < other[idxFam].preferences[idxRank].size(); m++) { + these[other[idxFam].preferences[idxRank][m]] + .positions[other[idxFam].ranks[idxRank][m]] + [other[idxFam].positions[idxRank][m]]--; + } + other[idxFam].nbTotPref--; + other[idxFam].positions[idxRank].erase( + other[idxFam].positions[idxRank].begin() + idxPos); + other[idxFam].ranks[idxRank].erase( + other[idxFam].ranks[idxRank].begin() + idxPos); + other[idxFam].preferences[idxRank].erase( + other[idxFam].preferences[idxRank].begin() + idxPos); + } + } + these[i].nbPref = worst_rank + 1; + these[i].preferences.resize(these[i].nbPref); + these[i].ranks.resize(these[i].nbPref); + these[i].positions.resize(these[i].nbPref); + break; + } + } + } + if (nbTotRem > 0) { + polish(); + } + return nbTotRem; +} + +void Allocation::polish(){ + // Remove unused groups in families + for(int j=0; j > preferences; + vector > ranks; + vector > positions; + int idxRem = 0; + for(int k=0;k > preferences; + vector > ranks; + vector > positions; + int idxRem = 0; + for(int k=0;k childAllocated (nbChildren, 0); + vector familyAllocated (nbFamilies, 0); + + // Fill the vectors + for(int i=0; i= 0) familyAllocated[assignmentByChild[i]]++; + } + for(int i=0; i= 0) childAllocated[assignmentByFamily[i]]++; + } + + // Rank of the family assigned to children and vice versa + vector rankC(nbChildren, -1); + for(int i=0;i rankF(nbFamilies, -1); + for(int i=0;i 1){ + cout << "Allocation error: child " << i << " is allocated " << childAllocated[i] << " times " << endl; + mistake = true; + } + else sol1 += childAllocated[i]; + } + + // Check for family used twice + int sol2 = 0; + for(int i=0; i 1){ + cout << "Allocation error: family " << i << " is allocated " << familyAllocated[i] << " times " << endl; + mistake = true; + } + else sol2 += familyAllocated[i]; + } + + + // Check for stability by child + for(int i=0; i + #include +#include + #include + #include + #include + #include + #include + #include + + class Child; + typedef Child Family; + class Assignment; + class Allocation; + +/* ************************************************************************************* + *********************************** DOCTOR ***************************************** + ************************************************************************************* */ + + class Child{ + public: + int id; + int nbPref; + int nbTotPref; + bool mustBeAllocated; + vector > preferences; + vector > ranks; + vector > positions; + void print(bool); + }; + +/* ************************************************************************************* + ************************************* INFO ****************************************** + ************************************************************************************* */ + + class Info{ + public: + bool opt; + double timeCPU; + double timeCPUPP; + double LB; + double UB; + float contUB; + int nbCons; + int nbVar; + int nbNZ; + float contUB2; + int nbCons2; + int nbVar2; + int nbNZ2; + }; + +/* ************************************************************************************* + ********************************** ALLOCATION *************************************** + ************************************************************************************* */ + class Allocation{ + public: + // Data read from the file + string name; + int nbChildren; + int nbFamilies; + int total_reduced; + + vector children; + vector families; + + // Given by the ILP model + vector assignmentByChild; + vector assignmentByFamily; + + std::list childrenMustBeAllocated; + std::list familiesMustBeAllocated; + + Info infos; + + void load(const string& path, const string& filein); + void printProb(); + int reductionMine(bool children_side=true, int mode=0, bool alt_store=false); + int reductionExact(bool children_side, bool supp=false, bool early_exit=false); + void polish(); + void reduction(int mode); + void printSol(); + void printInfo(const string& pathAndFileout); + void checkSolution(); + }; + + +#endif diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.cpp new file mode 100644 index 0000000..0e487e7 --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.cpp @@ -0,0 +1,107 @@ +#include +#include "Graph.h" + + +// Expected biggest graph, to save on allocations +const size_t expected_size = 50000; + +Graph::Graph() : _exists(2), _adjacents(2), _matching(2), _size(0), _matching_size(0) { + _exists[0] = std::vector(expected_size, false); + _exists[1] = std::vector(expected_size, false); + _adjacents[0] = std::vector>(expected_size); + _adjacents[1] = std::vector>(expected_size); + _matching[0] = std::vector(expected_size, -1); + _matching[1] = std::vector(expected_size, -1); +#ifdef DEBUG + std::cout << "New graph" << std::endl; +#endif /* DEBUG */ +} + +void Graph::addVertex(int side, int name) { + _exists[side][name] = true; + _size += 1; +} + +bool Graph::containsVertex(int side, int name) const { + return _exists[side][name]; +} + +/** + * Adds an edge to the graph. Note that this edge must always be added in the + * form (right, left) for things to work. + */ +void Graph::addEdge(int v1, int v2) { + _adjacents[1][v1].push_back(v2); + _adjacents[0][v2].push_back(v1); +} + +int Graph::size() const { + return _size; +} + +int Graph::matchingSize() const { + return _matching_size; +} + +/** + * Augment the matching, starting at vertex name which is on the right. + */ +void Graph::augment(int name) { +#ifdef DEBUG + std::cout << "Augmenting on " << _indices.at(start) << std::endl; + this->printGraph(); +#endif /* DEBUG */ + std::list path; + std::vector visited(expected_size, false); + path.push_back(name); + internal_augment(name, visited, path); +} + +/** + * Continues an augmentation, on vertex now, which is on the right. + */ +bool Graph::internal_augment(int now, std::vector & visited, + std::list & path) { + for(int next: _adjacents[1][now]) { + // next is on the left + if (visited[next]) { + continue; + } + if (_matching[0][next] == -1) { + // Found an augmenting path. Switch edges and return true. +#ifdef DEBUG + std::cout << "New matching found." << std::endl; +#endif /* DEBUG */ + path.push_back(next); +#ifdef DEBUG + std::cout << "Path is "; + for(auto p: path) { + std::cout << " " << _indices.at(p); + } + std::cout << std::endl; + +#endif /* DEBUG */ + while(!path.empty()) { + int right = path.front(); + path.pop_front(); + int left = path.front(); + path.pop_front(); + _matching[1][right] = left; + _matching[0][left] = right; + } + _matching_size += 1; + return true; + } + int next2 = _matching[0][next]; + path.push_back(next); + path.push_back(next2); + visited[next] = true; + if (internal_augment(next2, visited, path)) { + return true; + } + path.pop_back(); + path.pop_back(); + } + return false; +} + diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.h b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.h new file mode 100644 index 0000000..5d07f00 --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/Graph.h @@ -0,0 +1,60 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include +#include +#include + + +static_assert(std::numeric_limits::max() >= ((long unsigned)1 << 63), "size_t is too small"); + +struct pairhash { + public: + std::size_t operator()(const std::pair &x) const { + return (long)x.first * ((long)1 << 32) + x.second; + } +}; + +#ifdef DEBUG +#include +inline std::ostream& operator<<(std::ostream& o, const std::pair &x) { + o << "(" << x.first << ", " << x.second << ")"; + return o; +} +#endif /* DEBUG */ + + +class Graph { + public: + Graph(); + void addVertex(int side, int name); + bool containsVertex(int side, int name) const; + void addEdge(int v1, int v2); + int matched(int vertex) const; + void augment(int vertex); + + int size() const; + int matchingSize() const; + + int name(int vert_index); + +#ifdef DEBUG + void printGraph(); + void printMatching() const; +#endif /* DEBUG */ + + private: + std::vector> _exists; + std::vector>> _adjacents; + std::vector> _matching; + + int _size; + int _matching_size; + + bool internal_augment(int now, std::vector & visited, std::list & path); +}; + +#endif /* GRAPH_H */ diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp new file mode 100644 index 0000000..8a62faa --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp @@ -0,0 +1,219 @@ +#include "main.h" + +#define MAXTIME 3600 + +/* ************************************************************************************* + ************************************* MAIN ***************************************** + ************************************************************************************* */ + +int main(int argc, char **argv){ + + // local variables + Allocation allo ; + allo.total_reduced = 0; + string filein = argv[2]; + string path = argv[1]; + string pathAndFileout = argv[3]; + int mode = atoi(argv[4]); + + // functions + allo.load(path,filein); + //allo.printProb(); + + int res = manlove(allo, mode); + if (res != -1) { + allo.printSol(); + allo.checkSolution(); + } + allo.printInfo(pathAndFileout); +} + + +int manlove(Allocation& allo, int mode){ + double initTimeModelCPU = getCPUTime(); + GRBEnv env = GRBEnv(); + + double initTimeModelCPUPP = getCPUTime(); + if (mode != 12) { + allo.reduction(mode); + } + //allo.printProb(); + allo.infos.timeCPUPP = getCPUTime() - initTimeModelCPUPP; + if (allo.infos.timeCPUPP > MAXTIME) { + cout << "Preprocessing took over " << MAXTIME << " seconds" << endl; + allo.infos.LB = 0; + allo.assignmentByChild.resize(allo.nbChildren, -1); + allo.assignmentByFamily.resize(allo.nbFamilies,-1); + return -1; + } + + // Model + try{ + // Local variables + GRBModel model = GRBModel(env); + GRBLinExpr objFun = 0; + + vector > > isChildIAllocatedToFamilyJ (allo.nbChildren); + + vector > hIBFF (allo.nbFamilies); + vector > hIBFC (allo.nbChildren); + + // Initialization + for (int i = 0; i < allo.nbChildren; i++){ + isChildIAllocatedToFamilyJ[i].resize(allo.children[i].nbPref); + hIBFC[i].resize(allo.children[i].nbPref); + for (int j = 0; j 0) exp += hIBFC[i][j-1]; + model.addConstr(hIBFC[i][j] == exp); + } + } + + for (int j = 0; j < allo.nbFamilies; j++){ + for (int k = 0; k 0) exp += hIBFF[j][k-1]; + model.addConstr(hIBFF[j][k] == exp); + } + } + + + // Stability constraints + for (int i = 0; i < allo.nbChildren; i++){ + for (int j = 0; j + #include + #include + #include "gurobi_c++.h" + #include "time.h" + #include "Allocation.h" + + float EPSILON = 0.001; + + int manlove(Allocation& allo, int reduction_mode); + +#endif diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile new file mode 100644 index 0000000..0fd0850 --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile @@ -0,0 +1,22 @@ +SYSTEM = x86-64_sles10_4.1 +LIBFORMAT = static_pic + +GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 +CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 +INC = $(GUROBI_DIR)/include/ +CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) +GUROBI_OPTS = -I$(INC) $(CPPLIB) -lpthread -lm -m64 + +CC = g++ +CFLAGS = -O2 -Wall -ansi -pedantic -DIL_STD -std=c++11 +DEBUG = -pg -g -Wall -ansi -pedantic -DIL_STD +OBJECTS = main.o Allocation.o time.o AgentIterator.o Graph.o + +exec : $(OBJECTS) + $(CC) $(CFLAGS) -o YESBIN_1STA_YESMERGED_MAXWT $(OBJECTS) $(GUROBI_OPTS) + +.cpp.o : $< + $(CC) $(CFLAGS) $(GUROBI_OPTS) -c $< -o $@ + +clean : + rm -f $(OBJECTS) YESBIN_1STA_YESMERGED_MAXWT diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.cpp new file mode 100644 index 0000000..4726bdf --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.cpp @@ -0,0 +1,46 @@ +#include "time.h" + +#ifdef _WIN32 +#include +double getWallTime(){ + LARGE_INTEGER time,freq; + if (!QueryPerformanceFrequency(&freq)){ + // Handle error + return 0; + } + if (!QueryPerformanceCounter(&time)){ + // Handle error + return 0; + } + return (double)time.QuadPart / freq.QuadPart; +} +double getCPUTime(){ + FILETIME a,b,c,d; + if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0){ + // Returns total user time. + // Can be tweaked to include kernel times as well. + return + (double)(d.dwLowDateTime | + ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001; + }else{ + // Handle error + return 0; + } +} + +// Posix/Linux +#else +#include +#include +double getWallTime(){ + struct timeval time; + if (gettimeofday(&time,NULL)){ + // Handle error + return 0; + } + return (double)time.tv_sec + (double)time.tv_usec * .000001; +} +double getCPUTime(){ + return (double)clock() / CLOCKS_PER_SEC; +} +#endif \ No newline at end of file diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.h b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.h new file mode 100644 index 0000000..6f1cb4f --- /dev/null +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/time.h @@ -0,0 +1,15 @@ +#ifndef TIME_H + + #define TIME_H + + #ifdef WIN32 + #include + #else + #include + #include + #endif + + double getWallTime(); + double getCPUTime(); + +#endif From 8fbf7473f0fc8fbd333175a08b88a60229aedb8b Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Fri, 6 Sep 2019 17:27:54 +0100 Subject: [PATCH 46/48] Fix path to Gurobi --- SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile | 2 +- SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile index 50c0265..a81bed9 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/makefile @@ -1,7 +1,7 @@ SYSTEM = x86-64_sles10_4.1 LIBFORMAT = static_pic -GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 +GUROBI_DIR = /users/grad/wpette/opt/gurobi752/linux64 CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 INC = $(GUROBI_DIR)/include/ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile index 0fd0850..bd048da 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/makefile @@ -1,7 +1,7 @@ SYSTEM = x86-64_sles10_4.1 LIBFORMAT = static_pic -GUROBI_DIR = /home/wpette/opt/gurobi752/linux64 +GUROBI_DIR = /users/grad/wpette/opt/gurobi752/linux64 CLIB = -L$(GUROBI_DIR)/lib/ -lgurobi75 INC = $(GUROBI_DIR)/include/ CPPLIB = -L$(GUROBI_DIR)/lib/ -lgurobi_c++ $(CLIB) From 9d0493f4a06abaf1472078300b855ac18a699836 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Tue, 10 Sep 2019 09:28:25 +0100 Subject: [PATCH 47/48] Change wt to be sum of border scores, not product --- SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp | 2 +- SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp index 7e5267c..747ec6c 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp @@ -99,7 +99,7 @@ int manlove(Allocation& allo, int mode){ } } } - int score = (allo.nbFamilies - j) * (allo.nbChildren - fam_pref); + int score = (allo.nbFamilies - j) + (allo.nbChildren - fam_pref); objFun += score*isChildIAllocatedToFamilyJ[i][j][k]; } } diff --git a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp index 8a62faa..81d2621 100644 --- a/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp +++ b/SMTI/4_YESBIN_1STA_YESMERGED_MAXWT/main.cpp @@ -98,7 +98,7 @@ int manlove(Allocation& allo, int mode){ } } } - int score = (allo.nbFamilies - j) * (allo.nbChildren - fam_pref); + int score = (allo.nbFamilies - j) + (allo.nbChildren - fam_pref); objFun += score*isChildIAllocatedToFamilyJ[i][j][k]; } } From 1c31853df22e6aec89b278a18dfec8ab0a85b6b7 Mon Sep 17 00:00:00 2001 From: William Pettersson Date: Wed, 11 Sep 2019 10:20:01 +0100 Subject: [PATCH 48/48] Readd missing constraints --- SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp index 747ec6c..c42141b 100644 --- a/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp +++ b/SMTI/3_NOBIN_1STA_YESMERGED_MAXWT/main.cpp @@ -84,6 +84,20 @@ int manlove(Allocation& allo, int mode){ model.update(); + for (int i = 0; i < allo.nbChildren; i++){ + for (int j = 0; j