00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string>
00023 #include <vector>
00024 #include <map>
00025 #include <set>
00026 #include <sstream>
00027 #include <iostream>
00028 #include <fstream>
00029 #include <limits>
00030
00031 #include "driver.hh"
00032 #include "bounds.hh"
00033 #include "mipgen.hh"
00034 #include "euclid.hh"
00035 #include "triplet.hh"
00036 #include "vdiff.hh"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 mipgen::mipgen(const driver& d) : drv(d) {
00049 }
00050
00051
00052
00053
00054
00055
00056 mipgen::~mipgen() {
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 int mipgen::realmod(int a, int b) {
00072 if (a >= 0) return a % b;
00073 else return a + ((-a - 1)/b + 1) * b;
00074 }
00075
00076
00077
00078
00079
00080
00081 void mipgen::formulate() {
00082 constraints = drv.constraints;
00083 modfields();
00084 if (drv.multiply_k) multiply_k();
00085 if (drv.gamma_constraint) append_gamma();
00086 comdenom();
00087 get_indices();
00088 set_bounds();
00089 copy_row_names();
00090 collect_fields();
00091 copy_col_names();
00092
00093
00094 make_matrix(row_names.size(), col_names.size());
00095 fill_matrix();
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 void mipgen::modfields() {
00105 fields.clear();
00106 for (std::vector<constraint>::const_iterator
00107 i = drv.constraints.begin(), e = drv.constraints.end(); i != e; ++i) {
00108 if (i->mod <= 0) continue;
00109 std::ostringstream ss;
00110 ss << "_" << i->name << "mod" << i->mod;
00111 fields.push_back(field());
00112 fields.back().name = ss.str();
00113 fields.back().values.resize(drv.names.size());
00114 fields.back().values[drv.indices.find(i->name)->second] = i->mod;
00115 }
00116 modcount = fields.size();
00117 fields.insert(fields.end(), drv.fields.begin(), drv.fields.end());
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 void mipgen::multiply_k() {
00127 int k = drv.indices.find("k")->second;
00128 for (std::vector<field>::iterator
00129 i = fields.begin() + modcount, e = fields.end(); i != e; ++i) {
00130 for (size_t j = 0; j < drv.names.size(); ++j) {
00131 if (drv.names[j].find("n_") == 0)
00132 i->values[j] *= i->values[k];
00133 }
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 void mipgen::append_gamma() {
00172 int g = drv.indices.find("gamma")->second;
00173 for (std::vector<field>::iterator
00174 i = fields.begin(), e = fields.end(); i != e; ++i) {
00175 rational gamma = i->values[g];
00176 int code;
00177 if (gamma.nom == 0) code = 0;
00178 else if (gamma.nom % gamma.denom == 0) code = 2;
00179 else code = 1;
00180 i->values.push_back(code);
00181 i->values.push_back(code);
00182 }
00183 fields.insert(fields.begin(), field());
00184 fields[0].name = "_gamma";
00185 fields[0].values.resize(drv.names.size());
00186 fields[0].values.push_back(-2);
00187 fields[0].values.push_back(-2*drv.max_order);
00188 ++modcount;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 void mipgen::comdenom() {
00199 for (std::vector<constraint>::iterator
00200 i = constraints.begin(), e = constraints.end(); i != e; ++i) {
00201 int index = drv.indices.find(i->name)->second;
00202 int comdenom = i->goal.denom;
00203 for (std::vector<field>::iterator
00204 j = fields.begin(), ej = fields.end(); j != ej; ++j)
00205 comdenom = lcm(comdenom, j->values[index].denom);
00206 i->goal.set_denom(comdenom);
00207 for (std::vector<field>::iterator
00208 j = fields.begin(), ej = fields.end(); j != ej; ++j)
00209 j->values[index].set_denom(comdenom);
00210 }
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 void mipgen::get_indices() {
00222 indices.clear();
00223 indices.push_back(-1);
00224 if (drv.gamma_constraint) {
00225 indices.push_back(drv.names.size());
00226 indices.push_back(drv.names.size()+1);
00227 }
00228 for (std::vector<constraint>::const_iterator
00229 i = drv.constraints.begin(), e = drv.constraints.end(); i != e; ++i) {
00230 indices.push_back(drv.indices.find(i->name)->second);
00231 }
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 void mipgen::set_bounds() {
00257 row_bounds.clear();
00258 row_bounds.push_back(bounds(drv.min_order, drv.max_order));
00259 if (drv.gamma_constraint) {
00260 row_bounds.push_back(bounds(0, 2*drv.max_order));
00261 row_bounds.back().upper_type = bounds::hint;
00262 row_bounds.push_back(bounds(-2*drv.max_order, 0));
00263 row_bounds.back().lower_type = bounds::hint;
00264 }
00265 for (std::vector<constraint>::iterator
00266 i = constraints.begin(), e = constraints.end(); i != e; ++i)
00267 row_bounds.push_back(bounds(i->goal.nom));
00268
00269 col_bounds.clear();
00270 for (size_t i = 0; i < fields.size(); ++i) {
00271 if (drv.gamma_constraint && i == 0)
00272 col_bounds.push_back(bounds(0, 1));
00273 else if (i < modcount)
00274 col_bounds.push_back(bounds());
00275 else
00276 col_bounds.push_back(bounds(0, bounds::strict,
00277 drv.max_order, bounds::hint));
00278 }
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 void mipgen::copy_row_names() {
00292 row_names.clear();
00293 row_names.push_back("_MaxOrder");
00294 if (drv.gamma_constraint) {
00295 row_names.push_back("_gamma1");
00296 row_names.push_back("_gamma2");
00297 }
00298 for (std::vector<constraint>::const_iterator
00299 i = constraints.begin(), e = constraints.end(); i != e; ++i)
00300 row_names.push_back(i->name);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 void mipgen::collect_fields() {
00327
00328
00329 std::map<std::string, std::vector<const field*> > mf;
00330 for (std::vector<field>::iterator
00331 i = fields.begin() + modcount, e = fields.end(); i != e; ++i)
00332 mf[i->name].push_back(&*i);
00333
00334 std::map<vdiff, int> md;
00335 std::vector<field> of;
00336 std::vector<field> df;
00337 int cnt = 0;
00338 int rows = row_names.size();
00339 for (std::map<std::string, std::vector<const field*> >::iterator
00340 i = mf.begin(), e = mf.end(); i != e; ++i) {
00341 if (i->second.size() == 1) {
00342 of.push_back(*i->second[0]);
00343 continue;
00344 }
00345
00346
00347 std::pair<std::map<vdiff, int>::iterator, bool> ires =
00348 md.insert(std::make_pair(vdiff(i->second), rows));
00349 if (ires.second) {
00350
00351 std::ostringstream ss;
00352 ss << "_d" << ++cnt;
00353 ++rows;
00354 indices.push_back(rows - 1);
00355 row_names.push_back(ss.str());
00356 row_bounds.push_back(bounds(0, bounds::strict,
00357 drv.max_order, bounds::hint));
00358 for (size_t col = 0; col < ires.first->first.num_cols(); ++col) {
00359 std::ostringstream ssi;
00360 ssi << ss.str() << "_" << col+1;
00361 df.push_back(ires.first->first[col]);
00362 df.back().name = ssi.str();
00363 df.back().values.resize(rows);
00364
00365 df.back().values[rows-1] = -1;
00366 }
00367 }
00368 else {
00369
00370 row_bounds[ires.first->second].upper_value += drv.max_order;
00371 }
00372 of.push_back(*i->second[0]);
00373 of.back().values.resize(rows);
00374
00375 of.back().values[ires.first->second] = 1;
00376 }
00377
00378
00379
00380 fields.resize(modcount);
00381 fields.insert(fields.end(), df.begin(), df.end());
00382 fields.insert(fields.end(), of.begin(), of.end());
00383 for (std::vector<field>::iterator
00384 i = fields.begin(), e = fields.end(); i != e; ++i)
00385 i->values.resize(rows);
00386 col_bounds.resize(modcount);
00387 for (std::vector<field>::iterator
00388 i = df.begin(), e = df.end(); i != e; ++i) {
00389 size_t row;
00390 for (row = 0; !i->values[row]; ++row) ;
00391
00392 col_bounds.push_back(bounds(0, bounds::strict,
00393 row_bounds[row].upper_value, bounds::hint));
00394 }
00395 for (std::vector<field>::iterator
00396 i = of.begin(), e = of.end(); i != e; ++i) {
00397
00398 col_bounds.push_back(bounds(0, bounds::strict,
00399 drv.max_order, bounds::hint));
00400 }
00401 modcount += df.size();
00402 }
00403
00404
00405
00406
00407
00408 void mipgen::copy_col_names() {
00409 col_names.clear();
00410 for (std::vector<field>::iterator
00411 i = fields.begin(), e = fields.end(); i != e; ++i)
00412 col_names.push_back(i->name);
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 void mipgen::unique_names(std::vector<std::string>& names) {
00425 std::map<std::string, int> count;
00426 for (std::vector<std::string>::iterator
00427 i = names.begin(), e = names.end(); i != e; ++i) {
00428 std::ostringstream ss;
00429 ss << *i << "_" << ++count[*i];
00430 *i = ss.str();
00431 }
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 void mipgen::make_matrix(size_t rows, size_t cols) {
00446 matrix.clear();
00447 matrix.resize(rows, std::vector<int>(cols));
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 void mipgen::fill_matrix() {
00457 for (size_t col = 0; col < col_names.size(); ++col) {
00458 set_element(0, col, col < modcount ? 0 : 1);
00459 for (size_t row = 1; row < row_names.size(); ++row) {
00460 set_element(row, col, fields[col].values[indices[row]].nom);
00461 }
00462 }
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 void mipgen::set_element(size_t row, size_t col, int val) {
00480 matrix[row][col]=val;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 void mipgen::write(const char* filename) {
00492 if (filename == 0) {
00493 write(std::cout);
00494 }
00495 else {
00496 std::ofstream out(filename);
00497 write(out);
00498 out.close();
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 void mipgen::write(std::ostream& out) {
00512 out << "Name:";
00513 for (std::vector<std::string>::const_iterator
00514 i = drv.names.begin(), e = drv.names.end(); i != e; ++i) {
00515 out << '\t' << *i;
00516 }
00517 out << std::endl << "Goal:";
00518 for (std::vector<std::string>::const_iterator
00519 i = drv.names.begin(), e = drv.names.end(); i != e; ++i) {
00520 out << '\t';
00521 for (std::vector<constraint>::const_iterator
00522 j = drv.constraints.begin(), je = drv.constraints.end();
00523 j != je; ++j) {
00524 if (*i == j->name) {
00525 out << j->goal;
00526 break;
00527 }
00528 }
00529 }
00530 out << std::endl << "Mod:";
00531 for (std::vector<std::string>::const_iterator
00532 i = drv.names.begin(), e = drv.names.end(); i != e; ++i) {
00533 out << '\t';
00534 for (std::vector<constraint>::const_iterator
00535 j = drv.constraints.begin(), je = drv.constraints.end();
00536 j != je; ++j) {
00537 if (*i == j->name) {
00538 if (j->mod) out << j->mod;
00539 break;
00540 }
00541 }
00542 }
00543 out << std::endl;
00544 for (std::vector<field>::const_iterator
00545 i = drv.fields.begin(), e = drv.fields.end(); i != e; ++i) {
00546 out << i->name;
00547 for (size_t j = 0; j < drv.names.size(); ++j)
00548 out << '\t' << i->values[j];
00549 out << std::endl;
00550 }
00551 }