00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <labust/control/PNController.hpp>
00038 #include <boost/graph/graphviz.hpp>
00039 #include <boost/graph/visitors.hpp>
00040 #include <boost/graph/breadth_first_search.hpp>
00041
00042 #include <queue>
00043 #include <list>
00044 #include <algorithm>
00045 #include <sstream>
00046
00047 using namespace labust::control;
00048
00049 PNController::PNController():
00050 pnum(6),
00051 tnum(0),
00052 marking(pnum)
00053 {
00054
00055 std::string dofs[]={"X","Y","Z","K","M","N"};
00056
00057 for (int i=0; i<6;++i)
00058 {
00059 placeMap[i]=dofs[i];
00060 nameMap[dofs[i]].place_num = i;
00061 marking(i) = 1;
00062 int k = boost::add_vertex(pngraph);
00063 pngraph[k].marked = true;
00064 pngraph[k].type = PNVertexProperty::p;
00065 pngraph[k].p_num = k;
00066 pngraph[k].name = dofs[i];
00067 placeToVertexMap[i] = k;
00068 resourcePosition.push_back(k);
00069 }
00070 }
00071
00072 void PNController::addToGraph(const navcon_msgs::RegisterControllerRequest& info)
00073 {
00074 PlaceInfo& newcon=nameMap[info.name];
00075 newcon.place_num = pnum++;
00076
00077 marking.conservativeResize(pnum);
00078 marking(newcon.place_num) = 0;
00079 newcon.enable_t = tnum++;
00080 newcon.disable_t = tnum++;
00081
00082
00083 placeMap[newcon.place_num] = info.name;
00084 transitionMap[newcon.enable_t] = info.name+"_enable";
00085 transitionMap[newcon.disable_t] = info.name+"_disable";
00086
00087 Dm.conservativeResize(pnum, tnum);
00088 Dp.conservativeResize(pnum, tnum);
00089 Dm.row(newcon.place_num) = Eigen::VectorXi::Zero(tnum);
00090 Dp.row(newcon.place_num) = Eigen::VectorXi::Zero(tnum);
00091 Dm.col(newcon.enable_t)= Eigen::VectorXi::Zero(pnum);
00092 Dp.col(newcon.enable_t)= Eigen::VectorXi::Zero(pnum);
00093 Dm.col(newcon.disable_t)= Eigen::VectorXi::Zero(pnum);
00094 Dp.col(newcon.disable_t)= Eigen::VectorXi::Zero(pnum);
00095
00096
00097 Dm(newcon.place_num, newcon.disable_t) = 1;
00098 Dp(newcon.place_num, newcon.enable_t) = 1;
00099
00100 for (int i=0; i<info.used_dofs.size(); ++i)
00101 {
00102 if (info.used_dofs[i])
00103 {
00104 Dm(i, newcon.enable_t) = 1;
00105 Dp(i, newcon.disable_t) = 1;
00106 }
00107 }
00108
00109
00110 for (int i=0; i<info.used_cnt.size(); ++i)
00111 {
00112 int place_num = nameMap[info.used_cnt[i]].place_num;
00113 Dm(place_num, newcon.enable_t) = 1;
00114 Dp(place_num, newcon.disable_t) = 1;
00115 }
00116
00117 I=Dp-Dm;
00118
00119
00120 }
00121
00122 bool PNController::firing_rec(int des_place,
00123 std::set<int>& skip_transitions,
00124 std::set<int>& visited_places)
00125 {
00126
00127 visited_places.insert(des_place);
00128
00129
00130 Eigen::VectorXi transitions = Dp.row(des_place);
00131 std::vector<int> activators;
00132 for (int i=0; i<transitions.size(); ++i)
00133 {
00134
00135 if ((transitions(i) &&
00136 (skip_transitions.find(i) == skip_transitions.end())))
00137 {
00138 activators.push_back(i);
00139 }
00140 }
00141
00142
00143 if (activators.empty())
00144 {
00145 std::cout<<"Place "<<placeMap[des_place]<<" is a dead-end."<<std::endl;
00146 return false;
00147 }
00148
00149
00150 std::cout<<"Place "<<placeMap[des_place]<<" depends on transitions:";
00151 for (int i=0; i<activators.size(); ++i) std::cout<<transitionMap[activators[i]]<<", ";
00152 std::cout<<std::endl;
00153
00154
00155 bool trigerable = false;
00156 for (int i=0; i<activators.size(); ++i)
00157 {
00158 Eigen::VectorXi t_en = Dm.col(activators[i]);
00159 std::vector<int> places;
00160 for (int j=0; j<t_en.size(); ++j)
00161 {
00162
00163 if ((t_en(j) &&
00164 (visited_places.find(j) == visited_places.end())))
00165 {
00166 places.push_back(j);
00167 }
00168 }
00169
00170 if (places.size() == 0)
00171 {
00172 std::cout<<"Activator candidate transition "<<transitionMap[activators[i]];
00173 std::cout<<" is a dead-end."<<std::endl;
00174 continue;
00175 }
00176
00177
00178 std::cout<<"Activator candidate transition "<<transitionMap[activators[i]];
00179 std::cout<<" depends on:";
00180 for (int j=0; j<places.size(); ++j) std::cout<<placeMap[places[j]]<<", ";
00181 std::cout<<std::endl;
00182
00183 bool add_cur_seq=true;
00184
00185 for (int j=0; j<places.size(); ++j)
00186 if (marking(places[j])) visited_places.insert(places[j]);
00187
00188 for (int j=0; j<places.size(); ++j)
00189 {
00190
00191 if (!marking(places[j]))
00192 {
00193 if (!firing_rec(places[j], skip_transitions, visited_places))
00194 {
00195 add_cur_seq = false;
00196 break;
00197 }
00198 }
00199 }
00200
00201 if (add_cur_seq)
00202 {
00203 bool add = true;
00204 for (int j=0; j<firing_seq.size(); ++j)
00205 {
00206 if (firing_seq[j] == activators[i])
00207 {
00208 add = false;
00209 break;
00210 }
00211 }
00212
00213
00214 if (add)
00215 {
00216 std::cout<<"Adding to firing sequence:"<<transitionMap[activators[i]]<<std::endl;
00217 firing_seq.push_back(activators[i]);
00218 trigerable = true;
00219
00220
00221
00222 if (activators[i]%2 == 0)
00223 {
00224 std::cout<<"Adding to skip sequence:"<<transitionMap[activators[i]+1]<<std::endl;
00225 skip_transitions.insert(activators[i]+1);
00226 }
00227 else
00228 {
00229 std::cout<<"Adding to skip sequence:"<<transitionMap[activators[i]-1]<<std::endl;
00230 skip_transitions.insert(activators[i]-1);
00231 }
00232 }
00233 else
00234 {
00235 std::cout<<"Adding to skip sequence:"<<transitionMap[activators[i]]<<std::endl;
00236 skip_transitions.insert(activators[i]);
00237 }
00238 }
00239 }
00240 return trigerable;
00241 }
00242
00243 void PNController::get_firing(const std::string& name)
00244 {
00245
00246 int des_place = nameMap[name].place_num;
00247
00248 while (marking(des_place) != 1)
00249 {
00250 firing_seq.clear();
00251 std::set<int> skip_transitions;
00252 std::set<int> visited_places;
00253 firing_rec(des_place, skip_transitions, visited_places);
00254
00255 std::cout<<"The final firing sequence is:";
00256 for (int i=0; i<firing_seq.size(); ++i)
00257 {
00258 std::cout<<transitionMap[firing_seq[i]]<<" -> ";
00259 }
00260 std::cout<<"end"<<std::endl;
00261
00262
00263
00264
00265 for(int i=0; i<firing_seq.size(); ++i)
00266 {
00267 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00268 fire(firing_seq[i]) = 1;
00269
00270 Eigen::VectorXi enabled_trans = marking.transpose()*Dm;
00271 if (enabled_trans(firing_seq[i]) == Dm.col(firing_seq[i]).sum())
00272 {
00273 std::cout<<"Transition "<<transitionMap[firing_seq[i]]<<" is enabled."<<std::endl;
00274 }
00275 else
00276 {
00277 std::cout<<"Transition "<<transitionMap[firing_seq[i]]<<" is not enabled."<<std::endl;
00278 std::cerr<<"Error - cannot fire transition."<<std::endl;
00279 break;
00280 }
00281
00282 marking = marking + I*fire;
00283 std::cout<<"Transition "<<transitionMap[firing_seq[i]]<<" fired, new marking:"<<marking<<std::endl;
00284 if (marking(des_place))
00285 {
00286 std::cout<<"Reached desired update in the marking."<<std::endl;
00287 break;
00288 }
00289 }
00290
00291 usleep(1000*1000);
00292 }
00293 }
00294
00295 template <class Vector>
00296 void print_vec(const Vector& vec)
00297 {
00298 std::cout<<"(";
00299 int i;
00300 for(i=0; i<vec.size()-1;++i)
00301 {
00302 std::cout<<vec(i)<<",";
00303 }
00304 std::cout<<vec(i)<<")";
00305 }
00306
00307 template <typename DistanceMap, typename PredecessorMap>
00308 class bacon_number_recorder : public boost::default_bfs_visitor
00309 {
00310 public:
00311 bacon_number_recorder(DistanceMap dist, PredecessorMap p) : d(dist), p(p) { }
00312
00313 template <typename Edge, typename Graph>
00314 void tree_edge(Edge e, const Graph& g) const
00315 {
00316 typename boost::graph_traits<Graph>::vertex_descriptor
00317 u = source(e, g), v = target(e, g);
00318 d[v] = d[u] + 1;
00319 p[v] = u;
00320 }
00321 private:
00322 DistanceMap d;
00323 PredecessorMap p;
00324 };
00325
00326 template <typename DistanceMap, typename PredecessorMap>
00327 bacon_number_recorder<DistanceMap, PredecessorMap>
00328 record_bacon_number(DistanceMap d, PredecessorMap p)
00329 {
00330 return bacon_number_recorder<DistanceMap, PredecessorMap>(d,p);
00331 }
00332
00333 void PNController::get_firing_r(const std::string& name)
00334 {
00335
00336 int des_place = nameMap[name].place_num;
00337
00338 std::cout<<"Desired place to activate is: "<<placeMap[des_place]<<" == "<<des_place<<std::endl;
00339
00340 std::vector<Eigen::VectorXi> av_markings;
00341 std::vector<int> av_diff, av_diff2;
00342 for(int i=0; i<all_markings.size(); ++i)
00343 {
00344 if (all_markings[i](des_place))
00345 {
00346 av_markings.push_back(all_markings[i]);
00347 Eigen::VectorXi diff = (all_markings[i] - marking);
00348 diff = diff.array().abs();
00349 av_diff.push_back(diff.sum());
00350 av_diff2.push_back(diff.sum());
00351 }
00352 }
00353
00354 std::sort(av_diff2.begin(),av_diff2.end());
00355 std::vector<int>::iterator it=std::find(av_diff.begin(), av_diff.end(),av_diff2[0]);
00356
00357 std::cout<<"From "<<all_markings.size();
00358 std::cout<<" markings, "<<av_markings.size()<<" have the needed place enabled."<<std::endl;
00359 std::cout<<"The smallest difference marking is:";
00360 print_vec(av_markings[it-av_diff.begin()]);
00361 std::cout<<std::endl;
00362 std::cout<<"The current marking is:";
00363 print_vec(marking);
00364 std::cout<<std::endl;
00365
00366
00367 std::vector<Eigen::VectorXi>::iterator it2 = std::find(all_markings.begin(), all_markings.end(),marking);
00368
00369 std::vector <int> bacon_number(boost::num_vertices(rgraph));
00370 std::vector <int> pred_map(boost::num_vertices(rgraph));
00371
00372 GraphType::vertex_descriptor curr_vx = all_idx[it2-all_markings.begin()];
00373 std::cout<<"The current marking index is: "<<it2-all_markings.begin()<<std::endl;
00374 boost::breadth_first_search(rgraph, all_idx[it2-all_markings.begin()],
00375 boost::visitor(record_bacon_number(&bacon_number[0],&pred_map[0])));
00376
00377 std::vector<int> av_idx;
00378 av_markings.clear();
00379 av_diff.clear();
00380 av_diff2.clear();
00381 for(int i=0; i<all_markings.size(); ++i)
00382 {
00383 if (all_markings[i](des_place))
00384 {
00385 av_markings.push_back(all_markings[i]);
00386 av_idx.push_back(all_idx[i]);
00387 av_diff.push_back(bacon_number[all_idx[i]]);
00388 av_diff2.push_back(bacon_number[all_idx[i]]);
00389 }
00390 }
00391
00392 std::sort(av_diff2.begin(),av_diff2.end());
00393 it=std::find(av_diff.begin(), av_diff.end(),av_diff2[0]);
00394
00395 std::cout<<"The closest marking(s) is(are):"<<std::endl;
00396 bool run=true;
00397 std::vector<int>::iterator it_h = av_diff.begin();
00398 while (it_h != av_diff.end())
00399 {
00400 it_h=std::find(it_h, av_diff.end(),av_diff2[0]);
00401 if (it_h != av_diff.end())
00402 {
00403 std::cout<<"\t";
00404 print_vec(av_markings[it_h-av_diff.begin()]);
00405 std::cout<<std::endl;
00406 ++it_h;
00407 }
00408 }
00409 std::cout<<std::endl;
00410 std::cout<<"The current marking is:";
00411 print_vec(marking);
00412 std::cout<<std::endl;
00413 Eigen::VectorXi m_new = av_markings[it-av_diff.begin()];
00414
00415 std::cout<<"Calculating firing seq."<<std::endl;
00416
00417 GraphType::vertex_descriptor closest_vx = av_idx[it-av_diff.begin()];
00418 GraphType::vertex_descriptor curr_pred = closest_vx;
00419
00420 boost::property_map<GraphType, boost::edge_name_t>::type edgeMap =
00421 boost::get(boost::edge_name_t(), rgraph);
00422 std::cout<<"Get the edge map."<<std::endl;
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 std::cout<<"Loop across edges. The curr_pred = closest_vx = "<<closest_vx<<std::endl;
00434
00435 std::vector<int> firing_seq;
00436 while (curr_pred != curr_vx)
00437 {
00438 if (boost::edge(pred_map[curr_pred], curr_pred, rgraph).second)
00439 {
00440 std::cout<<"Get edge connection between "<<pred_map[curr_pred]<<" and "<<curr_pred<<std::endl;
00441 firing_seq.push_back(edgeMap[boost::edge(pred_map[curr_pred], curr_pred, rgraph).first]);
00442 }
00443 else
00444 {
00445 std::cout<<"No edge connection between "<<pred_map[curr_pred]<<" and "<<curr_pred<<std::endl;
00446 }
00447 curr_pred = pred_map[curr_pred];
00448 }
00449
00450 std::cout<<"Triggering the following sequence:";
00451 for (int i=firing_seq.size()-1; i>=0; --i)
00452 {
00453 std::cout<<transitionMap[firing_seq[i]]<<" -> ";
00454 }
00455 std::cout<<"end"<<std::endl;
00456
00457 marking = m_new;
00458 }
00459
00460 void PNController::get_firing_pn(const std::string& name)
00461 {
00462
00463 int des_place = nameMap[name].place_num;
00464
00465 std::cout<<"Desired place to activate is: "<<placeMap[des_place]<<" == "<<des_place<<std::endl;
00466 int v = placeToVertexMap[des_place];
00467 if (pngraph[v].marked)
00468 {
00469 std::cout<<"The place is already marked."<<std::endl;
00470 return;
00471 }
00472 else
00473 {
00474 std::cout<<"The place is not marked. Searching for firing vector."<<std::endl;
00475 }
00476
00477 typedef std::pair<PNGraphType::in_edge_iterator, PNGraphType::in_edge_iterator> RangePair;
00478 RangePair trans = boost::in_edges(v,pngraph);
00479
00480 std::cout<<"The place "<<pngraph[v].name<<" has following incoming transitions: ";
00481 for (PNGraphType::in_edge_iterator it=trans.first; it!=trans.second; ++it)
00482 {
00483 int t = boost::source(*it, pngraph);
00484 std::cout<<pngraph[t].name;
00485 if (it+1 != trans.second) std::cout<<", ";
00486 }
00487 std::cout<<std::endl;
00488
00489 std::cout<<"Current marking is:";
00490 print_vec(marking);
00491 std::cout<<std::endl;
00492
00493 std::vector<int> markedPlaces;
00494 for(int i=0; i<marking.size(); ++i)
00495 {
00496 if (marking(i))
00497 {
00498 markedPlaces.push_back(placeToVertexMap[i]);
00499 }
00500 }
00501
00502 std::map<int, int> pl_dist;
00503 for(int i=0; i<markedPlaces.size(); ++i)
00504 {
00505
00506 std::vector <int> bacon_number(boost::num_vertices(pngraph));
00507 std::vector <int> pred_map(boost::num_vertices(pngraph));
00508
00509 boost::breadth_first_search(pngraph, markedPlaces[i],
00510 boost::visitor(record_bacon_number(&bacon_number[0],&pred_map[0])));
00511 pl_dist[bacon_number[v]] = markedPlaces[i];
00512 }
00513
00514 std::vector<int> tokenLocation;
00515 for(std::set<int>::const_iterator it=pngraph[v].dep_resource.begin(); it!=pngraph[v].dep_resource.end(); ++it)
00516 {
00517 int p = resourcePosition[*it];
00518 tokenLocation.push_back(p);
00519 std::cout<<"Place "<<pngraph[p].name<<" contains the resource "<<pngraph[*it].name<<std::endl;
00520 }
00521
00522
00523 std::vector< std::set<int> > firing_seq_vec;
00524 tokenLocation = markedPlaces;
00525 for(int i=0; i<tokenLocation.size(); ++i)
00526 {
00527 std::set<int> firing_seq;
00528 int p = tokenLocation[i];
00529
00530 std::vector <int> bacon_number(boost::num_vertices(pngraph));
00531 std::vector <int> pred_map(boost::num_vertices(pngraph));
00532
00533 boost::breadth_first_search(pngraph, p,
00534 boost::visitor(record_bacon_number(&bacon_number[0],&pred_map[0])));
00535
00536 std::cout<<"Distance from "<<pngraph[p].name<<" is "<<bacon_number[v]<<std::endl;
00537
00538 if (bacon_number[v] != 0)
00539 {
00540 int pred = v;pred_map[v];
00541 bool validSeq = true;
00542 while (pred != p)
00543 {
00544 if (pngraph[pred].type == PNVertexProperty::t)
00545 {
00546 int tnum = pngraph[pred].t_num, tpair = 0;
00547 if (tnum % 2 == 0) tpair = tnum+1;
00548 else tpair = tnum - 1;
00549 if (firing_seq.find(tpair) != firing_seq.end())
00550 {
00551 std::cout<<"The sequence request adding a T-invariant. The sequence will be ignored."<<std::endl;
00552 validSeq = false;
00553 break;
00554 }
00555 else
00556 {
00557 std::cout<<"Adding transition "<<transitionMap[tnum]<<std::endl;
00558 firing_seq.insert(pngraph[pred].t_num);
00559 }
00560 }
00561 pred = pred_map[pred];
00562 }
00563
00564 if (validSeq) firing_seq_vec.push_back(firing_seq);
00565 }
00566
00567 }
00568
00569
00570 std::set<int> firing_seq;
00571 for (int i=0; i<firing_seq_vec.size(); ++i)
00572 {
00573 firing_seq.insert(firing_seq_vec[i].begin(), firing_seq_vec[i].end());
00574 }
00575
00576
00577 Eigen::VectorXi m = marking;
00578 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00579 bool seq_ok = false;
00580 std::cout<<"Triggering the following sequence:";
00581 int count = 0; int maxcount = firing_seq.size()+1;
00582 bool found_seq = true;
00583 while (firing_seq.size())
00584 {
00585 std::vector<int> rem;
00586 for(std::set<int>::const_iterator it=firing_seq.begin(); it != firing_seq.end(); ++it)
00587 {
00588 Eigen::VectorXi all_trans = m.transpose()*Dm;
00589 if (all_trans(*it) == Dm.col(*it).sum())
00590 {
00591 fire(*it) = 1;
00592 m = m + I*fire;
00593 fire(*it) = 0;
00594 rem.push_back(*it);
00595 std::cout<<transitionMap[*it]<<" -> ";
00596 }
00597 else
00598 {
00599 std::cout<<"Transition "<<transitionMap[*it]<<" is not enabled, skipping."<<std::endl;
00600 std::cout<<"Marked places:";
00601 for(int i=0; i<marking.size(); ++i)
00602 {
00603 if (m(i))
00604 {
00605 std::cout<<pngraph[placeToVertexMap[i]].name<<", ";
00606 }
00607 }
00608 std::cout<<std::endl;
00609 ++count;
00610 }
00611 }
00612
00613 for(int i=0; i<rem.size();++i)
00614 {
00615 firing_seq.erase(rem[i]);
00616 }
00617
00618 if (count > maxcount)
00619 {
00620 std::cout<<"Unable to find a solution."<<std::endl;
00621 found_seq = false;
00622 break;
00623 }
00624 }
00625 std::cout<<"end"<<std::endl;
00626
00627 marking = m;
00628
00629 for(std::set<int>::const_iterator it=pngraph[v].dep_resource.begin(); it!=pngraph[v].dep_resource.end(); ++it)
00630 {
00631 resourcePosition[*it] = v;
00632 }
00633
00634 if (!found_seq) get_firing_pn(name);
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 }
00682
00683 void PNController::addToPNGraph(const navcon_msgs::RegisterControllerRequest& info)
00684 {
00685 typedef PNGraphType::vertex_descriptor IntType;
00686 PlaceInfo& newcon=nameMap[info.name];
00687
00688 IntType place = boost::add_vertex(pngraph),
00689 en_t = boost::add_vertex(pngraph),
00690 dis_t = boost::add_vertex(pngraph);
00691
00692 pngraph[place].type = PNVertexProperty::p;
00693 pngraph[place].p_num = newcon.place_num;
00694 pngraph[place].marked = false;
00695 pngraph[place].name = placeMap[newcon.place_num];
00696 placeToVertexMap[newcon.place_num] = place;
00697
00698 pngraph[en_t].type = PNVertexProperty::t;
00699 pngraph[en_t].t_num = newcon.enable_t;
00700 pngraph[en_t].name = transitionMap[newcon.enable_t];
00701
00702 pngraph[dis_t].type = PNVertexProperty::t;
00703 pngraph[dis_t].t_num = newcon.disable_t;
00704 pngraph[dis_t].name = transitionMap[newcon.disable_t];
00705
00706
00707 boost::add_edge(en_t, place, 1, pngraph);
00708 boost::add_edge(place, dis_t, 1, pngraph);
00709
00710
00711 for (int i=0; i<info.used_dofs.size(); ++i)
00712 {
00713 if (info.used_dofs[i])
00714 {
00715 boost::add_edge(i,en_t,1,pngraph);
00716 boost::add_edge(dis_t,i,1,pngraph);
00717 pngraph[place].dep_resource.insert(i);
00718 }
00719 }
00720
00721
00722 for (int i=0; i<info.used_cnt.size(); ++i)
00723 {
00724 GraphType::vertex_descriptor place_num =
00725 placeToVertexMap[nameMap[info.used_cnt[i]].place_num];
00726 pngraph[place].dep_resource.insert(pngraph[place_num].dep_resource.begin(), pngraph[place_num].dep_resource.end());
00727 boost::add_edge(place_num, en_t,1,pngraph);
00728 boost::add_edge(dis_t, place_num,1,pngraph);
00729 }
00730 }
00731
00732 void PNController::addToRGraph2(const std::string& name)
00733 {
00734 typedef GraphType::vertex_descriptor IntType;
00735
00736 if (all_markings.size() == 0)
00737 {
00738 Eigen::VectorXi m0=Eigen::VectorXi::Zero(6);
00739 for (int i=0; i<6;++i) m0(i) = 1;
00740
00741 typedef GraphType::vertex_descriptor IntType;
00742 std::queue<Eigen::VectorXi> new_markings;
00743 std::queue<IntType> new_idx;
00744
00745 all_markings.push_back(m0);
00746 all_idx.push_back(boost::add_vertex(rgraph));
00747 rgraph[all_idx.back()].marking = m0;
00748 }
00749
00750
00751 PlaceInfo& newcon=nameMap[name];
00752
00753 std::queue<Eigen::VectorXi> triggers;
00754 std::queue<IntType> triggers_idx;
00755
00756 for(int i=0; i<all_markings.size(); ++i)
00757 {
00758
00759 all_markings[i].conservativeResize(newcon.place_num+1);
00760 all_markings[i](newcon.place_num) = 0;
00761 rgraph[all_idx[i]].marking = all_markings[i];
00762
00763
00764 Eigen::VectorXi all_trans = all_markings[i].transpose()*Dm;
00765 if (all_trans(newcon.enable_t) == Dm.col(newcon.enable_t).sum())
00766 {
00767 triggers.push(all_markings[i]);
00768 triggers_idx.push(all_idx[i]);
00769 }
00770 }
00771
00772 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00773 fire(newcon.enable_t) = 1;
00774
00775 std::queue<Eigen::VectorXi> new_markings;
00776 std::queue<IntType> new_idx;
00777
00778
00779 while(!triggers.empty())
00780 {
00781 Eigen::VectorXi m = triggers.front();
00782 IntType idx = triggers_idx.front();
00783 triggers.pop();
00784 triggers_idx.pop();
00785 Eigen::VectorXi newmarking = m + I*fire;
00786
00787
00788 IntType nidx = boost::add_vertex(rgraph);
00789 all_markings.push_back(newmarking);
00790 all_idx.push_back(nidx);
00791 new_markings.push(newmarking);
00792 new_idx.push(nidx);
00793
00794 rgraph[nidx].marking = newmarking;
00795 boost::add_edge(idx, nidx, newcon.enable_t,rgraph);
00796 boost::add_edge(nidx, idx, newcon.disable_t,rgraph);
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 }
00916
00917 void PNController::addToRGraph(const std::string& name)
00918 {
00919 typedef GraphType::vertex_descriptor IntType;
00920
00921 if (all_markings.size() == 0)
00922 {
00923 Eigen::VectorXi m0=Eigen::VectorXi::Zero(6);
00924 for (int i=0; i<6;++i) m0(i) = 1;
00925
00926 typedef GraphType::vertex_descriptor IntType;
00927 std::queue<Eigen::VectorXi> new_markings;
00928 std::queue<IntType> new_idx;
00929
00930 all_markings.push_back(m0);
00931 all_idx.push_back(boost::add_vertex(rgraph));
00932 rgraph[all_idx.back()].marking = m0;
00933 }
00934
00935
00936 PlaceInfo& newcon=nameMap[name];
00937
00938 std::queue<Eigen::VectorXi> triggers;
00939 std::queue<IntType> triggers_idx;
00940
00941 for(int i=0; i<all_markings.size(); ++i)
00942 {
00943
00944 all_markings[i].conservativeResize(newcon.place_num+1);
00945 all_markings[i](newcon.place_num) = 0;
00946 rgraph[all_idx[i]].marking = all_markings[i];
00947
00948
00949 Eigen::VectorXi all_trans = all_markings[i].transpose()*Dm;
00950 if (all_trans(newcon.enable_t) == Dm.col(newcon.enable_t).sum())
00951 {
00952 triggers.push(all_markings[i]);
00953 triggers_idx.push(all_idx[i]);
00954 }
00955 }
00956
00957 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00958 fire(newcon.enable_t) = 1;
00959
00960 std::queue<Eigen::VectorXi> new_markings;
00961 std::queue<IntType> new_idx;
00962
00963
00964 while(!triggers.empty())
00965 {
00966 Eigen::VectorXi m = triggers.front();
00967 IntType idx = triggers_idx.front();
00968 triggers.pop();
00969 triggers_idx.pop();
00970 Eigen::VectorXi newmarking = m + I*fire;
00971
00972
00973 IntType nidx = boost::add_vertex(rgraph);
00974 all_markings.push_back(newmarking);
00975 all_idx.push_back(nidx);
00976 new_markings.push(newmarking);
00977 new_idx.push(nidx);
00978
00979 rgraph[nidx].marking = newmarking;
00980 boost::add_edge(idx, nidx, newcon.enable_t,rgraph);
00981
00982 }
00983
00984 std::vector<Eigen::VectorXi> visited;
00985 std::vector<IntType> visited_idx;
00986
00987
00988 while (!new_markings.empty())
00989 {
00990 Eigen::VectorXi m;
00991 IntType idx;
00992 bool foundNew = false;
00993 do
00994 {
00995 m = new_markings.front();
00996 idx = new_idx.front();
00997 new_markings.pop();
00998 new_idx.pop();
00999 foundNew = !(std::find(visited.begin(),visited.end(),m) != visited.end());
01000 }
01001 while ((!foundNew) && (!new_markings.empty()));
01002
01003 if (!foundNew) break;
01004
01005 visited.push_back(m);
01006 visited_idx.push_back(idx);
01007 if (std::find(all_markings.begin(),all_markings.end(),m) == all_markings.end())
01008 {
01009 all_markings.push_back(m);
01010 all_idx.push_back(idx);
01011 }
01012
01013
01014 Eigen::VectorXi all_trans = m.transpose()*Dm;
01015 for (int i=0; i<all_trans.size(); ++i)
01016 {
01017 if (all_trans(i) == Dm.col(i).sum())
01018 {
01019
01020
01021 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
01022 fire(i) = 1;
01023 Eigen::VectorXi newmarking = m + I*fire;
01024
01025
01026 std::vector<Eigen::VectorXi>::iterator it;
01027 it = std::find(all_markings.begin(),all_markings.end(),newmarking);
01028
01029 if (it == all_markings.end())
01030 {
01031
01032 IntType nidx = boost::add_vertex(rgraph);
01033 new_markings.push(newmarking);
01034 new_idx.push(nidx);
01035 all_markings.push_back(newmarking);
01036 all_idx.push_back(nidx);
01037 rgraph[nidx].marking = newmarking;
01038 boost::add_edge(idx, nidx,
01039 i,rgraph);
01040 }
01041 else
01042 {
01043
01044
01045 int old_idx = it - all_markings.begin();
01046 boost::add_edge(idx, all_idx[old_idx],
01047 i,rgraph);
01048 }
01049 }
01050 }
01051 }
01052 }
01053
01054 void PNController::reachability()
01055 {
01056 rgraph.clear();
01057 Eigen::VectorXi m0=Eigen::VectorXi::Zero(marking.size());
01058 for (int i=0; i<6;++i) m0(i) = 1;
01059
01060 typedef GraphType::vertex_descriptor IntType;
01061 std::queue<Eigen::VectorXi> new_markings;
01062 std::queue<IntType> new_idx;
01063
01064 std::vector<Eigen::VectorXi> visited;
01065 std::vector<Eigen::VectorXi> all_markings;
01066 std::vector<IntType> all_markings_idx;
01067 std::vector<IntType> visited_idx;
01068 std::list<Eigen::VectorXi> dead_end;
01069
01070 new_markings.push(m0);
01071 new_idx.push(boost::add_vertex(rgraph));
01072 rgraph[new_idx.back()].marking = m0;
01073
01074 std::cout<<"Building reachability graph:"<<std::endl<<std::endl;
01075
01076 while (!new_markings.empty())
01077 {
01078 Eigen::VectorXi m;
01079 IntType idx;
01080 bool foundNew = false;
01081 do
01082 {
01083 m = new_markings.front();
01084 idx = new_idx.front();
01085 new_markings.pop();
01086 new_idx.pop();
01087 foundNew = !(std::find(visited.begin(),visited.end(),m) != visited.end());
01088 }
01089 while ((!foundNew) && (!new_markings.empty()));
01090
01091 if (!foundNew) break;
01092 std::cout<<"Selected new marking:"<<m<<std::endl;
01093 visited.push_back(m);
01094 visited_idx.push_back(idx);
01095 if (std::find(all_markings.begin(),all_markings.end(),m) == all_markings.end())
01096 {
01097 all_markings.push_back(m);
01098 all_markings_idx.push_back(idx);
01099 }
01100
01101
01102 Eigen::VectorXi all_trans = m.transpose()*Dm;
01103 for (int i=0; i<all_trans.size(); ++i)
01104 {
01105 if (all_trans(i) == Dm.col(i).sum())
01106 {
01107 std::cout<<"Transition "<<transitionMap[i]<<" is enabled.";
01108 std::cout<<"("<<all_trans(i)<<", "<<Dm.col(i).sum()<<")"<<std::endl;
01109 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
01110 fire(i) = 1;
01111 Eigen::VectorXi newmarking = m + I*fire;
01112
01113
01114 std::vector<Eigen::VectorXi>::iterator it;
01115 it = std::find(all_markings.begin(),all_markings.end(),newmarking);
01116
01117 if (it == all_markings.end())
01118 {
01119
01120 IntType nidx = boost::add_vertex(rgraph);
01121 new_markings.push(newmarking);
01122 new_idx.push(nidx);
01123 all_markings.push_back(newmarking);
01124 all_markings_idx.push_back(nidx);
01125 rgraph[nidx].marking = newmarking;
01126 boost::add_edge(idx, nidx,
01127 i,rgraph);
01128 }
01129 else
01130 {
01131
01132
01133 int old_idx = it - all_markings.begin();
01134 boost::add_edge(idx, all_markings_idx[old_idx],
01135 i,rgraph);
01136 }
01137 }
01138 }
01139 }
01140
01141 std::cout<<"Finished building graph."<<std::endl;
01142 this->all_markings.swap(all_markings);
01143 this->all_idx.swap(all_markings_idx);
01144 }
01145
01146 void PNController::getDotDesc(std::string& desc)
01147 {
01148 using namespace boost;
01149
01150 std::ostringstream out;
01151 write_graphviz(out, rgraph,
01152 pn_writer(rgraph),
01153 make_edge_writer(
01154 boost::get(boost::edge_name_t(),rgraph),
01155 transitionMap));
01156 desc = out.str();
01157 }
01158
01159 void PNController::getDotDesc2(std::string& desc)
01160 {
01161 using namespace boost;
01162
01163 std::ostringstream out;
01164 write_graphviz(out, pngraph,
01165 pn_writer2(pngraph));
01166 desc = out.str();
01167 }
01168