MeshKit  1.0
IAInterfaceStub.cpp
Go to the documentation of this file.
00001 // IAInterfaceStub.cpp stubbed version, without most of meshkit
00002 // Interval Assignment Data for Meshkit
00003 // Interface to the rest of Meshkit
00004 
00005 #include "meshkit/IAInterface.hpp" // the one in stubs = this dir
00006 #include "meshkit/IASolver.hpp"
00007 #include "meshkit/IADataBuilder.hpp"
00008 #include "meshkit/IASolution.hpp"
00009 
00010 // stubbed #include "meshkit/meshkit/ModelEnt.hpp" // from MeshKit
00011 
00012 #include <vector>
00013 #include <iterator>
00014 #include <set>
00015 #include <cstdio>
00016 #include <assert.h>
00017 #include <math.h>
00018 
00019 // zzyk
00020 #include <iostream.h>
00021 
00022 namespace MeshKit 
00023 {
00024   
00025 int ModelEnt::max_stub_id = 0;   // stubbed
00026   
00027 const bool IAInterface::debugging = false;
00028   
00029 //static IAVariable counter
00030 unsigned int IAVariable::numVariables(0);
00031 
00032 // stubbed  
00033 //moab::EntityType IAInterface_types[] = {moab::MBMAXTYPE};
00034 //const moab::EntityType* IAInterface::output_types() 
00035 //  { return IAInterface_types; }
00036     
00037 void IAInterface::setup_this()
00038 {
00039   ; //nothing for now
00040 }
00041     
00042 IAVariable *IAInterface::get_variable( ModelEnt* model_entity, bool create_if_missing )
00043 {
00044   // already exists?
00045   if (model_entity && model_entity->ia_var())
00046   {
00047     // return without setting values
00048     return model_entity->ia_var();
00049   }
00050   
00051   if (model_entity && create_if_missing) 
00052   {
00053     // default values
00054     double goal(1.);
00055     Firmness firm(DEFAULT);
00056     
00057     const Firmness me_firm( model_entity->interval_firmness() );
00058     const double me_edge_size( model_entity->mesh_interval_size() );
00059     if ( me_firm == DEFAULT || me_edge_size <= 0.) 
00060     {
00061       // ModelEnt was unset, so use default values
00062       ;
00063     }
00064     else
00065     {
00066       const double me_size = model_entity->measure();
00067       assert(me_edge_size > 0.);
00068       goal = me_size / me_edge_size;
00069       firm = model_entity->interval_firmness(); 
00070     }
00071     return create_variable( model_entity, firm, goal);  
00072   }
00073   return NULL;
00074 }
00075 
00076 
00077 IAVariable *IAInterface::create_variable( ModelEnt* model_entity, IAVariable::Firmness set_firm, double goal_value)
00078 {
00079   IAVariable *ia_var = NULL;
00080 
00081   // already exists?
00082   if (model_entity && model_entity->ia_var())
00083   {
00084     // set new values and return
00085     ia_var = model_entity->ia_var();
00086     ia_var->set_firmness(set_firm);
00087     ia_var->set_goal(goal_value);
00088     return ia_var;
00089   }
00090       
00091   ia_var = new IAVariable(model_entity, set_firm, goal_value);
00092   assert( ia_var->uniqueId + 1 == IAVariable::numVariables );
00093   variables.push_back(ia_var);
00094   assert( IAVariable::numVariables == variables.size() );
00095 
00096   return ia_var;
00097 }
00098 
00099 IAInterface::IAVariableVec IAInterface::make_constraint_group( const MEntVector &model_entity_vec )
00100 {
00101   IAVariableVec result( model_entity_vec.size() );
00102   for (unsigned int i = 0; i < model_entity_vec.size(); ++i)
00103   {
00104     assert(model_entity_vec[i]);
00105     IAVariable *v = get_variable( model_entity_vec[i], true );
00106     result[i] = v;
00107   }
00108   return result;
00109 }
00110 
00111 void IAInterface::destroy_variable( IAVariable* ia_variable )
00112 {
00113   if (!ia_variable)
00114     return;
00115   // model_entity shouldn't point to ia_variable anymore
00116   ModelEnt *me = ia_variable->get_model_ent();
00117   if (me && me->ia_var() == ia_variable)
00118     me->ia_var(NULL);
00119   
00120   variables[ ia_variable->uniqueId ] = NULL;
00121   delete ia_variable;    
00122 }
00123 
00124 
00125 void IAInterface::destroy_data()
00126 {
00127   // destroy remaining variables
00128   for (unsigned int i = 0; i < variables.size(); ++i)
00129   {
00130     if ( variables[i] )
00131     {
00132       assert( variables[i]->uniqueId == i);
00133       destroy_variable( variables[i] );
00134     }
00135   }
00136   variables.clear();
00137 
00138   // reset global variable id? Yes if this is a singleton class, which it is right now.
00139   IAVariable::numVariables = 0;
00140 
00141   // clear constraints
00142   sumEqualConstraints1.clear();
00143   sumEqualConstraints2.clear();
00144   sumEvenConstraints.clear();
00145   // ... additional types of constraints ...
00146 }
00147 
00148 IAInterface::~IAInterface()
00149 {
00150   destroy_data();
00151 }
00152 
00153 void IAInterface::constrain_sum_even( const IAVariableVec &sum_even_vars )
00154 {
00155   sumEvenConstraints.push_back( sum_even_vars ); // vector copy
00156 }
00157 
00158 void IAInterface::constrain_sum_equal( const IAVariableVec &side_one, const IAVariableVec &side_two )
00159 {
00160   sumEqualConstraints1.push_back(side_one); //vector copy of side_one
00161   sumEqualConstraints2.push_back(side_two); //vector copy of side_two
00162 }
00163 
00164 
00165 // for global vector of variables
00166 int IAInterface::variable_to_index(const IAVariable* var) const
00167 {
00168   return var->uniqueId;
00169 }
00170 
00171 IAVariable *IAInterface::index_to_variable(int ind) const
00172 {
00173   assert(ind < (int) variables.size());
00174   return variables[ind];
00175 }
00176 
00177 void IAInterface::make_set_0_to_nm1( IndexSet &index_set, const size_t k )
00178 {
00179   std::pair< IndexSet::iterator, bool> prior =  index_set.insert( 0 );
00180   assert(prior.second);
00181   for ( size_t i = 0; i < k; ++i)
00182   {
00183     prior.first = index_set.insert( prior.first, (int) i );
00184     // assert(prior.second); // second = insert-success is not assigned by this version of insert!
00185   }
00186 }
00187 
00188 void IAInterface::make_vec_0_to_nm1( IndexVec &index_vec, const size_t k )
00189 {
00190   index_vec.clear();
00191   index_vec.reserve(k);
00192   for (size_t i = 0; i < k; ++i)
00193     index_vec.push_back( (int) i);
00194 }
00195 
00196 void IAInterface::make_vec_unset( IndexVec &index_vec, const size_t k )
00197 {
00198   index_vec.clear();
00199   index_vec.reserve(k);
00200   for (int i = 0; i < (int) k; ++i)
00201     index_vec.push_back(-1);
00202 }
00203 
00204 void IAInterface::set_variable_constraint_indices(
00205             VariableConstraintDependencies &var_con_dep, 
00206             const int i_start, 
00207             const VariableVecVec &variable_vec_vec )
00208 {
00209   unsigned int j;
00210   int i;
00211   for (j = 0, i = i_start; j < variable_vec_vec.size(); ++j, ++i)
00212   {
00213     for (unsigned int k = 0; k < variable_vec_vec[j].size(); ++k )
00214     {
00215       const IAVariable *var = variable_vec_vec[j][k];
00216       const int v = variable_to_index( var ); 
00217       var_con_dep.constraintVariables[i].push_back( v );        
00218       assert( v < (int) var_con_dep.variableConstraints.size() );
00219       var_con_dep.variableConstraints[v].push_back( i );
00220     }
00221   }
00222 }
00223    
00224 void IAInterface::set_variable_constraint_indices(VariableConstraintDependencies &var_con_dep)
00225 {
00226   // create vectors of the length of constraints and variables, but containing of empty vectors
00227   var_con_dep.constraintVariables.resize( sumEqualConstraints1.size() + sumEvenConstraints.size() );
00228   var_con_dep.variableConstraints.resize( variables.size() );
00229 
00230   assert( sumEqualConstraints1.size() == sumEqualConstraints2.size() );
00231   const int sum_even_start = (int) sumEqualConstraints1.size();
00232   //zzyk hardsets
00233   // build vector map of variable-to-constraints
00234   // build vector map of constraint-to-variables
00235   set_variable_constraint_indices( var_con_dep, 0, sumEqualConstraints1 );
00236   set_variable_constraint_indices( var_con_dep, 0, sumEqualConstraints2 );
00237   set_variable_constraint_indices( var_con_dep, sum_even_start, sumEvenConstraints );
00238 }
00239 
00240 void IAInterface::ProblemSets::find_variable_dependent_set( 
00241          const int variable_j, 
00242          const VariableConstraintDependencies &var_con_dep,
00243          ProblemSets &subsets )
00244 {
00245   // return if we've already added this variable to the subset = removed it from this set
00246   IndexSet::iterator j = variableSet.find(variable_j);
00247   if ( j == variableSet.end() )
00248     return;
00249   
00250   // add the variable to the sub-problem
00251   subsets.variableSet.insert(*j);
00252   
00253   // remove the variable from the big problem
00254   variableSet.erase(j);
00255   
00256   // recursively find the dependent constraints
00257   IndexVec::const_iterator i;
00258   assert( variable_j < (int) var_con_dep.variableConstraints.size() ); 
00259   const IndexVec &v = var_con_dep.variableConstraints[variable_j];
00260   for ( i = v.begin(); i != v.end(); ++i )
00261     find_constraint_dependent_set( *i, var_con_dep, subsets );
00262 }
00263 
00264 
00265 void IAInterface::ProblemSets::find_constraint_dependent_set( 
00266          const int constraint_i, 
00267          const VariableConstraintDependencies &var_con_dep,
00268          ProblemSets &subsets )
00269 {
00270   // return if we've already added this constraint to the subset = removed it from this set
00271   // todo, could speed this up using some sort of mark on the entity
00272   IndexSet::iterator i = constraintSet.find(constraint_i);
00273   if ( i == constraintSet.end() )
00274     return;
00275   
00276   // add the constraint to the sub-problem
00277   subsets.constraintSet.insert(*i);
00278 
00279   // remove the constraint from the global problem
00280   constraintSet.erase(i);
00281 
00282   // recursively find the dependent variables
00283   IndexVec::const_iterator j;
00284   assert( constraint_i < (int) var_con_dep.constraintVariables.size() );
00285   const IndexVec &v = var_con_dep.constraintVariables[constraint_i];
00286   for ( j = v.begin(); j != v.end(); ++j )
00287     find_variable_dependent_set( *j, var_con_dep, subsets );
00288 }
00289 
00290 void IAInterface::ProblemSets::find_dependent_set( 
00291   const VariableConstraintDependencies &var_con_dep,
00292   ProblemSets &subsets )
00293 {
00294   if ( !constraintSet.empty() )
00295   {
00296     find_constraint_dependent_set( *constraintSet.begin(), var_con_dep, subsets );
00297   }
00298   else if ( !variableSet.empty() )
00299   {
00300     find_variable_dependent_set( *variableSet.begin(), var_con_dep, subsets );
00301   }
00302 }
00303    
00304 void IAInterface::make_global_set(ProblemSets &problem_sets)
00305 {
00306   make_set_0_to_nm1( problem_sets.constraintSet, sumEqualConstraints1.size() + sumEvenConstraints.size() );
00307   make_set_0_to_nm1( problem_sets.variableSet, variables.size() ); 
00308   make_vec_unset( problem_sets.varMap, variables.size() );
00309   // todo hardsets, 
00310   // move variables from variableSet to hard_variableSet if the variable is hard-set
00311 }
00312   
00313 void IAInterface::global_to_sub_side( 
00314   const VariableVec &global_constraint, 
00315   IndexVec &global_var_map,
00316   IndexVec &local_constraint, int &rhs ) const
00317 {
00318   for (unsigned int j = 0; j < global_constraint.size(); ++j )
00319   {
00320     IAVariable *v = global_constraint[j];
00321     if (v->get_firmness() == MeshKit::HARD )
00322       rhs -= floor( v->get_goal() + 0.5 ); // goal should be integer already for hardsets
00323     else
00324     {
00325       int local_index = global_var_map[ v->uniqueId ];
00326       assert( local_index >= 0 );
00327       // assert( local_index < variableSet.size() );
00328       local_constraint.push_back( local_index ); //variable_to_index( v, sub_variables ) );
00329     }
00330   }
00331 }
00332   
00333 void IAInterface::ProblemSets::print() const
00334 {
00335   printf("ProblemSets %p:\n", this);
00336   if (!empty())
00337     printf("non-");
00338   printf("empty. %lu variables, %lu hardsets, %lu constraints\n", variableSet.size(), hardVariableSet.size(), constraintSet.size());
00339   printf("Variables: ");
00340   for ( IndexSet::const_iterator i = variableSet.begin(); i != variableSet.end(); ++i )
00341   {
00342     printf("%d ", *i);
00343   }
00344   printf("\n");
00345   printf("HardSet Variables: ");
00346   for ( IndexSet::const_iterator i = hardVariableSet.begin(); i != hardVariableSet.end(); ++i )
00347   {
00348     printf("%d ", *i);
00349   }
00350   printf("\n");  
00351   printf("Constraints: ");
00352   for ( IndexSet::const_iterator i = constraintSet.begin(); i != constraintSet.end(); ++i )
00353   {
00354     printf("%d ", *i);
00355   }
00356   printf("\n\n");
00357 }
00358 
00359 void IAInterface::VariableConstraintDependencies::print() const
00360 {
00361   printf("VariableConstraintDependencies %p:\n",this);
00362   printf("%lu variables, %lu constraints\n", variableConstraints.size(), constraintVariables.size() );
00363   for (size_t i = 0; i < variableConstraints.size(); ++i)
00364   {
00365     printf("Variable %lu depends on constraints ", i);
00366     for (size_t j = 0; j < variableConstraints[i].size(); ++j)
00367     {
00368       printf("%d ", variableConstraints[i][j]);
00369     }
00370     printf("\n");
00371   }
00372   
00373   for (size_t i = 0; i < constraintVariables.size(); ++i)
00374   {
00375     printf("Constraint %lu depends on variables ", i);
00376     for (size_t j = 0; j < constraintVariables[i].size(); ++j)
00377     {
00378       printf("%d ", constraintVariables[i][j]);
00379     }
00380     printf("\n");
00381   }
00382   printf("\n");
00383 }
00384 
00385   
00386 void IAInterface::fill_problem( ProblemSets &sub_sets, 
00387   SubProblem *sub_problem, IndexVec &global_var_map ) const
00388 {
00389   IADataBuilder data_builder( sub_problem->data ); 
00390   // number the variables from 0..n, by setting ia_index
00391   sub_problem->data->I.reserve(sub_sets.variableSet.size());
00392   sub_sets.varMap.reserve(sub_sets.variableSet.size());
00393   for (IndexSet::const_iterator i = sub_sets.variableSet.begin(); i != sub_sets.variableSet.end(); ++i)
00394   {
00395     size_t index = *i; // global index
00396     IAVariable *v = index_to_variable( (int) index );
00397     if ( v->get_firmness() != MeshKit::HARD )
00398     {
00399       // index maps
00400       global_var_map[index] = (int) sub_sets.varMap.size();
00401       sub_sets.varMap.push_back( (int) index );
00402 
00403       // add the goals
00404       data_builder.add_variable( v->goal );
00405     }
00406     else
00407     {
00408      // nothing to do, it is a constant, not a variable in the sub problem
00409     }
00410   }
00411 
00412   // convert constraints to IASolver format
00413   for (IndexSet::const_iterator i = sub_sets.constraintSet.begin(); i != sub_sets.constraintSet.end(); ++i )
00414   {
00415     unsigned int c = *i;
00416     if (c < sumEqualConstraints1.size()) // equal
00417     {
00418       IndexVec side_1, side_2;
00419       int rhs_1(0), rhs_2(0);
00420         
00421       global_to_sub_side( sumEqualConstraints1[c], global_var_map, side_1, rhs_1 );
00422       global_to_sub_side( sumEqualConstraints2[c], global_var_map, side_2, rhs_2 );
00423       
00424       data_builder.constrain_opposite_side_equal(side_1, side_2, rhs_1 - rhs_2 );   
00425       // todo check should be rhs_2 - rhs_1 ?
00426     }
00427     else // even 
00428     {
00429       c -= sumEqualConstraints1.size();
00430       assert( c >= 0 ); // not useful because it is unsigned
00431       assert( c < sumEvenConstraints.size() );
00432 
00433       IndexVec side;
00434       int rhs(0);
00435       global_to_sub_side( sumEvenConstraints[c], global_var_map, side, rhs ); // todo check if should be -rhs?
00436       data_builder.constrain_sum_even(side, rhs );   
00437     }
00438   }
00439 }
00440 
00441 void IAInterface::subdivide_problem(SubProblemVec &subproblems)
00442 {
00443   // find independent subproblems, by index of constraint and variable
00444   ProblemSets global_prob_set;
00445   make_global_set(global_prob_set);
00446   if (debugging)
00447     global_prob_set.print(); 
00448   VariableConstraintDependencies var_con_dep;
00449   set_variable_constraint_indices(var_con_dep);
00450   if (debugging)
00451     var_con_dep.print(); 
00452   
00453   while ( !global_prob_set.empty() )
00454   {
00455     // define a sub-problem by indices
00456     SubProblem *subproblem = new SubProblem;
00457     subproblems.push_back( subproblem );
00458     global_prob_set.find_dependent_set(var_con_dep, subproblem->problemSets);
00459     
00460     if (debugging)
00461     {
00462       printf("subproblem peeled out:\n");
00463       subproblem->print();
00464       printf("\nremaining global problem:\n");
00465       global_prob_set.print();
00466     }
00467     
00468     // Fill in solver with data from those indices    
00469     // convert the set into an IASolver, add data
00470     fill_problem( subproblem->problemSets, subproblem, global_prob_set.varMap );
00471     if (debugging)
00472       subproblem->print();
00473   }    
00474 }
00475 
00476 void IAInterface::subdivide_problem_one(std::vector<IAData*> &subproblems)
00477 {
00478    // placeholder - just make one subproblem
00479   IAData *sub_problem = new IAData();
00480   subproblems.push_back(sub_problem);
00481   IADataBuilder data_builder( sub_problem ); // data  
00482 
00483   // this grabs the whole problem and converts it
00484   // variables numbered 0..n
00485   for(VariableVec::const_iterator i = variables.begin(); i != variables.end(); ++i)
00486   {
00487     IAVariable *v = *i;
00488     data_builder.add_variable( v->goal );
00489   }
00490   // equal constraints
00491   for (unsigned int i = 0; i < sumEqualConstraints1.size(); ++i)
00492   {
00493     std::vector<int> side_1, side_2;
00494     for (unsigned int j = 0; j < sumEqualConstraints1[i].size(); ++j)
00495     {
00496       IAVariable *v = sumEqualConstraints1[i][j];
00497       int index = variable_to_index(v);
00498       // sanity check that the indexing was correct
00499       assert( sub_problem->I[index] == v->goal ); 
00500       side_1.push_back(index);
00501     }
00502     for (unsigned int j = 0; j < sumEqualConstraints2[i].size(); ++j)
00503     {
00504       IAVariable *v = sumEqualConstraints2[i][j];
00505       int index = variable_to_index(v);
00506       side_2.push_back(index);
00507     }
00508     data_builder.constrain_opposite_side_equal(side_1, side_2, 0.);
00509   }
00510   // even constraints
00511   for (unsigned int i = 0; i < sumEvenConstraints.size(); ++i)
00512   {
00513     std::vector<int> side;
00514     for (unsigned int j = 0; j < sumEvenConstraints[i].size(); ++j)
00515     {
00516       IAVariable *v = sumEvenConstraints[i][j];
00517       int index = variable_to_index(v);
00518       side.push_back(index);
00519     }
00520     data_builder.constrain_sum_even(side, 0.);
00521   }
00522 
00523 }
00524 
00525 void IAInterface::print_problem() const
00526 {
00527   // describe variables
00528   // describe constraints
00529 }
00530 
00531 void IAInterface::SubProblem::print() const
00532 {
00533   printf("subproblem %d:\n", id);
00534   problemSets.print();
00535   IASolverTool solver_tool(data,solution);
00536   solver_tool.print();
00537   // describe variables
00538   // describe constraints
00539 }
00540 
00541 bool IAInterface::solve_subproblem( SubProblem *subproblem )
00542 {
00543   IASolver solver( subproblem->data, subproblem->solution );
00544   return solver.solve();
00545 }
00546 
00547 void IAInterface::assign_solution( SubProblem *subproblem )
00548 {
00549   // assign solution value from subproblem to model entities
00550   std::vector<double> &x_solution = subproblem->solution->x_solution; // shorthand
00551   for (unsigned int i = 0; i < x_solution.size(); ++i)
00552   {
00553     const double x = x_solution[i];
00554     // map index i to IAVariable, which will be different when we have non-full subproblems
00555     IAVariable *v = index_to_variable( subproblem->problemSets.varMap[i] );
00556     assert(v);
00557     assert( x > 0. );
00558     const int x_int = (int) floor( x + 0.5 );
00559     v->solution = x_int;
00560     if (v->get_model_ent())
00561     {
00562       v->get_model_ent()->mesh_intervals(x_int);
00563     }
00564   }
00565 }
00566 
00567 void IAInterface::execute_this()
00568 {
00569   //zzyk
00570   clock_t t = clock();
00571 
00572   SubProblemVec subproblems;
00573   subdivide_problem(subproblems);
00574   for (unsigned int i = 0; i < subproblems.size(); ++i)
00575   {
00576     SubProblem *p = subproblems[i];
00577     if (debugging)
00578       printf("Solving subproblem %d\n", p->id);
00579     if ( solve_subproblem(p) )
00580       assign_solution(p);
00581     else
00582     {
00583       ; // some error statement
00584     }
00585     delete p;
00586   }
00587   subproblems.clear();
00588 
00589   //zzyk
00590   t = clock()-t;
00591   float seconds = ((float)t)/CLOCKS_PER_SEC;
00592   std::cout << "total IA time " << seconds << std::endl;
00593 
00594   
00595   return;
00596 }
00597 
00598 
00599 int IAInterface::SubProblem::max_id = 0;
00600 
00601 IAInterface::SubProblem::SubProblem()
00602   : id( max_id++ )
00603 {
00604   data = new IAData;
00605   solution = new IASolution;
00606 }
00607   
00608 IAInterface::SubProblem::~SubProblem()
00609 {
00610   delete data;
00611   data = NULL;
00612   delete solution;
00613   solution = NULL;
00614 }
00615 
00616 } // namespace MeshKit
00617 
00618 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines