PPL  0.12.1
PIP_Problem.cc
Go to the documentation of this file.
00001 /* PIP_Problem class implementation: non-inline functions.
00002    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
00003    Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com)
00004 
00005 This file is part of the Parma Polyhedra Library (PPL).
00006 
00007 The PPL is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 The PPL is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software Foundation,
00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
00020 
00021 For the most up-to-date information see the Parma Polyhedra Library
00022 site: http://bugseng.com/products/ppl/ . */
00023 
00024 #include "ppl-config.h"
00025 #include "PIP_Problem.defs.hh"
00026 #include "PIP_Tree.defs.hh"
00027 
00028 namespace PPL = Parma_Polyhedra_Library;
00029 
00031 std::ostream&
00032 PPL::IO_Operators::operator<<(std::ostream& s, const PIP_Problem& pip) {
00033   s << "Space dimension: " << pip.space_dimension();
00034   s << "\nConstraints:";
00035   for (PIP_Problem::const_iterator i = pip.constraints_begin(),
00036          i_end = pip.constraints_end(); i != i_end; ++i)
00037     s << "\n" << *i;
00038   s << "\nProblem parameters: " << pip.parameter_space_dimensions();
00039   if (pip.get_big_parameter_dimension() == not_a_dimension())
00040     s << "\nNo big-parameter set.\n";
00041   else
00042     s << "\nBig-parameter: " << Variable(pip.get_big_parameter_dimension());
00043   s << "\n";
00044   return s;
00045 }
00046 
00047 PPL::PIP_Problem::PIP_Problem(const dimension_type dim)
00048   : external_space_dim(dim),
00049     internal_space_dim(0),
00050     status(PARTIALLY_SATISFIABLE),
00051     current_solution(0),
00052     input_cs(),
00053     first_pending_constraint(0),
00054     parameters(),
00055     initial_context(),
00056     big_parameter_dimension(not_a_dimension()) {
00057   // Check for space dimension overflow.
00058   if (dim > max_space_dimension())
00059     throw std::length_error("PPL::PIP_Problem::PIP_Problem(dim):\n"
00060                             "dim exceeds the maximum allowed "
00061                             "space dimension.");
00062   control_parameters_init();
00063   PPL_ASSERT(OK());
00064 }
00065 
00066 PPL::PIP_Problem::PIP_Problem(const PIP_Problem &y)
00067   : external_space_dim(y.external_space_dim),
00068     internal_space_dim(y.internal_space_dim),
00069     status(y.status),
00070     current_solution(0),
00071     input_cs(y.input_cs),
00072     first_pending_constraint(y.first_pending_constraint),
00073     parameters(y.parameters),
00074     initial_context(y.initial_context),
00075     big_parameter_dimension(y.big_parameter_dimension) {
00076   if (y.current_solution != 0) {
00077     current_solution = y.current_solution->clone();
00078     current_solution->set_owner(this);
00079   }
00080   control_parameters_copy(y);
00081   PPL_ASSERT(OK());
00082 }
00083 
00084 PPL::PIP_Problem::~PIP_Problem() {
00085   delete current_solution;
00086 }
00087 
00088 void
00089 PPL::PIP_Problem::control_parameters_init() {
00090   control_parameters[CUTTING_STRATEGY] = CUTTING_STRATEGY_FIRST;
00091   control_parameters[PIVOT_ROW_STRATEGY] = PIVOT_ROW_STRATEGY_FIRST;
00092 }
00093 
00094 void
00095 PPL::PIP_Problem::control_parameters_copy(const PIP_Problem& y) {
00096   for (dimension_type i = CONTROL_PARAMETER_NAME_SIZE; i-- > 0; )
00097     control_parameters[i] = y.control_parameters[i];
00098 }
00099 
00100 PPL::PIP_Problem_Status
00101 PPL::PIP_Problem::solve() const {
00102   switch (status) {
00103 
00104   case UNSATISFIABLE:
00105     PPL_ASSERT(OK());
00106     return UNFEASIBLE_PIP_PROBLEM;
00107 
00108   case OPTIMIZED:
00109     PPL_ASSERT(OK());
00110     return OPTIMIZED_PIP_PROBLEM;
00111 
00112   case PARTIALLY_SATISFIABLE:
00113     {
00114       PIP_Problem& x = const_cast<PIP_Problem&>(*this);
00115       // Allocate PIP solution tree root, if needed.
00116       if (current_solution == 0)
00117         x.current_solution = new PIP_Solution_Node(this);
00118 
00119       // Properly resize context matrix.
00120       const dimension_type new_num_cols = parameters.size() + 1;
00121       const dimension_type old_num_cols = initial_context.num_columns();
00122       if (old_num_cols < new_num_cols)
00123         x.initial_context.add_zero_columns(new_num_cols - old_num_cols);
00124 
00125       // Computed once for all (to be used inside loop).
00126       const Variables_Set::const_iterator param_begin = parameters.begin();
00127       const Variables_Set::const_iterator param_end = parameters.end();
00128 
00129       // This flag will be set if we insert a pending constraint
00130       // in the initial context.
00131       bool check_feasible_context = false;
00132 
00133       // Go through all pending constraints.
00134       for (Constraint_Sequence::const_iterator
00135              cs_i = nth_iter(input_cs, first_pending_constraint),
00136              cs_end = input_cs.end(); cs_i != cs_end; ++cs_i) {
00137         const Constraint& c = *cs_i;
00138         const dimension_type c_space_dim = c.space_dimension();
00139         PPL_ASSERT(external_space_dim >= c_space_dim);
00140 
00141         // Check if constraint has a non-zero variable coefficient.
00142         bool has_nonzero_variable_coefficient = false;
00143         for (dimension_type i = c_space_dim; i-- > 0; ) {
00144           if (c.coefficient(Variable(i)) != 0
00145               && parameters.count(i) == 0) {
00146             has_nonzero_variable_coefficient = true;
00147             break;
00148           }
00149         }
00150         // Constraints having a non-zero variable coefficient
00151         // should not be inserted in context.
00152         if (has_nonzero_variable_coefficient)
00153           continue;
00154 
00155         check_feasible_context = true;
00156 
00157         x.initial_context.add_zero_rows(1, Row_Flags());
00158 
00159         Row& row = x.initial_context[x.initial_context.num_rows()-1];
00160 
00161         {
00162           Row::iterator itr = row.end();
00163 
00164           if (c.inhomogeneous_term() != 0) {
00165             itr = row.insert(0, c.inhomogeneous_term());
00166             // Adjust inhomogeneous term if strict.
00167             if (c.is_strict_inequality())
00168               --(*itr);
00169           } else {
00170             // Adjust inhomogeneous term if strict.
00171             if (c.is_strict_inequality())
00172               itr = row.insert(0, -1);
00173           }
00174           dimension_type i = 1;
00175 
00176           // itr may still be end(), but it can still be used as hint.
00177           for (Variables_Set::const_iterator
00178                pi = param_begin; pi != param_end; ++pi, ++i) {
00179             if (*pi < c_space_dim) {
00180               Coefficient_traits::const_reference coeff_pi
00181                 = c.coefficient(Variable(*pi));
00182               if (coeff_pi != 0)
00183                 itr = row.insert(itr, i, coeff_pi);
00184             } else
00185               break;
00186           }
00187         }
00188 
00189         // If it is an equality, also insert its negation.
00190         if (c.is_equality()) {
00191           x.initial_context.add_zero_rows(1, Row_Flags());
00192 
00193           // The reference `row' has been invalidated.
00194 
00195           Row& last_row = x.initial_context[x.initial_context.num_rows()-1];
00196 
00197           last_row = x.initial_context[x.initial_context.num_rows()-2];
00198 
00199           for (Row::iterator
00200                i = last_row.begin(), i_end = last_row.end(); i != i_end; ++i)
00201             neg_assign(*i);
00202         }
00203       }
00204 
00205       if (check_feasible_context) {
00206         // Check for feasibility of initial context.
00207         Matrix ctx_copy(initial_context);
00208         if (!PIP_Solution_Node::compatibility_check(ctx_copy)) {
00209           // Problem found to be unfeasible.
00210           delete x.current_solution;
00211           x.current_solution = 0;
00212           x.status = UNSATISFIABLE;
00213           PPL_ASSERT(OK());
00214           return UNFEASIBLE_PIP_PROBLEM;
00215         }
00216       }
00217 
00218       // Update tableau and mark constraints as no longer pending.
00219       x.current_solution->update_tableau(*this,
00220                                          external_space_dim,
00221                                          first_pending_constraint,
00222                                          input_cs,
00223                                          parameters);
00224       x.internal_space_dim = external_space_dim;
00225       x.first_pending_constraint = input_cs.size();
00226 
00227       // Actually solve problem.
00228       x.current_solution = x.current_solution->solve(*this,
00229                                                      check_feasible_context,
00230                                                      initial_context,
00231                                                      parameters,
00232                                                      external_space_dim,
00233                                                      /*indent_level=*/ 0);
00234       // Update problem status.
00235       x.status = (x.current_solution != 0) ? OPTIMIZED : UNSATISFIABLE;
00236 
00237       PPL_ASSERT(OK());
00238       return (x.current_solution != 0)
00239         ? OPTIMIZED_PIP_PROBLEM
00240         : UNFEASIBLE_PIP_PROBLEM;
00241     } // End of handler for PARTIALLY_SATISFIABLE case.
00242 
00243   } // End of switch.
00244 
00245   // We should not be here!
00246   PPL_UNREACHABLE;
00247   return UNFEASIBLE_PIP_PROBLEM;
00248 }
00249 
00250 PPL::PIP_Tree
00251 PPL::PIP_Problem::solution() const {
00252   if (status == PARTIALLY_SATISFIABLE)
00253     solve();
00254   return current_solution;
00255 }
00256 
00257 PPL::PIP_Tree
00258 PPL::PIP_Problem::optimizing_solution() const {
00259   if (status == PARTIALLY_SATISFIABLE)
00260     solve();
00261   return current_solution;
00262 }
00263 
00264 bool
00265 PPL::PIP_Problem::OK() const {
00266 #ifndef NDEBUG
00267   using std::endl;
00268   using std::cerr;
00269 #endif
00270 
00271   if (external_space_dim < internal_space_dim) {
00272 #ifndef NDEBUG
00273       cerr << "The internal space dimension of the PIP_Problem is "
00274            << "greater than its external space dimension."
00275            << endl;
00276       ascii_dump(cerr);
00277 #endif
00278       return false;
00279     }
00280 
00281   // Constraint system should be OK.
00282   const dimension_type input_cs_num_rows = input_cs.size();
00283   for (dimension_type i = input_cs_num_rows; i-- > 0; )
00284     if (!input_cs[i].OK())
00285       return false;
00286 
00287   // Constraint system should be space dimension compatible.
00288   for (dimension_type i = input_cs_num_rows; i-- > 0; ) {
00289     if (input_cs[i].space_dimension() > external_space_dim) {
00290 #ifndef NDEBUG
00291       cerr << "The space dimension of the PIP_Problem is smaller than "
00292            << "the space dimension of one of its constraints."
00293            << endl;
00294       ascii_dump(cerr);
00295 #endif
00296       return false;
00297     }
00298   }
00299 
00300   // Test validity of control parameter values.
00301   Control_Parameter_Value strategy = control_parameters[CUTTING_STRATEGY];
00302   if (strategy != CUTTING_STRATEGY_FIRST
00303       && strategy != CUTTING_STRATEGY_DEEPEST
00304       && strategy != CUTTING_STRATEGY_ALL) {
00305 #ifndef NDEBUG
00306     cerr << "Invalid value for the CUTTING_STRATEGY control parameter."
00307          << endl;
00308     ascii_dump(cerr);
00309 #endif
00310     return false;
00311   }
00312 
00313   strategy = control_parameters[PIVOT_ROW_STRATEGY];
00314   if (strategy < PIVOT_ROW_STRATEGY_FIRST
00315       || strategy > PIVOT_ROW_STRATEGY_MAX_COLUMN) {
00316 #ifndef NDEBUG
00317     cerr << "Invalid value for the PIVOT_ROW_STRATEGY control parameter."
00318         << endl;
00319     ascii_dump(cerr);
00320 #endif
00321     return false;
00322   }
00323 
00324   if (big_parameter_dimension != not_a_dimension()
00325       && parameters.count(big_parameter_dimension) == 0) {
00326 #ifndef NDEBUG
00327     cerr << "The big parameter is set, but it is not a parameter." << endl;
00328     ascii_dump(cerr);
00329 #endif
00330     return false;
00331   }
00332 
00333   if (!parameters.OK())
00334     return false;
00335   if (!initial_context.OK())
00336     return false;
00337 
00338   if (current_solution != 0) {
00339     // Check well formedness of the solution tree.
00340     if (!current_solution->OK()) {
00341 #ifndef NDEBUG
00342       cerr << "The computed solution tree is broken.\n";
00343       ascii_dump(cerr);
00344 #endif
00345       return false;
00346     }
00347     // Check that all nodes in the solution tree belong to *this.
00348     if (!current_solution->check_ownership(this)) {
00349 #ifndef NDEBUG
00350       cerr << "There are nodes in the solution tree "
00351            << "that are not owned by *this.\n";
00352       ascii_dump(cerr);
00353 #endif
00354       return false;
00355     }
00356   }
00357 
00358   // All checks passed.
00359   return true;
00360 }
00361 
00362 void
00363 PPL::PIP_Problem::ascii_dump(std::ostream& s) const {
00364   using namespace IO_Operators;
00365   s << "\nexternal_space_dim: " << external_space_dim << "\n";
00366   s << "\ninternal_space_dim: " << internal_space_dim << "\n";
00367 
00368   const dimension_type input_cs_size = input_cs.size();
00369 
00370   s << "\ninput_cs( " << input_cs_size << " )\n";
00371   for (dimension_type i = 0; i < input_cs_size; ++i)
00372     input_cs[i].ascii_dump(s);
00373 
00374   s << "\nfirst_pending_constraint: " <<  first_pending_constraint << "\n";
00375 
00376   s << "\nstatus: ";
00377   switch (status) {
00378   case UNSATISFIABLE:
00379     s << "UNSATISFIABLE";
00380     break;
00381   case OPTIMIZED:
00382     s << "OPTIMIZED";
00383     break;
00384   case PARTIALLY_SATISFIABLE:
00385     s << "PARTIALLY_SATISFIABLE";
00386     break;
00387   }
00388   s << "\n";
00389 
00390   s << "\nparameters";
00391   parameters.ascii_dump(s);
00392 
00393   s << "\ninitial_context\n";
00394   initial_context.ascii_dump(s);
00395 
00396   s << "\ncontrol_parameters\n";
00397   for (dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
00398     Control_Parameter_Value value = control_parameters[i];
00399     switch (value) {
00400     case CUTTING_STRATEGY_FIRST:
00401       s << "CUTTING_STRATEGY_FIRST";
00402       break;
00403     case CUTTING_STRATEGY_DEEPEST:
00404       s << "CUTTING_STRATEGY_DEEPEST";
00405       break;
00406     case CUTTING_STRATEGY_ALL:
00407       s << "CUTTING_STRATEGY_ALL";
00408       break;
00409     case PIVOT_ROW_STRATEGY_FIRST:
00410       s << "PIVOT_ROW_STRATEGY_FIRST";
00411       break;
00412     case PIVOT_ROW_STRATEGY_MAX_COLUMN:
00413       s << "PIVOT_ROW_STRATEGY_MAX_COLUMN";
00414       break;
00415     default:
00416       s << "Invalid control parameter value";
00417     }
00418     s << "\n";
00419   }
00420 
00421   s << "\nbig_parameter_dimension: " << big_parameter_dimension << "\n";
00422 
00423   s << "\ncurrent_solution: ";
00424   if (current_solution == 0)
00425     s << "BOTTOM\n";
00426   else if (const PIP_Decision_Node* dec = current_solution->as_decision()) {
00427     s << "DECISION\n";
00428     dec->ascii_dump(s);
00429   }
00430   else {
00431     const PIP_Solution_Node* sol = current_solution->as_solution();
00432     PPL_ASSERT(sol != 0);
00433     s << "SOLUTION\n";
00434     sol->ascii_dump(s);
00435   }
00436 }
00437 
00438 PPL_OUTPUT_DEFINITIONS(PIP_Problem)
00439 
00440 bool
00441 PPL::PIP_Problem::ascii_load(std::istream& s) {
00442   std::string str;
00443   if (!(s >> str) || str != "external_space_dim:")
00444     return false;
00445 
00446   if (!(s >> external_space_dim))
00447     return false;
00448 
00449   if (!(s >> str) || str != "internal_space_dim:")
00450     return false;
00451 
00452   if (!(s >> internal_space_dim))
00453     return false;
00454 
00455   if (!(s >> str) || str != "input_cs(")
00456     return false;
00457 
00458   dimension_type input_cs_size;
00459 
00460   if (!(s >> input_cs_size))
00461     return false;
00462 
00463   if (!(s >> str) || str != ")")
00464     return false;
00465 
00466   Constraint c(Constraint::zero_dim_positivity());
00467   for (dimension_type i = 0; i < input_cs_size; ++i) {
00468     if (!c.ascii_load(s))
00469       return false;
00470     input_cs.push_back(c);
00471   }
00472 
00473   if (!(s >> str) || str != "first_pending_constraint:")
00474     return false;
00475 
00476   if (!(s >> first_pending_constraint))
00477     return false;
00478 
00479   if (!(s >> str) || str != "status:")
00480     return false;
00481 
00482   if (!(s >> str))
00483     return false;
00484 
00485   if (str == "UNSATISFIABLE")
00486     status = UNSATISFIABLE;
00487   else if (str == "OPTIMIZED")
00488     status = OPTIMIZED;
00489   else if (str == "PARTIALLY_SATISFIABLE")
00490     status = PARTIALLY_SATISFIABLE;
00491   else
00492     return false;
00493 
00494   if (!(s >> str) || str != "parameters")
00495     return false;
00496 
00497   if (!parameters.ascii_load(s))
00498     return false;
00499 
00500   if (!(s >> str) || str != "initial_context")
00501     return false;
00502 
00503   if (!initial_context.ascii_load(s))
00504     return false;
00505 
00506   if (!(s >> str) || str != "control_parameters")
00507     return false;
00508 
00509   for (dimension_type i = 0; i < CONTROL_PARAMETER_NAME_SIZE; ++i) {
00510     if (!(s >> str))
00511       return false;
00512     Control_Parameter_Value value;
00513     if (str == "CUTTING_STRATEGY_FIRST")
00514       value = CUTTING_STRATEGY_FIRST;
00515     else if (str == "CUTTING_STRATEGY_DEEPEST")
00516       value = CUTTING_STRATEGY_DEEPEST;
00517     else if (str == "CUTTING_STRATEGY_ALL")
00518       value = CUTTING_STRATEGY_ALL;
00519     else if (str == "PIVOT_ROW_STRATEGY_FIRST")
00520       value = PIVOT_ROW_STRATEGY_FIRST;
00521     else if (str == "PIVOT_ROW_STRATEGY_MAX_COLUMN")
00522       value = PIVOT_ROW_STRATEGY_MAX_COLUMN;
00523     else
00524       return false;
00525     control_parameters[i] = value;
00526   }
00527 
00528   if (!(s >> str) || str != "big_parameter_dimension:")
00529     return false;
00530   if (!(s >> big_parameter_dimension))
00531     return false;
00532 
00533   // Release current_solution tree (if any).
00534   delete current_solution;
00535   current_solution = 0;
00536   // Load current_solution (if any).
00537   if (!(s >> str) || str != "current_solution:")
00538     return false;
00539   if (!(s >> str))
00540     return false;
00541   if (str == "BOTTOM")
00542     current_solution = 0;
00543   else if (str == "DECISION") {
00544     PIP_Decision_Node* dec = new PIP_Decision_Node(0, 0, 0);
00545     current_solution = dec;
00546     if (!dec->ascii_load(s))
00547       return false;
00548     dec->set_owner(this);
00549   }
00550   else if (str == "SOLUTION") {
00551     PIP_Solution_Node* sol = new PIP_Solution_Node(0);
00552     current_solution = sol;
00553     if (!sol->ascii_load(s))
00554       return false;
00555     sol->set_owner(this);
00556   }
00557   else
00558     // Unknown node kind.
00559     return false;
00560 
00561   PPL_ASSERT(OK());
00562   return true;
00563 }
00564 
00565 void
00566 PPL::PIP_Problem::clear() {
00567   external_space_dim = 0;
00568   internal_space_dim = 0;
00569   status = PARTIALLY_SATISFIABLE;
00570   if (current_solution != 0) {
00571     delete current_solution;
00572     current_solution = 0;
00573   }
00574   input_cs.clear();
00575   first_pending_constraint = 0;
00576   parameters.clear();
00577   initial_context.clear();
00578   control_parameters_init();
00579   big_parameter_dimension = not_a_dimension();
00580 }
00581 
00582 void
00583 PPL::PIP_Problem
00584 ::add_space_dimensions_and_embed(const dimension_type m_vars,
00585                                  const dimension_type m_params) {
00586   // Adding no space dims at all is a no-op:
00587   // this avoids invalidating problem status (if it was optimized).
00588   if (m_vars == 0 && m_params == 0)
00589     return;
00590 
00591   // The space dimension of the resulting PIP problem should not
00592   // overflow the maximum allowed space dimension.
00593   dimension_type available = max_space_dimension() - space_dimension();
00594   bool should_throw = (m_vars > available);
00595   if (!should_throw) {
00596     available -= m_vars;
00597     should_throw = (m_params > available);
00598   }
00599   if (should_throw)
00600     throw std::length_error("PPL::PIP_Problem::"
00601                             "add_space_dimensions_and_embed(m_v, m_p):\n"
00602                             "adding m_v+m_p new space dimensions exceeds "
00603                             "the maximum allowed space dimension.");
00604   // First add PIP variables ...
00605   external_space_dim += m_vars;
00606   // ... then add PIP parameters.
00607   for (dimension_type i = m_params; i-- > 0; ) {
00608     parameters.insert(Variable(external_space_dim));
00609     ++external_space_dim;
00610   }
00611   // Update problem status.
00612   if (status != UNSATISFIABLE)
00613     status = PARTIALLY_SATISFIABLE;
00614   PPL_ASSERT(OK());
00615 }
00616 
00617 void
00618 PPL::PIP_Problem
00619 ::add_to_parameter_space_dimensions(const Variables_Set& p_vars) {
00620   if (p_vars.space_dimension() > external_space_dim)
00621     throw std::invalid_argument("PPL::PIP_Problem::"
00622                                 "add_to_parameter_space_dimension(p_vars):\n"
00623                                 "*this and p_vars are dimension "
00624                                 "incompatible.");
00625   const dimension_type original_size = parameters.size();
00626   parameters.insert(p_vars.begin(), p_vars.end());
00627   // Do not allow to turn variables into parameters.
00628   for (Variables_Set::const_iterator p = p_vars.begin(),
00629          end = p_vars.end(); p != end; ++p) {
00630     if (*p < internal_space_dim) {
00631       throw std::invalid_argument("PPL::PIP_Problem::"
00632                                   "add_to_parameter_space_dimension(p_vars):"
00633                                   "p_vars contain variable indices.");
00634     }
00635   }
00636 
00637   // If a new parameter was inserted, set the internal status to
00638   // PARTIALLY_SATISFIABLE.
00639   if (parameters.size() != original_size && status != UNSATISFIABLE)
00640     status = PARTIALLY_SATISFIABLE;
00641 }
00642 
00643 void
00644 PPL::PIP_Problem::add_constraint(const Constraint& c) {
00645   if (c.space_dimension() > external_space_dim) {
00646     std::ostringstream s;
00647     s << "PPL::PIP_Problem::add_constraint(c):\n"
00648       << "dim == "<< external_space_dim << " and c.space_dimension() == "
00649       << c.space_dimension() << " are dimension incompatible.";
00650     throw std::invalid_argument(s.str());
00651   }
00652   input_cs.push_back(c);
00653   // Update problem status.
00654   if (status != UNSATISFIABLE)
00655     status = PARTIALLY_SATISFIABLE;
00656 }
00657 
00658 void
00659 PPL::PIP_Problem::add_constraints(const Constraint_System &cs) {
00660   for (Constraint_System::const_iterator ci = cs.begin(),
00661          ci_end = cs.end(); ci != ci_end; ++ci)
00662     add_constraint(*ci);
00663 }
00664 
00665 bool
00666 PPL::PIP_Problem::is_satisfiable() const {
00667   if (status == PARTIALLY_SATISFIABLE)
00668     solve();
00669   return status == OPTIMIZED;
00670 }
00671 
00672 void
00673 PPL::PIP_Problem::set_control_parameter(Control_Parameter_Value value) {
00674   switch (value) {
00675   case CUTTING_STRATEGY_FIRST:
00676     // Intentionally fall through.
00677   case CUTTING_STRATEGY_DEEPEST:
00678     // Intentionally fall through.
00679   case CUTTING_STRATEGY_ALL:
00680     control_parameters[CUTTING_STRATEGY] = value;
00681     break;
00682   case PIVOT_ROW_STRATEGY_FIRST:
00683     // Intentionally fall through.
00684   case PIVOT_ROW_STRATEGY_MAX_COLUMN:
00685     control_parameters[PIVOT_ROW_STRATEGY] = value;
00686     break;
00687   default:
00688     throw std::invalid_argument("PPL::PIP_Problem::set_control_parameter(v)"
00689                                 ":\ninvalid value.");
00690   }
00691 }
00692 
00693 void
00694 PPL::PIP_Problem::set_big_parameter_dimension(dimension_type big_dim) {
00695   if (parameters.count(big_dim) == 0)
00696     throw std::invalid_argument("PPL::PIP_Problem::"
00697                                 "set_big_parameter_dimension(big_dim):\n"
00698                                 "dimension 'big_dim' is not a parameter.");
00699   if (big_dim < internal_space_dim)
00700     throw std::invalid_argument("PPL::PIP_Problem::"
00701                                 "set_big_parameter_dimension(big_dim):\n"
00702                                 "only newly-added parameters can be"
00703                                 "converted into the big parameter.");
00704   big_parameter_dimension = big_dim;
00705 }
00706 
00707 PPL::memory_size_type
00708 PPL::PIP_Problem::external_memory_in_bytes() const {
00709   memory_size_type n = initial_context.external_memory_in_bytes();
00710   // Adding the external memory for `current_solution'.
00711   if (current_solution != 0)
00712     n += current_solution->total_memory_in_bytes();
00713   // Adding the external memory for `input_cs'.
00714   n += input_cs.capacity() * sizeof(Constraint);
00715   for (const_iterator i = input_cs.begin(),
00716        i_end = input_cs.end(); i != i_end; ++i)
00717     n += (i->external_memory_in_bytes());
00718   // FIXME: Adding the external memory for `parameters'.
00719   n += parameters.size() * sizeof(dimension_type);
00720 
00721   return n;
00722 }
00723 
00724 PPL::memory_size_type
00725 PPL::PIP_Problem::total_memory_in_bytes() const {
00726   return sizeof(*this) + external_memory_in_bytes();
00727 }
00728 
00729 void
00730 PPL::PIP_Problem::print_solution(std::ostream& s, int indent) const {
00731   switch (status) {
00732 
00733   case UNSATISFIABLE:
00734     PPL_ASSERT(current_solution == 0);
00735     PIP_Tree_Node::indent_and_print(s, indent, "_|_\n");
00736     break;
00737 
00738   case OPTIMIZED:
00739     PPL_ASSERT(current_solution != 0);
00740     current_solution->print(s, indent);
00741     break;
00742 
00743   case PARTIALLY_SATISFIABLE:
00744     throw std::logic_error("PIP_Problem::print_solution():\n"
00745                            "the PIP problem has not been solved.");
00746   }
00747 }
00748