PNController.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author: Dula Nad
00035  *  Created: 30.10.2013.
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         //Add the basic vertices.
00055         std::string dofs[]={"X","Y","Z","K","M","N"};
00056         //Initial marking
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         //Debug info
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         //Add local connection
00097         Dm(newcon.place_num, newcon.disable_t) = 1;
00098         Dp(newcon.place_num, newcon.enable_t) = 1;
00099         //Add basic dependencies.
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         //Add advanced dependencies.
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         //this->addToRGraph(info.name);
00120 }
00121 
00122 bool PNController::firing_rec(int des_place,
00123                 std::set<int>& skip_transitions,
00124                 std::set<int>& visited_places)
00125 {
00126         //Add place to visited places.
00127         visited_places.insert(des_place);
00128 
00129         //Find all possible transition activators for this place
00130         Eigen::VectorXi transitions = Dp.row(des_place);
00131         std::vector<int> activators;
00132         for (int i=0; i<transitions.size(); ++i)
00133         {
00134                 //If connected (!=0) AND not in skipped transitions.
00135                 if ((transitions(i) &&
00136                                 (skip_transitions.find(i) == skip_transitions.end())))
00137                 {
00138                         activators.push_back(i);
00139                 }
00140         }
00141 
00142         //If no activators this is a dead-end.
00143         if (activators.empty())
00144         {
00145                 std::cout<<"Place "<<placeMap[des_place]<<" is a dead-end."<<std::endl;
00146                 return false;
00147         }
00148 
00149         //Output debugging information for the curret
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         //For each activator test if there exists a posibility to trigger it.
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                         //If connected (!=0) AND not in visited places.
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                 //Debugging information for the activator places.
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                 //Places that are already marked add to visited places to avoid backlash.
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                         //Recurse to search a lever higher for unmarked places
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                         //Before adding check if still not skipped
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                                 //Skip other pair. There is no change in the marking if we trigger
00221                                 //a pair in the same sequence.
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         //Desired place to activate
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                 //Do the firing
00263                 //Add testing "simulation" of the firing before applying.
00264                 //Add enable/disable service calls for these.
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 // Convenience function
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         //Desired place to activate
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         //marking = av_markings[it-av_diff.begin()];
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         //Create the distance map
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   //Firing sequence to closest based on predecessor map.
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 //  if (boost::edge(curr_pred, closest_vx, rgraph).second)
00424 //  {
00425 //      std::cout<<"Get edge connection between "<<curr_pred<<" and "<<closest_vx<<std::endl;
00426 //    firing_seq.push_back(edgeMap[boost::edge(curr_pred, closest_vx, rgraph).first]);
00427 //  }
00428 //  else
00429 //  {
00430 //      std::cout<<"No edge connection between "<<curr_pred<<" and "<<closest_vx<<std::endl;
00431 //  }
00432 
00433   std::cout<<"Loop across edges. The curr_pred = closest_vx = "<<closest_vx<<std::endl;
00434   //Go back...
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         //Desired place to activate
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                         //Search the graph
00506                         std::vector <int> bacon_number(boost::num_vertices(pngraph));
00507                         std::vector <int> pred_map(boost::num_vertices(pngraph));
00508                         //Create the distance map
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           //Get the transitions from locations
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                         //Search the graph
00530             std::vector <int> bacon_number(boost::num_vertices(pngraph));
00531                         std::vector <int> pred_map(boost::num_vertices(pngraph));
00532                         //Create the distance map
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           //Filter firing sequence
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           //Process and order the firing sequence.
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           std::cout<<"Calculating firing seq."<<std::endl;
00638           //Firing sequence to closest based on predecessor map.
00639           GraphType::vertex_descriptor closest_vx = av_idx[it-av_diff.begin()];
00640           GraphType::vertex_descriptor curr_pred = closest_vx;
00641 
00642           boost::property_map<GraphType, boost::edge_name_t>::type edgeMap =
00643                         boost::get(boost::edge_name_t(), rgraph);
00644           std::cout<<"Get the edge map."<<std::endl;
00645         //  if (boost::edge(curr_pred, closest_vx, rgraph).second)
00646         //  {
00647         //      std::cout<<"Get edge connection between "<<curr_pred<<" and "<<closest_vx<<std::endl;
00648         //    firing_seq.push_back(edgeMap[boost::edge(curr_pred, closest_vx, rgraph).first]);
00649         //  }
00650         //  else
00651         //  {
00652         //      std::cout<<"No edge connection between "<<curr_pred<<" and "<<closest_vx<<std::endl;
00653         //  }
00654 
00655           std::cout<<"Loop across edges. The curr_pred = closest_vx = "<<closest_vx<<std::endl;
00656           //Go back...
00657           std::vector<int> firing_seq;
00658           while (curr_pred != curr_vx)
00659           {
00660             if (boost::edge(pred_map[curr_pred], curr_pred, rgraph).second)
00661             {
00662                 std::cout<<"Get edge connection between "<<pred_map[curr_pred]<<" and "<<curr_pred<<std::endl;
00663                 firing_seq.push_back(edgeMap[boost::edge(pred_map[curr_pred], curr_pred, rgraph).first]);
00664             }
00665             else
00666             {
00667                 std::cout<<"No edge connection between "<<pred_map[curr_pred]<<" and "<<curr_pred<<std::endl;
00668             }
00669             curr_pred = pred_map[curr_pred];
00670           }
00671 
00672           std::cout<<"Triggering the following sequence:";
00673           for (int i=firing_seq.size()-1; i>=0; --i)
00674           {
00675                 std::cout<<transitionMap[firing_seq[i]]<<" -> ";
00676           }
00677           std::cout<<"end"<<std::endl;
00678 
00679           marking = m_new;
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         //Add local connections
00707         boost::add_edge(en_t, place, 1, pngraph);
00708         boost::add_edge(place, dis_t, 1, pngraph);
00709 
00710         //Add basic dependencies.
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         //Add advanced dependencies
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         //If first call populate with default resources
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         //Otherwise do the default
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                 //Extend all current markings
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                 //Check if a new transition can trigger with this marking.
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         //Add enable/disable trigger pairs
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                 //Add new marking
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 //      while (!new_markings.empty())
00800 //      {
00801 //              //Check for enabled transitions
00802 //              Eigen::VectorXi m;
00803 //              m = new_markings.front();
00804 //              new_markings.pop();
00805 //              IntType idx = new_idx.front();
00806 //              new_idx.pop();
00807 //              Eigen::VectorXi all_trans = m.transpose()*Dm;
00808 //              for (int i=0; i<all_trans.size(); ++i)
00809 //              {
00810 //                      if (all_trans(i) == Dm.col(i).sum())
00811 //                      {
00812 //                              //std::cout<<"Transition "<<transitionMap[i]<<" is enabled.";
00813 //                              //std::cout<<"("<<all_trans(i)<<", "<<Dm.col(i).sum()<<")"<<std::endl;
00814 //                              Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00815 //                              fire(i) = 1;
00816 //                              Eigen::VectorXi newmarking = m + I*fire;
00817 //
00818 //                              //Check if we already found this marking.
00819 //                              std::vector<Eigen::VectorXi>::iterator it;
00820 //                              it = std::find(all_markings.begin(),all_markings.end(),newmarking);
00821 //
00822 //                              if (it == all_markings.end())
00823 //                              {
00824 //                                      //New marking
00825 //                                      std::cout<<"New marking!"<<std::endl;
00826 //                                      IntType nidx = boost::add_vertex(rgraph);
00827 //                                      new_markings.push(newmarking);
00828 //                              new_idx.push(nidx);
00829 //                              all_markings.push_back(newmarking);
00830 //                                      all_idx.push_back(nidx);
00831 //                                      rgraph[nidx].marking = newmarking;
00832 //                                      boost::add_edge(idx, nidx,
00833 //                                                              i,rgraph);
00834 //                              }
00835 //                              else
00836 //                              {
00837 //                                      //Old marking
00838 //                                      //Possibly suboptimal
00839 //                                      int old_idx = it - all_markings.begin();
00840 //                                      boost::add_edge(idx, all_idx[old_idx],
00841 //                                                      i,rgraph);
00842 //                              }
00843 //                      }
00844 //              }
00845 //      }
00846 
00847 //      std::vector<Eigen::VectorXi> visited;
00848 //      std::vector<IntType> visited_idx;
00849 //
00850 //      //Revisit other transitions
00851 //      while (!new_markings.empty())
00852 //              {
00853 //                      Eigen::VectorXi m;
00854 //                      IntType idx;
00855 //                      bool foundNew = false;
00856 //                      do
00857 //                      {
00858 //                              m = new_markings.front();
00859 //                              idx = new_idx.front();
00860 //                              new_markings.pop();
00861 //                              new_idx.pop();
00862 //                              foundNew = !(std::find(visited.begin(),visited.end(),m) != visited.end());
00863 //                      }
00864 //                      while ((!foundNew) && (!new_markings.empty()));
00865 //
00866 //                      if (!foundNew) break;
00867 //                      std::cout<<"Selected new marking:"<<m<<std::endl;
00868 //                      visited.push_back(m);
00869 //                      visited_idx.push_back(idx);
00870 //                      if (std::find(all_markings.begin(),all_markings.end(),m) == all_markings.end())
00871 //                      {
00872 //                              all_markings.push_back(m);
00873 //                              all_idx.push_back(idx);
00874 //                      }
00875 //
00876 //                      //Check for enabled transitions
00877 //                      Eigen::VectorXi all_trans = m.transpose()*Dm;
00878 //                      for (int i=0; i<all_trans.size(); ++i)
00879 //                      {
00880 //                              if (all_trans(i) == Dm.col(i).sum())
00881 //                              {
00882 //                                      std::cout<<"Transition "<<transitionMap[i]<<" is enabled.";
00883 //                                      std::cout<<"("<<all_trans(i)<<", "<<Dm.col(i).sum()<<")"<<std::endl;
00884 //                                      Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00885 //                                      fire(i) = 1;
00886 //                                      Eigen::VectorXi newmarking = m + I*fire;
00887 //
00888 //                                      //Check if we already found this marking.
00889 //                                      std::vector<Eigen::VectorXi>::iterator it;
00890 //                                      it = std::find(all_markings.begin(),all_markings.end(),newmarking);
00891 //
00892 //                                      if (it == all_markings.end())
00893 //                                      {
00894 //                                              //New marking
00895 //                                              IntType nidx = boost::add_vertex(rgraph);
00896 //                                              new_markings.push(newmarking);
00897 //                                              new_idx.push(nidx);
00898 //                                              all_markings.push_back(newmarking);
00899 //                                              all_idx.push_back(nidx);
00900 //                                              rgraph[nidx].marking = newmarking;
00901 //                                              boost::add_edge(idx, nidx,
00902 //                                                              i,rgraph);
00903 //                                      }
00904 //                                      else
00905 //                                      {
00906 //                                              //Old marking
00907 //                                              //Possibly suboptimal
00908 //                                              int old_idx = it - all_markings.begin();
00909 //                                              boost::add_edge(idx, all_idx[old_idx],
00910 //                                                              i,rgraph);
00911 //                                      }
00912 //                              }
00913 //                      }
00914 //              }
00915 }
00916 
00917 void PNController::addToRGraph(const std::string& name)
00918 {
00919         typedef GraphType::vertex_descriptor IntType;
00920         //If first call populate with default resources
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         //Otherwise do the default
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                 //Extend all current markings
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                 //Check if a new transition can trigger with this marking.
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         //Add enable/disable trigger pairs
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                 //Add new marking
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                 //boost::add_edge(nidx, idx, newcon.disable_t,rgraph);
00982         }
00983 
00984         std::vector<Eigen::VectorXi> visited;
00985         std::vector<IntType> visited_idx;
00986 
00987         //Revisit other transitions
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                         //std::cout<<"Selected new marking:"<<m<<std::endl;
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                         //Check for enabled transitions
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                                         //std::cout<<"Transition "<<transitionMap[i]<<" is enabled.";
01020                                         //std::cout<<"("<<all_trans(i)<<", "<<Dm.col(i).sum()<<")"<<std::endl;
01021                                         Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
01022                                         fire(i) = 1;
01023                                         Eigen::VectorXi newmarking = m + I*fire;
01024 
01025                                         //Check if we already found this marking.
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                                                 //New marking
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                                                 //Old marking
01044                                                 //Possibly suboptimal
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                 //Check for enabled transitions
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                                 //Check if we already found this marking.
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                                         //New marking
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                                         //Old marking
01132                                         //Possibly suboptimal
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         //Construct a label writer.
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         //Construct a label writer.
01163         std::ostringstream out;
01164         write_graphviz(out, pngraph,
01165                         pn_writer2(pngraph));
01166         desc = out.str();
01167 }
01168 


labust_execution
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:23:25