syn_supreduce.cpp
Go to the documentation of this file.
1 /** @file syn_supreduce.cpp Supervisor Reduction */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2006 Bernd Opitz
6  Exclusive copyright is granted to Klaus Schmidt
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21 
22 
23 #include "syn_supreduce.h"
24 
25 /* turn on debugging for this file */
26 //#undef FD_DF
27 //#define FD_DF(a) FD_WARN(a);
28 
29 
30 namespace faudes {
31 
32 
33 
34 
35 /*
36 ***************************************************************************************
37 ***************************************************************************************
38  Implementation
39 ***************************************************************************************
40 ***************************************************************************************
41 */
42 
43 
44 /**
45  * Data structure for identifying states in the same coset for supervisor reduction
46  */
53 };
54 
55 
56 /*
57 Reduction mergibility algorithm
58 
59 This recursive algorithm determines if two supervisor states can be merged to the same coset.
60 It is called by the main procedure SupReduce.
61 -- stateI, stateJ: pair of states to be tested
62 -- rWaitList: list of waiting state pairs
63 -- cNode: record first state to be checked
64 -- rSupGen: const ref to supervisor
65 -- rSupStateInfo: ref to state info
66 -- rState2Class: const ref to state->coset map
67 -- rClass2State: const ref to coset->states
68 
69 return True if the classes of the two states can be merged
70 */
71 
73  Idx stateI, Idx stateJ,
74  std::vector<std::set<Idx> >& rWaitList,
75  Idx cNode,
76  const System& rSupGen,
77  const std::map<Idx,ReductionStateInfo>& rSupStateInfo,
78  const std::map<Idx,Idx>& rState2Class,
79  const std::vector<StateSet>& rClass2States)
80 {
81  FD_DF("TestMergebility: stateI " << stateI << " stateJ " << stateJ);
82  // Loop through all state combinations in the current classes
83  //std::cout
84  /* for(unsigned int i = 0; i < rWaitList.size(); i++)
85  std::cout << *rWaitList[i].begin() << " " << *(++rWaitList[i].begin() ) << std::endl;*/
86  StateSet::Iterator siIt, siEndIt, sjIt, sjEndIt;
87  StateSet statesI, statesJ;
88  statesI = rClass2States[rState2Class.at(stateI)]; // all states of the class of stateI
89  statesJ = rClass2States[rState2Class.at(stateJ)]; // all states of the class of stateJ
90  // add the states on the waitlist to statesI and statesJ
91  for(unsigned int i = 0; i < rWaitList.size(); i++){
92  // StateI: add classes for corresponding state on waitList
93  if(*rWaitList[i].begin() == stateI )
94  statesI = statesI + rClass2States[rState2Class.find(*(++rWaitList[i].begin() ) )->second];
95  if(*(++rWaitList[i].begin() ) == stateI )
96  statesI = statesI + rClass2States[rState2Class.find(*rWaitList[i].begin() )->second];
97  // StateJ: add classes for corresponding state on waitList
98  if(*rWaitList[i].begin() == stateJ )
99  statesJ = statesJ + rClass2States[rState2Class.find(*(++rWaitList[i].begin() ) )->second];
100  if(*(++rWaitList[i].begin() ) == stateJ )
101  statesJ = statesJ + rClass2States[rState2Class.find(*rWaitList[i].begin() )->second];
102  }
103  //FD_DF("Test: statesI " << statesI.ToString() << " stateJ " << statesJ.ToString());
104  siIt = statesI.Begin(); // Iterators for states of class for stateI
105  siEndIt = statesI.End();
106  sjIt = statesJ.Begin(); // Iterators for states of class for stateJ
107  sjEndIt = statesJ.End();
108  std::set<Idx> statePair;
109  for( ; siIt != siEndIt; siIt++){// loop over states for stateI
110  sjIt = statesJ.Begin();
111  for(; sjIt != sjEndIt; sjIt++){ // loop over states for stateJ
112  // only look at state pairs that are not already in the same class2ReducedStates
113  if(rClass2States[rState2Class.find(*siIt)->second].Exists(*sjIt) )
114  continue;
115  if(*siIt == *sjIt)
116  continue;
117 
118  statePair.clear();
119  statePair.insert(*siIt);
120  statePair.insert(*sjIt);
121  //std::cout << "mergibility states: " << *siIt << " and " << *sjIt << std::endl;
122 
123  bool continueLoop = false;
124  for(unsigned int i = 0; i < rWaitList.size(); i++)
125  if(rWaitList[i] == statePair){
126  continueLoop = true;
127  break;
128  }
129  if(continueLoop == true)// the current state pair is already on the waiting list
130  continue;
131 
132  // tmoor: fix nonstandard std::map::at()
133  const ReductionStateInfo& siinf=rSupStateInfo.find(*siIt)->second;
134  const ReductionStateInfo& sjinf=rSupStateInfo.find(*sjIt)->second;
135 
136  // Test whether the state pair belongs to the control relation \mathcal{R}:
137  // E(*siIt) \cap D(*sjIt) = E(*sjIt) \cap D(*siIt) = \emptyset
138  // and C(*siIt) = C(*sjIt) \Rightarrow M(*siIt) = M(*sjIt)
139  //if( !(siinf.mEnabledEvents * sjinf.mDisabledEvents).Empty() ) return false;
140  //if( !(sjinf.mEnabledEvents * siinf.mDisabledEvents).Empty() ) return false;
141  if( !(siinf.mEnabledEvents.Disjoint(sjinf.mDisabledEvents)) ) return false;
142  if( !(sjinf.mEnabledEvents.Disjoint(siinf.mDisabledEvents)) ) return false;
143 
144  // Test whether the marking of the states is consistent
145  if( (siinf.mPlantMarked == sjinf.mPlantMarked) && (siinf.mMarkedState != sjinf.mMarkedState) )
146  return false;
147 
148 
149 
150  /*
151  // original (for reference)
152 
153  // Test if the state pair belongs to the control relation \mathcal{R}:
154  // E(*siIt) \cap D(*sjIt) = E(*sjIt) \cap D(*siIt) = \emptyset and C(*siIt) = C(*sjIt) \Rightarrow M(*siIt) = M(*sjIt)
155  if( !(rSupStateInfo.at(*siIt).mEnabledEvents * rSupStateInfo.at(*sjIt).mDisabledEvents).Empty() ||
156  !(rSupStateInfo.at(*sjIt).mEnabledEvents * rSupStateInfo.at(*siIt).mDisabledEvents).Empty() )
157  return false;
158 
159  // Test if the marking of the states is consistent
160  if( (rSupStateInfo.at(*siIt).mPlantMarked == rSupStateInfo.at(*sjIt).mPlantMarked) &&
161  (rSupStateInfo.at(*siIt).mPlantMarked != rSupStateInfo.at(*sjIt).mPlantMarked) )
162  return false;
163 
164  */
165  rWaitList.push_back(std::set<Idx>() );
166  rWaitList.back().insert(*siIt);
167  rWaitList.back().insert(*sjIt);
168 
169  EventSet sharedEvents = rSupGen.ActiveEventSet(*siIt) * rSupGen.ActiveEventSet(*sjIt);
170  EventSet::Iterator eIt, eEndIt;
171  eIt = sharedEvents.Begin();
172  eEndIt = sharedEvents.End();
173  Idx goalStateI, goalStateJ;
174  for( ; eIt != eEndIt; eIt++){// go over all shared active events of the current states
175  goalStateI = (rSupGen.TransRelBegin(*siIt,*eIt) )->X2;
176  goalStateJ = (rSupGen.TransRelBegin(*sjIt,*eIt) )->X2;
177  if(*rState2Class.find( goalStateI ) == *rState2Class.find( goalStateJ ) )// event leads to same class
178  continue;
179  statePair.clear();
180  statePair.insert(goalStateI);
181  statePair.insert(goalStateJ);
182  continueLoop = false;
183  for(unsigned int i = 0; i < rWaitList.size(); i++){
184  if(rWaitList[i] == statePair)// the current goal state pair is already on the waiting list
185  continueLoop = true;
186  break;
187  }
188  if(continueLoop == true)// the current state pair is already on the waiting list
189  continue;
190 
191  // find classes of goalStateI and goalStateJ and check if they are already merged
192  if( *(rClass2States.at( rState2Class.find(goalStateI)->second ).Begin() ) < cNode)
193  return false;
194  if( *(rClass2States.at(rState2Class.find(goalStateJ)->second ).Begin() ) < cNode)
195  return false;
196  bool flag = TestMergibility(goalStateI, goalStateJ, rWaitList, cNode, rSupGen, rSupStateInfo, rState2Class, rClass2States);
197  if(flag == false){
198  return false;
199  }
200  }
201  }
202  }
203  return true;
204 }
205 
206 
207 
208 
209 // SupReduce(rPlantGen, rSupGen, rReducedSup)
210 bool SupReduce(const System& rPlantGen, const System& rSupGen, System& rReducedSup) {
211  FD_DF("SupReduce()");
212 
213  // CONSISTENCY CHECK:
214 
215  // alphabets must match
216  if (rPlantGen.Alphabet() != rSupGen.Alphabet()) {
217  EventSet only_in_plant = rPlantGen.Alphabet() - rSupGen.Alphabet();
218  EventSet only_in_spec = rSupGen.Alphabet() - rPlantGen.Alphabet();
219  std::stringstream errstr;
220  errstr << "Alphabets of generators do not match. Only in plant: "
221  << only_in_plant.ToString() << ". Only in spec: "
222  << only_in_spec.ToString() << ".";
223  throw Exception("SupReduce", errstr.str(), 100);
224  }
225 
226  // plant and spec must be deterministic
227  bool plant_det = rPlantGen.IsDeterministic();
228  bool sup_det = rSupGen.IsDeterministic();
229 
230  if ((plant_det == false) && (sup_det == true)) {
231  std::stringstream errstr;
232  errstr << "Plant generator must be deterministic, " << "but is nondeterministic";
233  throw Exception("SupReduce", errstr.str(), 201);
234  }
235  else if ((plant_det == true) && (sup_det == false)) {
236  std::stringstream errstr;
237  errstr << "Supervisor generator must be deterministic, " << "but is nondeterministic";
238  throw Exception("SupReduce", errstr.str(), 203);
239  }
240  else if ((plant_det == false) && (sup_det == false)) {
241  std::stringstream errstr;
242  errstr << "Plant and supervisor generator must be deterministic, "
243  << "but both are nondeterministic";
244  throw Exception("SupReduce", errstr.str(), 204);
245  }
246  // Clear the result generator rReducedsup
247  rReducedSup.Clear();
248 
249  // HELPERS:
250  System previousSupReduced = rSupGen;
251  std::vector<StateSet> class2States; // control equivalent states in supervisor
252  std::map<Idx, Idx> state2Class; // map from state Idx to its control equivalent class
253  std::vector<std::set<Idx> > waitList; // list of states for classes to be merged
254  EventSet alwaysEnabledEvents = rSupGen.Alphabet(); // set of events that are never disabled
255  // Initialize the helpers that store information about the equivalence classes
256  StateSet::Iterator sIt, sEndIt;
257  sIt = rSupGen.States().Begin();
258  sEndIt = rSupGen.States().End();
259  for(; sIt != sEndIt; sIt++){ // Note: States are ordered by index
260  class2States.push_back(StateSet() );
261  class2States.back().Insert(*sIt);
262  state2Class[*sIt] = class2States.size() - 1;
263  }
264  // Evaluate the composition of plant and supervisor in order to classify corresponding states
265  System tmp;
266  std::map<std::pair<Idx,Idx>, Idx> reverseCompositionMap;
267  std::map<std::pair<Idx,Idx>, Idx>::const_iterator rcIt, rcEndIt;
268  Parallel(rPlantGen, rSupGen, reverseCompositionMap, tmp);
269  rcIt = reverseCompositionMap.begin();
270  rcEndIt = reverseCompositionMap.end();
271  std::map<Idx,ReductionStateInfo> supStateInfo;
272  std::map<Idx,ReductionStateInfo>::iterator rsIt;
273  // Find the plant states that belong to each supervisor state
274  for(; rcIt != rcEndIt; rcIt++){
275  rsIt = supStateInfo.find(rcIt->first.second);
276  if(rsIt == supStateInfo.end() )
277  supStateInfo[rcIt->first.second] = ReductionStateInfo();
278 
279  supStateInfo[rcIt->first.second].mPlantStates.Insert(rcIt->first.first);
280  }
281  /*
282  FD_DF("SupReduce(): states per supervisor state ");
283  for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++)
284  FD_DF("sup state: " << rsIt->first << " plant states " << rsIt->second.mPlantStates.ToString());
285  */
286  // Determine the state properties for all supervisor stateset
287  for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++){
288  rsIt->second.mEnabledEvents = rSupGen.ActiveEventSet(rsIt->first); // all events enabled at current state2Class
289  sIt = rsIt->second.mPlantStates.Begin();
290  sEndIt = rsIt->second.mPlantStates.End();
291  rsIt->second.mPlantMarked = false;
292  for(; sIt != sEndIt; sIt++){
293  rsIt->second.mDisabledEvents = rsIt->second.mDisabledEvents + rPlantGen.ActiveEventSet(*sIt); // compute active events in plant_det for state *sIt
294  rsIt->second.mPlantMarked = rsIt->second.mPlantMarked || rPlantGen.ExistsMarkedState(*sIt); // compute colors of corresponding plant states
295  }
296 
297  rsIt->second.mDisabledEvents = rsIt->second.mDisabledEvents - rsIt->second.mEnabledEvents; // compute disable events (events that are not enabled
298  rsIt->second.mMarkedState = rSupGen.ExistsMarkedState(rsIt->first);
299  alwaysEnabledEvents = alwaysEnabledEvents - rsIt->second.mDisabledEvents; // subtract disabled events from always enabled events
300  }
301  FD_DF("SupReduce(): Always enabled events: " << alwaysEnabledEvents.ToString());
302  // if no events are disabled, then the reduced supervisor has only one state without events
303  if(rSupGen.Alphabet() == alwaysEnabledEvents){
304  Idx state = rReducedSup.InsState();
305  rReducedSup.SetMarkedState(state);
306  rReducedSup.SetInitState(state);
307  return true;
308  }
309  /*for(rsIt = supStateInfo.begin(); rsIt != supStateInfo.end(); rsIt++)
310  std::cout << "state: " << rsIt->first << " enabled: " << rsIt->second.mEnabledEvents.ToString() << " disabled: " << rsIt->second.mDisabledEvents.ToString() << std::endl;*/ // REMOVE
311 
312  std::map<Idx,bool> usedEventsMap;
313  EventSet::Iterator eIt = alwaysEnabledEvents.Begin();
314  for( ; eIt != alwaysEnabledEvents.End(); eIt++)// map that indicates if always enabled event is relevant for supervisor (true) or not (false)
315  usedEventsMap[*eIt] = false;
316  // ==========================
317  // Algorithm
318  //===========================
319  // go through all supervisor states
320  std::map<Idx,Idx>::const_iterator mIt;
321  std::map<Idx,Idx>::const_iterator mEndIt = state2Class.end();
322  mEndIt--;
323  std::map<Idx,Idx>::const_iterator mbIt, mbEndIt;
324  mbEndIt = state2Class.end();
325 
326  /* std::cout << "Classes to states" << std::endl;
327  for(unsigned int i = 0; i < class2States.size(); i ++)
328  std::cout << "class: " << i << " state " << class2States[i].ToString() << std::endl;
329 
330  std::cout << "State to class" << std::endl;
331  for(mIt = state2Class.begin(); mIt != state2Class.end(); mIt++)
332  std::cout << "state: " << mIt->first << " class: " << mIt->second << std::endl; */ // REMOVE
333 
334  for(mIt = state2Class.begin(); mIt != mEndIt; mIt++){
335  // Evaluate min{k \in I | x_k \in [x_i]}; since StateSets are ordered by index, this simply means finding the first state in the class of x_i
336  if( mIt->first > *class2States[mIt->second].Begin() ){// state is already in other equivalence class
337  continue;
338  }
339  mbIt = ++mIt;
340  mIt--;
341  for(; mbIt != mbEndIt; mbIt++) {// approach from back
342  //if(j > min{k \in I | x_k \in [x_j]}
343  if(mbIt->first > *class2States[mbIt->second].Begin() ){
344  continue;
345  }
346  FD_DF("SupReduce(): loop state i " << mIt->first << "state j " << mbIt->first);
347 
348  // Start actual algorithm after filtering
349  waitList.clear();
350  //if((mIt->first == 1 && mbIt->first == 4) ){
351  //waitList.push_back(std::set<Idx>() );
352  //waitList.back().insert(mIt->first);
353  //waitList.back().insert(mbIt->first); REMOVE
354  //}
355  bool flag = TestMergibility(mIt->first,mbIt->first,waitList,mIt->first, rSupGen, supStateInfo, state2Class, class2States);
356  if(flag == true){// merge classes indicated by waitList
357  FD_DF("SupReduce(): merging");
358  std::vector<std::set<Idx> >::const_iterator wlIt, wlEndIt;
359  //std::cout << "size of weitlist " << waitList.size() << std::endl;
360  wlIt = waitList.begin();
361  wlEndIt = waitList.end();
362  for(; wlIt != wlEndIt; wlIt++){// go through waiting list
363  //std::cout << " states " << *wlIt->begin() << " " << *(++wlIt->begin() ) << std::endl;
364  if(state2Class[*wlIt->begin() ] == state2Class[*(++(wlIt->begin() ) ) ])// no action is required if the states are already in the same class
365  continue;
366  class2States[state2Class[*wlIt->begin() ] ] = class2States[state2Class[*wlIt->begin()] ] + class2States[state2Class[*(++(wlIt->begin() ) ) ] ]; // union of state sets of both classes
367  Idx removeClass = state2Class[*(++(wlIt->begin() ) ) ];
368  sIt = class2States[removeClass ].Begin();
369  sEndIt = class2States[removeClass ].End();
370  for(; sIt != sEndIt; sIt++)
371  state2Class[*sIt] = state2Class[*wlIt->begin() ]; // change class of all states that were merged
372 
373  class2States[removeClass ].Clear(); // clear merged class
374 
375  /*std::cout << "Classes to states" << std::endl;
376  for(unsigned int i = 0; i < class2States.size(); i ++)
377  std::cout << "class: " << i << " state " << class2States[i].ToString() << std::endl;
378 
379  std::cout << "State to class" << std::endl;
380  std::map<Idx,Idx>::const_iterator cIt;
381  for(cIt = state2Class.begin(); cIt != state2Class.end(); cIt++)
382  std::cout << "state: " << cIt->first << " class: " << cIt->second << std::endl; */ // REMOVE
383  }
384  }
385  }
386  }
387 
388  // ===============================
389  // Construct the reduced superisor
390  // ===============================
391  // Every state corresponds to a class that we found and we try to avoid adding trnasitions with always enabled events
392  FD_DF("SupReduce(): construct quitient");
393  std::map<Idx,Idx> class2ReducedStates;
394  Idx newStateIdx;
395  rReducedSup.InjectAlphabet(rSupGen.Alphabet() );
396  // First generate one state for each class in the reduced generator
397  for(unsigned int i = 0; i < class2States.size(); i++){
398  if(class2States[i].Empty() == true)// if the state set is empty, then the class is not used
399  continue;
400  else{// create new state in the reduced supervisor for the class
401  newStateIdx = rReducedSup.InsState();
402  class2ReducedStates[i ] = newStateIdx; // save state for the class
403  }
404  }// all states of the reduced generator are now generated and stored
405 
406  // Now add the transitions to the reduced generator
407  TransSet::Iterator tIt, tEndIt;
408  Idx newGoalState; // goal state for transition to be added
409  for(unsigned int i = 0; i < class2States.size(); i++){
410  if(class2States[i].Empty() == true)// if the state set is empty, then the class is not used
411  continue;
412  sIt = class2States[i].Begin();
413  sEndIt = class2States[i].End();
414  newStateIdx = class2ReducedStates[i];
415  for(; sIt != sEndIt; sIt++){// go through all states of the current class
416  if(rSupGen.ExistsInitState(*sIt) )// determine the initial state of the reduced supervisor
417  rReducedSup.InsInitState(newStateIdx);
418 
419  if(rSupGen.ExistsMarkedState(*sIt) )
420  rReducedSup.SetMarkedState(newStateIdx); // insert the supervisor colors per state
421 
422  tIt = rSupGen.TransRelBegin(*sIt); // transitions of state *sIt in supervisor
423  tEndIt = rSupGen.TransRelEnd(*sIt);
424  for( ; tIt != tEndIt; tIt++){
425  newGoalState = class2ReducedStates[state2Class[tIt->X2] ]; // goal state of transition in the reduced supervisor
426  if(alwaysEnabledEvents.Exists(tIt->Ev) == true && newGoalState != newStateIdx )// always enabled event changes class and is thus relevant for supervisor
427  usedEventsMap[tIt->Ev] = true;
428 
429  rReducedSup.SetTransition(newStateIdx, tIt->Ev, newGoalState);
430  }
431  }
432  }
433  if(previousSupReduced.Size() == rReducedSup.Size() ){
434  std::map<Idx,bool>::const_iterator uIt = usedEventsMap.begin();
435  for(; uIt != usedEventsMap.end(); uIt++){// delete the unused events from the reduced supervisor
436  if(uIt->second == false){
437  rReducedSup.DelEvent(uIt->first);
438  }
439  }
440  }
441  else{
442  previousSupReduced.Clear();
443  Deterministic(rReducedSup,previousSupReduced);
444  SupReduce(rPlantGen,previousSupReduced,rReducedSup);
445  }
446  FD_DF("SupReduce(): done");
447  return true;
448 }
449 
450 
451 
452 } // name space
#define FD_DF(message)
Debug: optional report on user functions.
Faudes exception class.
Set of indices.
Definition: cfl_indexset.h:78
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
Idx InsState(void)
Add new anonymous state to generator.
virtual void Clear(void)
Clear generator data.
const TaStateSet< StateAttr > & States(void) const
Return reference to state set.
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
bool SetTransition(Idx x1, Idx ev, Idx x2)
Add a transition to generator by indices.
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
Generator with controllability attributes.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
EventSet ActiveEventSet(Idx x1) const
Return active event set at state x1.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
bool DelEvent(Idx index)
Delete event from generator by index.
void SetInitState(Idx index)
Set an existing state as initial state by index.
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
bool IsDeterministic(void) const
Check if generator is deterministic.
void SetMarkedState(Idx index)
Set an existing state as marked state by index.
Idx InsInitState(void)
Create new anonymous state and set as initial state.
Idx Size(void) const
Get generator size (number of states)
bool ExistsInitState(Idx index) const
Test existence of state in mInitStates.
bool ExistsMarkedState(Idx index) const
Test existence of state in mMarkedStates.
virtual bool Disjoint(const TBaseSet &rOtherSet) const
Test for this set to be disjoint witg other set.
Definition: cfl_baseset.h:2089
IndexSet StateSet
Definition: cfl_indexset.h:271
Iterator End(void) const
Iterator to the end of set.
Definition: cfl_baseset.h:1896
Iterator Begin(void) const
Iterator to the begin of set.
Definition: cfl_baseset.h:1891
void Deterministic(const Generator &rGen, Generator &rResGen)
Make generator deterministic.
void Parallel(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
Parallel composition.
bool SupReduce(const System &rPlantGen, const System &rSupGen, System &rReducedSup)
Supervisor Reduction algorithm.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
bool TestMergibility(Idx stateI, Idx stateJ, std::vector< std::set< Idx > > &rWaitList, Idx cNode, const System &rSupGen, const std::map< Idx, ReductionStateInfo > &rSupStateInfo, const std::map< Idx, Idx > &rState2Class, const std::vector< StateSet > &rClass2States)
Data structure for identifying states in the same coset for supervisor reduction.
Supervisor Reduction.

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen