00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cstdlib>
00022 #include <cmath>
00023 #include <cassert>
00024 #include <algorithm>
00025 #include <iostream>
00026 #include <fstream>
00027 #include <vector>
00028 #include <set>
00029 #include <map>
00030
00031 #include "loader.h"
00032
00033 using namespace Udine;
00034
00035 void checkFile(const char *path) {
00036 try {
00037 std::ifstream input(path);
00038 input.seekg(0, std::ios::end);
00039 if (input.tellg() < 1) {
00040 std::cerr << "Loader: The data file " << path << " has zero lenght" << std::endl;
00041 std::abort();
00042 }
00043 input.close();
00044 } catch (...) {
00045 std::cerr << "Loader: There was an error opening the data file " << path << std::endl;
00046 std::abort();
00047 }
00048 }
00049
00050
00051 std::istream& operator>>(std::istream &is, Course &c) {
00052 return is >> c.name >> c.teacher >> c.lectures >> c.minWorkingDays >> c.students;
00053 }
00054
00055
00056 void Instance::load(const char *filename) {
00057 try {
00058 std::ifstream file;
00059 file.open(filename, std::ifstream::in);
00060
00061 std::string forget; int i;
00062 std::map< std::string, int, std::less<std::string> > cnames;
00063
00064 std::string iname;
00065 int courseCnt, eventCnt, roomCnt, dayCnt, curriculumCnt, constraintCnt;
00066
00067
00068 file >> forget >> iname;
00069 file >> forget >> courseCnt; eventCnt = 0;
00070 file >> forget >> roomCnt;
00071 file >> forget >> dayCnt;
00072 file >> forget >> periodsPerDay;
00073 file >> forget >> curriculumCnt;
00074 file >> forget >> constraintCnt;
00075
00076 periods = dayCnt * periodsPerDay;
00077 days = dayCnt;
00078 checks = periodsPerDay;
00079
00080 std::cout << "Loader: Instance " << iname << " (" << filename << ")"<< std::endl;
00081
00082
00083 file >> forget;
00084 for (i = 0; i < courseCnt; i++) {
00085 Course c;
00086 assert(file.good());
00087 file >> c;
00088 cnames[c.name] = i;
00089 eventCnt += c.lectures;
00090 courses.push_back(c);
00091 }
00092
00093
00094 file >> forget;
00095 for (i = 0; i < roomCnt; i++) {
00096 Room room;
00097 assert(file.good());
00098 file >> room.name >> room.capacity;
00099 rooms.push_back(room);
00100 }
00101 RoomCapacityLess capacityLess;
00102 std::sort(rooms.begin(), rooms.end(), capacityLess);
00103
00104 genMRoomsAggregates();
00105
00106
00107 file >> forget;
00108 for (i = 0; i < curriculumCnt; i++) {
00109 Curriculum u; int ccount;
00110 file >> u.name >> ccount;
00111 for (int j = 0; j < ccount; j++) {
00112 std::string s;
00113 assert(file.good());
00114 file >> s;
00115 assert(cnames.find(s) != cnames.end());
00116 u.courseIds.push_back(cnames.find(s)->second);
00117 }
00118 curricula.push_back(u);
00119 }
00120 origCurricula = curricula.size();
00121
00122
00123 file >> forget;
00124 for (i = 0; i < constraintCnt; i++) {
00125 std::string cname; int day; int period;
00126 assert(file.good());
00127 file >> cname >> day >> period;
00128 Restriction r;
00129 assert(cnames.find(cname) != cnames.end());
00130 r.courseId = cnames.find(cname)->second;
00131 r.period = day * periodsPerDay + period;
00132 restrict.push_back(r);
00133 }
00134
00135
00136 typedef std::map< std::string, std::vector<int>, std::less<std::string> > s2veci;
00137 s2veci tnames;
00138 std::vector<Course>::iterator it = courses.begin();
00139 for (i = 0; it != courses.end(); it++, i++) {
00140 if (tnames.find(it->teacher) == tnames.end()) {
00141 std::vector<int> teaches;
00142 teaches.push_back(i);
00143 tnames[it->teacher] = teaches;
00144 } else {
00145 tnames.find(it->teacher)->second.push_back(i);
00146 }
00147 }
00148
00149 s2veci::iterator mapit = tnames.begin();
00150 for (; mapit != tnames.end(); mapit++) {
00151 if (mapit->second.size() > 1) {
00152
00153 Curriculum c;
00154 c.courseIds = mapit->second;
00155 c.name = mapit->first;
00156 curricula.push_back(c);
00157 }
00158 }
00159
00160 if (file.bad()) {
00161 std::cout << "Loader: Instance incomplete!" << std::endl;
00162 abort();
00163 } else {
00164 std::cout << "Loader: " << courseCnt << " courses, ";
00165 std::cout << eventCnt << " events, and ";
00166 std::cout << curriculumCnt << " curricula" << std::endl;
00167 }
00168
00169 file.close();
00170
00171 genPatterns(periodsPerDay);
00172
00173 } catch (std::exception &e) {
00174 std::cerr << "Loader: There was an error reading the instance!" << std::endl;
00175 std::cerr << "Exception says: " << e.what() << std::endl;
00176 abort();
00177 }
00178 }
00179
00180
00181
00182
00183 void Instance::genPatterns(int toAdd, int rhs, std::vector<int> pat) {
00184
00185 const int minus = -1;
00186 const int plus = 1;
00187
00188
00189 if (toAdd > 0) {
00190 pat.push_back(minus);
00191 genPatterns(toAdd - 1, rhs, pat);
00192 pat.pop_back();
00193 pat.push_back(plus);
00194 genPatterns(toAdd - 1, rhs + plus, pat);
00195 return;
00196 }
00197
00198
00199 int penalty = 0;
00200 int last = pat.size() - 1;
00201 if (pat.size() < 3) return;
00202
00203 if (pat[0] == plus && pat[1] == minus) penalty += 1;
00204 if (pat[last] == plus && pat[last - 1] == minus) penalty += 1;
00205
00206 for (int i = 0; i < pat.size() - 2; i++)
00207 if (pat[i] == minus && pat[i + 1] == plus && pat[i + 2] == minus)
00208 penalty += 1;
00209
00210
00211 if (penalty > 0) {
00212 Pattern p;
00213 p.coefs = pat;
00214 p.penalty = penalty;
00215 p.rhs = rhs;
00216 patterns.push_back(p);
00217 }
00218 }
00219
00220
00221 bool RoomCapacityLess::operator()(const Room &x, const Room &y ) {
00222 if (x.capacity != y.capacity) return (x.capacity > y.capacity);
00223 return (x.name > y.name);
00224 }
00225
00226
00227
00228
00229 void Instance::genMRoomsAggregates() {
00230
00231 for (int type = 0; type < ModelTypeLen; type++) {
00232
00233 switch(type) {
00234
00235 case Monolithic:
00236 case FixPeriod:
00237 {
00238 for (int i = 0; i < rooms.size(); i++) {
00239 MRoom room;
00240 room.multiplicity = 1;
00241 room.perEventCapacity = rooms.at(i).capacity;
00242 room.rooms.push_back(rooms.at(i));
00243 mRooms.at(type).push_back(room);
00244 }
00245 }
00246 break;
00247
00248 case FixDay:
00249 {
00250 MRoom mRoom;
00251 for (int i = 0; i < rooms.size() - 1; i++) {
00252 mRoom.multiplicity += 1;
00253 mRoom.perEventCapacity = std::max(mRoom.perEventCapacity, rooms.at(i).capacity);
00254 mRoom.rooms.push_back(rooms.at(i));
00255 if (rooms.at(i).capacity != rooms.at(i + 1).capacity) {
00256 mRooms.at(type).push_back(mRoom);
00257 mRoom.rooms.clear();
00258 mRoom.multiplicity = 0;
00259 mRoom.perEventCapacity = rooms.at(i + 1).capacity;
00260 }
00261 }
00262 mRoom.multiplicity += 1;
00263 mRoom.perEventCapacity = rooms.at(rooms.size() - 1).capacity;
00264 mRoom.rooms.push_back(rooms.at(rooms.size() - 1));
00265 mRooms.at(type).push_back(mRoom);
00266 }
00267 break;
00268
00269 case Surface:
00270 {
00271 MRoom large, small;
00272 int i;
00273
00274 std::vector<int> distinct;
00275 distinct.push_back(rooms.at(0).capacity);
00276 for (i = 1; i < rooms.size(); i++) {
00277 if (rooms.at(i - 1).capacity != rooms.at(i).capacity)
00278 distinct.push_back(rooms.at(i).capacity);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 float splitAt = distinct.at(floor((float)(distinct.size() / 2))) + 1;
00294
00295 for (i = 0; i < rooms.size(); i++) {
00296 if (rooms.at(i).capacity < splitAt) {
00297 small.multiplicity += 1;
00298 small.perEventCapacity = std::max(small.perEventCapacity, rooms.at(i).capacity);
00299 small.rooms.push_back(rooms.at(i));
00300 } else {
00301 large.multiplicity += 1;
00302 large.perEventCapacity = std::max(large.perEventCapacity, rooms.at(i).capacity);
00303 large.rooms.push_back(rooms.at(i));
00304 }
00305 }
00306 std::cout << "The surface mRooms have capacity " << small.perEventCapacity;
00307 std::cout << " and " << large.perEventCapacity << std::endl;
00308 mRooms.at(type).push_back(small);
00309 mRooms.at(type).push_back(large);
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 }
00321 break;
00322 }
00323 }
00324 }