solver/Matrix.h
00001 /*
00002  * Matrix.h
00003  *
00004  *  Created on: Dec 10, 2008
00005  *      Author: tdillig
00006  */
00007 
00008 #include "Equation.h"
00009 #include <unordered_map>
00010 #include <set>
00011 #include <map>
00012 #include <list>
00013 
00014 
00015 typedef  unordered_map<Equation*, bignum, hash<Equation*>, equation_eq> eq_map;
00016 
00017 #ifndef BIG_MATRIX_H_
00018 #define BIG_MATRIX_H_
00019 
00020 #define MATRIX_ASSERT false
00021 
00022 #define REAL (1)
00023 #define IGNORED (1<<1)
00024 
00025 
00026 
00027 class Matrix {
00028 
00029 public:
00030         class iterator
00031         {
00032                 friend class Matrix;
00033         private:
00034                 set<pair<int, Equation*> >::iterator it;
00035                 Matrix & m;
00036                 iterator(set<pair<int, Equation*> >::iterator it, Matrix & m):
00037                         it(it), m(m)
00038                 {
00039 
00040                 }
00041         public:
00042                 pair<Equation* const, bignum> *operator->()
00043                 {
00044                         if(MATRIX_ASSERT) assert(m.equations.count(it->second) > 0);
00045                         return &(*m.equations.find(it->second));
00046                 }
00047                 pair<Equation*, bignum> operator*()
00048                 {
00049                         if(MATRIX_ASSERT) assert(m.equations.count(it->second) > 0);
00050                         return *m.equations.find(it->second);
00051                 }
00052                 const void operator++(int i)
00053                 {
00054                         it++;
00055                         while(it != m.ordered_eqs.end() && m.ignored.count(it->second) >0){
00056                                 it++;
00057                         }
00058 
00059                 }
00060                 bool operator==(iterator  other)
00061                 {
00062                         return (it == other.it);
00063                 }
00064                 bool operator!=(iterator  other)
00065                 {
00066                         return (it != other.it);
00067                 }
00068 
00069         };
00070 
00071 
00072 
00073 private:
00074         vector<string> vars;
00075         vector<string>& original_vars;
00076         map<int, int> old_to_new_vars;
00077         map<int, Equation*> index_to_sub;
00078         vector<int> substitution_order;
00079         set<Equation*> initial_eq;
00080         bool initial;
00081         eq_map equations;
00082         int eq_count;
00083         set<pair<int, Equation*> > ordered_eqs;
00084         map<Equation*, int> eq_to_time;
00085 
00086         /*
00087          * Set of equations we want to ignore (to avoid making copies)
00088          */
00089         set<Equation*> ignored;
00090 
00091         list<pair<Equation*, int> > eq_stack;
00092         map<Equation*, list<bignum> > history;
00093 public:
00094         inline Matrix(vector<string>& vars):vars(vars), original_vars(vars)
00095         {
00096                 initial = true;
00097                 eq_count = 0;
00098         }
00099 
00100         inline Matrix(Matrix & other):vars(other.vars),
00101         original_vars(other.original_vars)
00102         {
00103                 eq_count = 0;
00104                 initial = other.initial;
00105                 iterator it = other.begin();
00106                 for(; it!= other.end(); it++) {
00107                         Equation* eq = it->first->clone();
00108                         insert(eq, it->second);
00109                 }
00110 
00111         }
00112 
00113         inline int num_initial_equations()
00114         {
00115                 return initial_eq.size();
00116         }
00117 
00118 
00119 
00120         inline void end_initial()
00121         {
00122                 initial = false;
00123         }
00124 
00125         inline int num_vars()
00126         {
00127                 return vars.size();
00128         }
00129 
00130         inline bool ignored_set_empty()
00131         {
00132                 return ignored.size() == 0;
00133         }
00134 
00135         inline vector<string>& get_vars()
00136         {
00137                 return vars;
00138         }
00139 
00140         void check_consistency()
00141         {
00142                 set<Equation*> old_eqs;
00143                 eq_map::iterator it = equations.begin();
00144                 for(;it != equations.end();it++){
00145                         if(ignored.count(it->first) >0) continue;
00146                         old_eqs.insert(it->first);
00147                 }
00148 
00149                 set<Equation*> new_eqs;
00150                 set<pair<int, Equation*> >::iterator i2 = ordered_eqs.begin();
00151                 for(; i2 != ordered_eqs.end(); i2++) {
00152                         if(ignored.count(i2->second) >0) continue;
00153                         new_eqs.insert(i2->second);
00154                 }
00155                 if(old_eqs.size() != new_eqs.size()){
00156                         cout << "Assertion failed: OLD EQ SIZE: " << old_eqs.size() <<
00157                          " NEW EQ SIZE: " << new_eqs.size() << endl;
00158                         assert(false);
00159                 }
00160                 assert(old_eqs == new_eqs);
00161         }
00162 
00163         inline iterator begin()
00164         {
00165 
00166                 if(MATRIX_ASSERT) check_consistency();
00167 
00168                 set<pair<int, Equation*> >::iterator it = ordered_eqs.begin();
00169                 while(it != ordered_eqs.end() && ignored.count(it->second) >0){
00170                         it++;
00171                 }
00172                 return iterator(it, *this);
00173         }
00174         inline iterator end()
00175         {
00176                 return iterator(ordered_eqs.end(), *this);
00177         }
00178 
00179         inline int size()
00180         {
00181                 return equations.size()-ignored.size();
00182 
00183         }
00184 
00185         inline void simplify()
00186         {
00187                 map<Equation*, bignum> old_equations;
00188                 old_equations.insert(equations.begin(), equations.end());
00189                 equations.clear();
00190                 ordered_eqs.clear();
00191                 eq_to_time.clear();
00192                 std::set<Equation*> to_delete;
00193                 map<Equation*, bignum>::iterator it = old_equations.begin();
00194                 for(; it!= old_equations.end(); it++)
00195                 {
00196                         Equation* eq = it->first;
00197                         bignum constant = it->second;
00198                         bignum gcd = eq->compute_gcd();
00199                         bignum total_gcd = gcd.compute_gcd(constant);
00200                         if(total_gcd == 0) continue;
00201                         if(total_gcd == 1){
00202                                 insert(eq, constant);
00203                                 continue;
00204                         }
00205                         Equation* new_eq = new Equation(eq->get_cols());
00206                         for(int i=0; i < eq->get_cols(); i++) {
00207                                 new_eq->set(i, eq->get(i)/total_gcd);
00208                         }
00209                         insert(new_eq, constant/total_gcd);
00210                         to_delete.insert(eq);
00211                 }
00212                 set<Equation*>::iterator it2 = to_delete.begin();
00213                 for(; it2!= to_delete.end(); it2++) {
00214                         delete *it2;
00215                 }
00216                 if(MATRIX_ASSERT) check_consistency();
00217         }
00218 
00219         inline void insert(Equation*& eq, bignum constant)
00220         {
00221                 if(eq_stack.size() >0){
00222                         push_equation_internal(eq, constant, false);
00223                         return;
00224                 }
00225                 insert_internal(eq, constant);
00226         }
00227 
00228         inline void insert_internal(Equation*& eq, bignum constant)
00229         {
00230                 if(MATRIX_ASSERT) assert(eq->get_cols() == (int)vars.size());
00231                 if(equations.count(eq) == 0){
00232                         if(MATRIX_ASSERT){
00233                                 assert(eq_to_time.count(eq) == 0);
00234                         }
00235                         int time_stamp = eq_count++;
00236                         equations[eq] = constant;
00237                         ordered_eqs.insert(pair<int, Equation*>(time_stamp, eq));
00238                         eq_to_time[eq] = time_stamp;
00239                         if(initial) initial_eq.insert(eq);
00240                 }
00241                 else {
00242                         Equation* old_eq = equations.find(eq)->first;
00243                         if(MATRIX_ASSERT){
00244                                 assert(eq_to_time.count(old_eq) > 0);
00245                         }
00246                         bignum old_c = equations[old_eq];
00247                         if(constant<old_c){
00248                                 if(MATRIX_ASSERT){
00249                                         assert(eq_to_time.count(old_eq) > 0);
00250                                 }
00251                                 equations[old_eq] = constant;
00252                                 if(initial) initial_eq.insert(old_eq);
00253 
00254                         }
00255                         delete eq;
00256                 }
00257                 eq = NULL;
00258         }
00259 
00260         inline bool is_initial(Equation* e)
00261         {
00262                 return initial_eq.count(e) !=0;
00263         }
00264 
00265 
00266 
00267         inline void push_equation(Equation* eq, bignum constant)
00268         {
00269                 push_equation_internal(eq, constant, true);
00270         }
00271 
00272         inline void push_equation_internal(Equation* eq, bignum constant, bool real)
00273         {
00274                 //cout << "Push--> " << (real ? "real" : "not real" ) << endl;
00275                 int attribute = 0;
00276                 if(real) attribute |= REAL;
00277                 Equation* existing = get(eq);
00278                 if(existing == NULL) {
00279                         if(MATRIX_ASSERT){
00280                                 assert(eq_to_time.count(eq) == 0);
00281                         }
00282                         int time_stamp = eq_count++;
00283                         eq_to_time[eq] = time_stamp;
00284                         ordered_eqs.insert(pair<int, Equation*>(time_stamp, eq));
00285 
00286                         equations[eq] = constant;
00287                         eq_stack.push_front(pair<Equation*, bool>(eq, attribute));
00288                         return;
00289                 }
00290 
00291                 if(MATRIX_ASSERT){
00292                         assert(eq_to_time.count(existing) > 0);
00293                 }
00294                 if(ignored.count(existing) > 0){
00295                         attribute |= IGNORED;
00296                         ignored.erase(existing);
00297                 }
00298                 bignum old_c = get_constant(eq);
00299                 delete eq;
00300                 if(old_c <= constant){
00301                         assert(false);
00302                         eq_stack.push_front(pair<Equation*, bool>((Equation*)NULL, attribute));
00303                         return;
00304                 }
00305                 equations[existing] = constant;
00306                 history[existing].push_front(old_c);
00307                 eq_stack.push_front(pair<Equation*, bool>(existing, attribute));
00308         }
00309 
00310         inline void pop_equation()
00311         {
00312                 while(true)
00313                 {
00314                         Equation* eq = eq_stack.front().first;
00315                         int attribute = eq_stack.front().second;
00316                         bool real = attribute & REAL;
00317                         bool is_ignored = attribute & IGNORED;
00318                         //cout << "Pop--> " << (real ? "real" : "not real" ) << endl;
00319                         eq_stack.pop_front();
00320                         if(eq == NULL){
00321                                 if(real) return;
00322                                 continue;
00323                         }
00324 
00325                         if(history.count(eq) == 0) {
00326                                 if(MATRIX_ASSERT) assert(equations.count(eq));
00327                                 if(MATRIX_ASSERT) {
00328                                         assert(eq_to_time.count(eq) > 0);
00329                                 }
00330                                 int old_time_stamp = eq_to_time[eq];
00331                                 pair<int, Equation*> p(old_time_stamp, eq);
00332                                 if(MATRIX_ASSERT) assert(ordered_eqs.count(p) > 0);
00333                                 ordered_eqs.erase(p);
00334                                 eq_to_time.erase(eq);
00335                                 assert(!is_ignored);
00336                                 assert(equations.count(eq) >0);
00337                                 equations.erase(eq);
00338                                 delete eq;
00339                                 if(real) return;
00340                                 continue;
00341                         }
00342                         bignum old_c = history[eq].front();
00343                         history[eq].pop_front();
00344                         if(history[eq].size() == 0)
00345                                 history.erase(eq);
00346                         equations[eq] = old_c;
00347                         if(is_ignored) ignored.insert(eq);
00348                         if(real) return;
00349                 }
00350         }
00351 
00352         inline void set_value(Equation* eq, bignum constant)
00353         {
00354                 if(MATRIX_ASSERT) assert(contains(eq));
00355                 equations[eq] = constant;
00356         }
00357 
00358         inline bool contains(Equation* eq)
00359         {
00360                 return equations.count(eq)>0;
00361         }
00362 
00363         inline bool contains(Equation* eq, bignum constant)
00364         {
00365                 if(!contains(eq)) return false;
00366                 return equations[eq] == constant;
00367         }
00368 
00369         inline Equation* get(Equation* eq)
00370         {
00371                 if(!contains(eq)) return NULL;
00372                 return equations.find(eq)->first;
00373         }
00374 
00375         inline bool contains_negative(Equation* eq, bignum constant)
00376         {
00377                 Equation neg_eq(vars.size());
00378                 for(int c=0; c<eq->get_cols(); c++)
00379                 {
00380                         neg_eq.set(c, -eq->get(c));
00381                 }
00382                 if(!contains(&neg_eq)) return false;
00383                 return contains(&neg_eq, -constant);
00384         }
00385 
00386         inline Equation* get_negative(Equation* eq, bignum constant)
00387         {
00388                 Equation neg_eq(vars.size());
00389                 for(int c=0; c<eq->get_cols(); c++)
00390                 {
00391                         neg_eq.set(c, -eq->get(c));
00392                 }
00393                 if(!contains(&neg_eq)) return NULL;
00394                 Equation* res = equations.find(&neg_eq)->first;
00395                 bignum c2 = equations.find(&neg_eq)->second;
00396                 if(c2 == -constant) return res;
00397                 return NULL;
00398         }
00399 
00400         /*
00401          * Is adding eq<=constant to the matrix redundant?
00402          */
00403         inline bool is_redundant(Equation* eq, bignum constant)
00404         {
00405                 if(equations.count(eq) == 0) return false;
00406                 bignum existing_const = equations[eq];
00407                 return (existing_const <= constant);
00408         }
00409 
00410         inline bignum get_constant(Equation* eq)
00411         {
00412                 if(MATRIX_ASSERT) assert(equations.count(eq) > 0);
00413                 return equations[eq];
00414         }
00415 
00416         inline bool remove(Equation* eq)
00417         {
00418 
00419                 if(!contains(eq)) return false;
00420                 Equation* old_eq = equations.find(eq)->first;
00421                 assert(ignored.count(old_eq)==0);
00422                 if(MATRIX_ASSERT) assert(equations.count(old_eq)>0);
00423                 equations.erase(old_eq);
00424                 if(MATRIX_ASSERT){
00425                         assert(eq_to_time[old_eq] > 0);
00426                 }
00427                 int old_time_stamp = eq_to_time[old_eq];
00428                 pair<int, Equation*> p(old_time_stamp, old_eq);
00429                 if(MATRIX_ASSERT) {
00430                         assert(ordered_eqs.count(p) > 0);
00431                 }
00432                 ordered_eqs.erase(p);
00433                 eq_to_time.erase(old_eq);
00434                 delete old_eq;
00435                 return true;
00436         }
00437 
00438         inline bool remove(Equation* eq, bignum constant)
00439         {
00440                 if(!contains(eq)) return false;
00441                 Equation* old_eq = equations.find(eq)->first;
00442                 assert(ignored.count(old_eq)==0);
00443                 if(equations.find(eq)->second != constant) return false;
00444                 equations.erase(old_eq);
00445                 if(MATRIX_ASSERT){
00446                         assert(eq_to_time[old_eq] > 0);
00447                 }
00448                 int old_time_stamp = eq_to_time[old_eq];
00449                 pair<int, Equation*> p(old_time_stamp, old_eq);
00450                 if(MATRIX_ASSERT) assert(ordered_eqs.count(p) > 0);
00451                 ordered_eqs.erase(p);
00452                 eq_to_time.erase(old_eq);
00453                 delete old_eq;
00454                 return true;
00455         }
00456 
00457         string to_string()
00458         {
00459                 string res;
00460                 for(unsigned int i=0; i < vars.size(); i++) {
00461                         res+= vars[i] + "\t";
00462                 }
00463                 res+= "[c]\n";
00464                 eq_map::iterator it = equations.begin();
00465                 for(; it!= equations.end(); it++) {
00466                         res+=it->first->to_string();
00467                         res+=it->second.to_string();
00468                         res+="\n";
00469                 }
00470                 return res;
00471         }
00472 
00473         friend ostream& operator <<(ostream &os,const Matrix &obj);
00474 
00475 
00476         inline ~Matrix()
00477         {
00478 
00479                 eq_map::iterator it = equations.begin();
00480                 set<Equation*> to_delete;
00481                 for(; it != equations.end(); it++) {
00482                         to_delete.insert(it->first);
00483                 }
00484                 set<Equation*>::iterator it2 = to_delete.begin();
00485                 for(; it2 != to_delete.end(); it2++) {
00486                         delete *it2;
00487                 }
00488 
00489                 map<int, Equation*>::iterator it3 = index_to_sub.begin();
00490                 for(; it3!= index_to_sub.end(); it3++) {
00491                         delete it3->second;
00492                 }
00493         }
00494 
00495         //-------------------------------------------------------------
00496         inline void make_diophantine()
00497         {
00498                 Matrix::iterator it = begin();
00499                 for(; it!= end(); it++)
00500                 {
00501                         Equation* eq= it->first;
00502                         bignum constant = it->second;
00503                         bignum coef_gcd = eq->compute_gcd();
00504                         if(coef_gcd == 0 || constant.divisible(coef_gcd)) continue;
00505                         bignum quotient = constant/coef_gcd;
00506                         if(constant<0) quotient-=1;
00507                         bignum new_c = coef_gcd*quotient;
00508                         set_value(eq, new_c);
00509 
00510                 }
00511                 simplify();
00512         }
00513 
00514 
00515 
00516         /*
00517          * If there is an inequality a1x1 + ... + anxn <= b as well as
00518          * a1x1 + ... + anxn >= b, propagate this as an equality if there exists
00519          * some a_i with coefficient +-1.
00520          */
00521         void propagate_equalities(set< set< pair<Equation*, bignum> > >*
00522                         neq_constraints = NULL)
00523         {
00524 
00525                 set<int> neq_vars;
00526                 if(neq_constraints != NULL) {
00527                         set<set<pair<Equation*, bignum> > >::iterator it = neq_constraints->begin();
00528                         for(; it!= neq_constraints->end(); it++) {
00529                                 set<pair<Equation*, bignum> >::iterator it2= it->begin();
00530                                 for(; it2!= it->end(); it2++)
00531                                 {
00532                                         Equation* e = it2->first;
00533 
00534 
00535                                         for(int i=0;i < e->num_entries(); i++) {
00536                                                 if(e->get(i) != 0) neq_vars.insert(i);
00537                                         }
00538                                 }
00539 
00540 
00541                         }
00542                 }
00543 
00544                 while(true)
00545                 {
00546                         Equation* eq_old = NULL;
00547                         Equation* neq_old = NULL;
00548                         iterator it = begin();
00549                         int eliminate_index = -1; // index of var to be eliminated
00550                         Equation* sub = NULL;
00551                         bool progress = false;
00552                         for(; it!= end(); it++)
00553                         {
00554                                 eq_old = it->first;
00555                                 bignum constant = it->second;
00556                                 /*
00557                                  * Check if this inequality actually appears as an
00558                                  * equality.
00559                                  */
00560                                 neq_old = get_negative(eq_old, constant);
00561                                 if(neq_old == NULL) continue;
00562 
00563                                 /*
00564                                  * Check if any coefficient is +-1.
00565                                  */
00566                                 bool remove = false;
00567                                 for(int c=0; c<eq_old->num_entries(); c++)
00568                                 {
00569                                         if((eq_old->get(c) == 1 || eq_old->get(c) == -1) &&
00570                                                 index_to_sub.count(c) == 0 && neq_vars.count(c) == 0 &&
00571                                                 var_occurs(c, eq_old, neq_old)){
00572                                                 remove = true;
00573                                                 eliminate_index = c;
00574 
00575                                                 /*
00576                                                  * Figure out the correct substitution for the
00577                                                  * variable to be eliminated.
00578                                                  */
00579                                                 sub = new Equation(eq_old->num_entries()+1);
00580                                                 if(eq_old->get(c) == 1)
00581                                                 {
00582                                                         for(int i=0; i<eq_old->num_entries(); i++){
00583                                                                 if(i == c)
00584                                                                         sub->set(i, 0);
00585                                                                 else
00586                                                                         sub->set(i, -eq_old->get(i));
00587                                                         }
00588                                                         sub->set(eq_old->num_entries(), constant);
00589                                                 }
00590                                                 else
00591                                                 {
00592                                                         for(int i=0; i<eq_old->num_entries(); i++){
00593                                                         if(i == c)
00594                                                                 sub->set(i, 0);
00595                                                         else
00596                                                                 sub->set(i, eq_old->get(i));
00597                                                 }
00598                                                 sub->set(eq_old->num_entries(), -constant);
00599                                                 }
00600                                                 index_to_sub[c] = sub;
00601                                                 substitution_order.push_back(c);
00602 
00603                                                 break;
00604                                         }
00605                                 }
00606                                 if(!remove) continue;
00607                                 progress = true;
00608                                 break;
00609                         }
00610                         if(!progress) break;
00611                         remove(eq_old);
00612                         remove(neq_old);
00613                         eliminate_var(eliminate_index, sub);
00614                 }
00615                 //update mappings
00616                 int old_size = num_vars();
00617                 vars.clear();
00618                 int cur = 0;
00619 
00620 
00621                 for(int i=0; i < old_size; i++) {
00622                         if(index_to_sub.count(i) == 0){
00623                                 vars.push_back(original_vars[i]);
00624                                 old_to_new_vars[i] = cur++;
00625 
00626                         }
00627                         else {
00628                                 old_to_new_vars[i] = -1;
00629 
00630                         }
00631                 }
00632                 map<Equation*, bignum> temp_map;
00633                 iterator it = begin();
00634                 for(; it!= end(); it++) {
00635                         temp_map[it->first] = it->second;
00636                 }
00637 
00638                 equations.clear();
00639                 ordered_eqs.clear();
00640                 eq_to_time.clear();
00641                 int new_eq_size = vars.size();
00642 
00643 
00644 
00645                 map<Equation*, bignum>::iterator it2 = temp_map.begin();
00646                 for(; it2!= temp_map.end(); it2++) {
00647                         Equation* eq = it2->first;
00648                         bignum constant = it2->second;
00649                         Equation* new_eq = new Equation(new_eq_size);
00650                         int cur = 0;
00651 
00652 
00653                         for(int i=0; i < eq->num_entries(); i++) {
00654                                 if(old_to_new_vars[i]==-1){
00655                                         continue;
00656                                 }
00657 
00658                                 new_eq->set(cur++, eq->get(i));
00659                         }
00660 
00661                         insert(new_eq, constant);
00662                         delete eq;
00663                 }
00664 
00665                 if(neq_constraints != NULL) {
00666                         set<int> cols_to_remove;
00667                         cols_to_remove.insert(substitution_order.begin(),
00668                                         substitution_order.end());
00669 
00670 
00671 
00672 
00673 
00674                         set< set< pair<Equation*, bignum> > > result_neq;
00675                         set< set< pair<Equation*, bignum> > >::iterator it =
00676                                         neq_constraints->begin();
00677                         for(; it!= neq_constraints->end(); it++) {
00678                                 set<pair<Equation*, bignum> >::iterator it2 = it->begin();
00679                                 set<pair<Equation*, bignum> > cur_disjunctive_ineq;
00680                                 for(; it2!= it->end(); it2++)
00681                                 {
00682                                         Equation* old_eq =it2->first;
00683                                         //assert(old_eq->get_cols() == old_size);
00684                                         Equation* new_eq = new Equation(vars.size());
00685 
00686                                         int cur_index = 0;
00687 
00688 
00689                                         for(int i=0; i<old_eq->num_entries(); i++) {
00690                                                 if(cols_to_remove.count(i) > 0) continue;
00691                                                 new_eq->set(cur_index, old_eq->get(i));
00692                                                 cur_index++;
00693                                         }
00694                                         cur_disjunctive_ineq.insert(pair<Equation*, bignum>(new_eq,
00695                                                         it2->second));
00696                                         delete old_eq;
00697                                 }
00698 
00699 
00700                                 result_neq.insert(cur_disjunctive_ineq);
00701 
00702                         }
00703 
00704                         *neq_constraints = result_neq;
00705                 }
00706                 if(MATRIX_ASSERT) check_consistency();
00707         }
00708 
00709         inline void adjust_assignments(vector<bigfraction> & assignments,
00710                         vector<bignum>& final_assignments)
00711         {
00712                 final_assignments.reserve(old_to_new_vars.size());
00713                 map<int, bigfraction> res_assignments;
00714                 map<int, int>::iterator it = old_to_new_vars.begin();
00715                 for(; it != old_to_new_vars.end(); it++)
00716                 {
00717                         int old_index = it->first;
00718                         int new_index = it->second;
00719                         if(new_index == -1) continue; // was eliminated
00720                         res_assignments[old_index] = assignments[new_index];
00721                 }
00722 
00723                 for(int i=substitution_order.size()-1; i>=0; i--)
00724                 {
00725                         int old_index = substitution_order[i];
00726                         Equation* sub = index_to_sub[old_index];
00727                         int num_entries = sub->num_entries();
00728                         bigfraction cur = 0;
00729                         for(int j=0; j<num_entries-1; j++)
00730                         {
00731                                 bigfraction coef = sub->get(j);
00732                                 if(coef == 0) continue;
00733                                 assert(res_assignments.count(j) != 0);
00734                                 cur += coef*res_assignments[j];
00735                         }
00736 
00737                         cur += sub->get(num_entries-1); // add the constant
00738                         res_assignments[old_index] = cur;
00739 
00740                 }
00741 
00742                 map<int, bigfraction>::iterator it2 = res_assignments.begin();
00743                 for(; it2!= res_assignments.end(); it2++) {
00744                         bigfraction& f = it2->second;
00745                         bignum n = f.get_numerator();
00746                         bignum d = f.get_denominator();
00747                         if(d!=1) {
00748                                 cerr << "n: " << n << " d: " << d << endl;
00749                                 assert(false);
00750                         }
00751                         final_assignments.push_back(n);
00752                 }
00753 
00754         }
00755 
00756         inline bool var_occurs(int index, Equation* eq1, Equation* eq2)
00757         {
00758                 iterator it = begin();
00759                 for(; it!= end(); it++)
00760                 {
00761                         Equation* eq = it->first;
00762                         if(eq == eq1 || eq == eq2) continue;
00763                         if(eq->get(index) != 0) return true;
00764                 }
00765                 return false;
00766         }
00767 
00768 
00769         void eliminate_var(int i, Equation* sub)
00770         {
00771 
00772                 map<Equation*, bignum> temp_map;
00773                 iterator it = begin();
00774                 for(; it!= end(); it++) {
00775                         temp_map[it->first] = it->second;
00776                 }
00777                 equations.clear();
00778                 ordered_eqs.clear();
00779                 eq_to_time.clear();
00780 
00781                 map<Equation*, bignum>::iterator it2 = temp_map.begin();
00782                 for(; it2!= temp_map.end(); it2++) {
00783                         Equation* eq = it2->first;
00784                         bignum constant = it2->second;
00785                         bignum factor = eq->get(i);
00786                         if(factor == 0){
00787                                 insert(eq, constant);
00788                                 continue;
00789                         }
00790                         for(int c=0; c<eq->num_entries(); c++) {
00791                                 bignum val = 0;
00792                                 if(c != i)
00793                                         val = eq->get(c);
00794                                 eq->set(c, val+sub->get(c)*factor);
00795                         }
00796                         constant-=sub->get(eq->num_entries())*factor;
00797                         insert(eq, constant);
00798                 }
00799 
00800                 if(MATRIX_ASSERT) check_consistency();
00801         }
00802 
00803 
00804         inline void mark_current_facets(vector<bigfraction>& assignments)
00805         {
00806                 eq_map::iterator it = equations.begin();
00807                 for(; it!= equations.end(); it++)
00808                 {
00809                         Equation* eq = it->first;
00810                         bignum constant = it->second;
00811                         bigfraction lhs = eq->evaluate(assignments);
00812                         if(lhs != constant) ignored.insert(eq);
00813                 }
00814         }
00815 
00816         inline void clear_current_facets()
00817         {
00818                 ignored.clear();
00819         }
00820 };
00821 
00822 #endif /* BIG_MATRIX_H_ */