MeshKit
1.0
|
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