syn_tsupcon.cpp
Go to the documentation of this file.
1 /** @file syn_tsupcon.cpp Supremal TDES-controllable sublanguage */
2 
3 /* FAU Discrete Event Systems Library (libfaudes)
4 
5  Copyright (C) 2013 Thomas Moor
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
20 
21 
22 #include "syn_tsupcon.h"
23 
24 
25 namespace faudes {
26 
27 
28 
29 
30 /*
31 ***************************************************************************************
32 ***************************************************************************************
33  Implementation
34 ***************************************************************************************
35 ***************************************************************************************
36 */
37 
38 
39 // SupTconUnchecked(rPlantGen, rCAlph, rFAlph, rPAlph, rCPAlph, rSupCandGen)
41  const Generator& rPlantGen, // aka G
42  const EventSet& rCAlph,
43  const EventSet& rFAlph,
44  const EventSet& rPAlph,
45  const EventSet& rCPAlph,
46  Generator& rSupCandGen // aka H
47 )
48 {
49  FD_DF("SupTconUnchecked(" << &rSupCandGen << "," << &rPlantGen << ")");
50 
51  // bail out if plant or candidate contain no initial states
52  if(rPlantGen.InitStatesEmpty() || rSupCandGen.InitStatesEmpty())
53  return;
54 
55  // todo stack (pairs of states)
56  std::stack<Idx> todog, todoh;
57  // set of already processed states of H (this is why we need H-states)
58  StateSet processed;
59 
60  // critical states
61  StateSet critical;
62 
63  // push combined initial state on todo stack
64  todog.push(*rPlantGen.InitStatesBegin());
65  todoh.push(*rSupCandGen.InitStatesBegin());
66  FD_DF("SupCon: todo push: (" << rPlantGen.SStr(*rPlantGen.InitStatesBegin()) << "|"
67  << rSupCandGen.SStr(*rSupCandGen.InitStatesBegin()) << ")");
68 
69  // process todo stack
70  while(!todog.empty()) {
71  // allow for user interrupt
72  // LoopCallback();
73  // allow for user interrupt, incl progress report
74  FD_WPC(1,2,"TdesControllability(): iterating states");
75  // get top element from todo stack
76  Idx currentg = todog.top();
77  Idx currenth = todoh.top();
78  todog.pop();
79  todoh.pop();
80  FD_DF("SupCon: todo pop: (" << rPlantGen.SStr(currentg) << "|"
81  << rSupCandGen.SStr(currenth) << ")");
82 
83  // break on doublets (tmoor 201104)
84  if(processed.Exists(currenth)) continue;
85  processed.Insert(currenth);
86 
87 #ifdef FAUDES_DEBUG_FUNCTION
88  TransSet::Iterator _titg, _tith;
89  // print all transitions of current states
90  FD_DF("SupCon: transitions from current states:");
91  for (_titg = rPlantGen.TransRelBegin(currentg); _titg != rPlantGen.TransRelEnd(currentg); ++_titg)
92  FD_DF("SupCon: g: " << rPlantGen.SStr(_titg->X1) << "-"
93  << rPlantGen.EStr(_titg->Ev) << "-" << rPlantGen.SStr(_titg->X2));
94  for (_tith = rSupCandGen.TransRelBegin(currenth); _tith != rSupCandGen.TransRelEnd(currenth); ++_tith)
95  FD_DF("SupCon: h: " << rSupCandGen.SStr(_tith->X1) << "-"
96  << rSupCandGen.EStr(_tith->Ev) << "-" << rSupCandGen.SStr(_tith->X2));
97 #endif
98 
99  // loop vars
100  TransSet::Iterator tith, tith_end, titg, titg_end;
101 
102  // test current state ...
103  bool pass=false;
104 
105  // 1. figure disabled in the plant g by the loop g x h
106  EventSet disabled;
107  tith = rSupCandGen.TransRelBegin(currenth);
108  tith_end = rSupCandGen.TransRelEnd(currenth);
109  titg = rPlantGen.TransRelBegin(currentg);
110  titg_end = rPlantGen.TransRelEnd(currentg);
111  while( (tith != tith_end) && (titg != titg_end)) {
112  if(tith->Ev > titg->Ev) {
113  disabled.Insert(titg->Ev);
114  ++titg;
115  } else if(tith->Ev == titg->Ev) {
116  ++titg;
117  ++tith;
118  } else {
119  ++tith; // cannot happen
120  }
121  }
122 
123  // 2. pass, if all disabled are controllable
124  if(disabled <= rCAlph) {
125  pass=true;
126  }
127 
128  // 3. is a forcible event enabled for the loop g x h ?
129  bool fenabled=false;
130  if(!pass) {
131  tith = rSupCandGen.TransRelBegin(currenth);
132  tith_end = rSupCandGen.TransRelEnd(currenth);
133  titg = rPlantGen.TransRelBegin(currentg);
134  titg_end = rPlantGen.TransRelEnd(currentg);
135  while( (tith != tith_end) && (titg != titg_end)) {
136  if(tith->Ev > titg->Ev) {
137  ++titg;
138  } else if(tith->Ev == titg->Ev) {
139  if(rFAlph.Exists(titg->Ev)) {fenabled=true; break;}
140  ++titg;
141  ++tith;
142  } else {
143  ++tith; // cannot happen
144  }
145  }
146  }
147 
148  // 4. pass if all uncontr. disabled events are preempted by a forcible event
149  if((!pass) && fenabled) {
150  if(disabled <= rCPAlph) pass=true;
151  }
152 
153  // 5. record non-passed as critical
154  if(!pass) {
155  critical.Insert(currenth);
156  FD_DF("SupCon: todo pop: (" << rPlantGen.SStr(currentg) << "|"
157  << rSupCandGen.SStr(currenth) << "): FAIL");
158  continue;
159  }
160 
161  // 6. if passed, stack successor state
162  if(pass) {
163  // process all h transitions while there could be matching g transitions
164  titg = rPlantGen.TransRelBegin(currentg);
165  titg_end = rPlantGen.TransRelEnd(currentg);
166  tith = rSupCandGen.TransRelBegin(currenth);
167  tith_end = rSupCandGen.TransRelEnd(currenth);
168  while ((tith != tith_end) && (titg != titg_end)) {
169  // increment tith and titg case A: process common events
170  if(titg->Ev == tith->Ev) {
171  FD_DF("SupCon: processing common event " << rPlantGen.EStr(titg->Ev));
172  // add to todo list if state not processed (tmoor 201104: record next H state on stack)
173  if(!processed.Exists(tith->X2)) {
174  todog.push(titg->X2);
175  todoh.push(tith->X2);
176  FD_DF("SupCon: todo push: (" << rPlantGen.SStr(titg->X2) << "|"
177  << rSupCandGen.SStr(tith->X2) << ")");
178  }
179  FD_DF("SupCon: incrementing g and h transrel");
180  ++titg;
181  ++tith;
182  }
183  // increment tith and titg case B: process g event that is not enabled in h
184  else if (titg->Ev < tith->Ev) {
185  FD_DF("SupCon: incrementing g transrel");
186  ++titg;
187  }
188  // increment tith and titg case C: process h event that is not enabled in g
189  else {
190  FD_DF("SupCon: incrementing h transrel"); // cannot happen
191  ++tith;
192  }
193  } // end while tith and titg
194  } // end if passed
195 
196  } //end while todog
197 
198 
199  // remove all states that have been identified as critical or that have
200  // been not processed
201  critical = rSupCandGen.States() - ( processed - critical );
202  rSupCandGen.DelStates(critical);
203 }
204 
205 
206 
207 
208 
209 
210 // SupTconNBUnchecked(rPlantGen, rCAlph, rFAlph, rPAlph, rSpecGen, rCompositionMap, rResGen)
212  const Generator& rPlantGen,
213  const EventSet& rCAlph,
214  const EventSet& rFAlph,
215  const EventSet& rPAlph,
216  const Generator& rSpecGen,
217  std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
218  Generator& rResGen)
219 {
220  FD_DF("SupTconNB(" << &rPlantGen << "," << &rSpecGen << ")");
221 
222  // PREPARE RESULT:
223  Generator* pResGen = &rResGen;
224  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
225  pResGen= rResGen.New();
226  }
227  pResGen->Clear();
228  pResGen->Name(CollapsString("SupTconNB(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
229  pResGen->InjectAlphabet(rPlantGen.Alphabet());
230 
231  // controllable events
232  FD_DF("SupTconNB: controllable events: " << rCAlph.ToString());
233  FD_DF("SupTconNB: forcible events: " << rFAlph.ToString());
234  FD_DF("SupTconNB: preemptyble events: " << rPAlph.ToString());
235 
236  // weackly controllable
237  EventSet cpalph = rCAlph + rPAlph;
238 
239  // ALGORITHM:
240  FD_DF("SupTconNB(): SupConProduct on #" << rPlantGen.Size() << "/ #" << rSpecGen.Size());
241  SupConProduct(rPlantGen, cpalph, rSpecGen, rCompositionMap, *pResGen);
242 
243 
244  // make resulting generator trim until it's fully tdes controllable
245  while(true) {
246  if(pResGen->Empty()) break;
247  Idx state_num = pResGen->Size();
248  FD_DF("SupTconNB(): SupConClosed on #" << rPlantGen.Size() << "/ #" << pResGen->Size());
249  SupConClosedUnchecked(rPlantGen, cpalph, *pResGen);
250  FD_DF("SupTconNB(): SupTcon on #" << rPlantGen.Size() << "/ #" << pResGen->Size());
251  SupTconUnchecked(rPlantGen, rCAlph, rFAlph, rPAlph, cpalph, *pResGen);
252  FD_DF("SupTconNB(): Trim on #" << pResGen->Size());
253  pResGen->Trim();
254  if(pResGen->Size() == state_num) break;
255  }
256 
257  // convenience state names
258  if(rPlantGen.StateNamesEnabled() && rSpecGen.StateNamesEnabled() && rResGen.StateNamesEnabled())
259  SetComposedStateNames(rPlantGen, rSpecGen, rCompositionMap, *pResGen);
260  else
261  pResGen->StateNamesEnabled(false);
262 
263  // copy result
264  if(pResGen != &rResGen) {
265  pResGen->Move(rResGen);
266  delete pResGen;
267  }
268 
269 }
270 
271 
272 
273 // SupTconNB(rPlantGen, rCAlph, rFAlph, rSpecGen, rResGen)
275  const Generator& rPlantGen,
276  const EventSet& rCAlph,
277  const EventSet& rFAlph,
278  const EventSet& rPAlph,
279  const Generator& rSpecGen,
280  Generator& rResGen)
281 {
282 
283  // CONSISTENCY CHECK:
284  ControlProblemConsistencyCheck(rPlantGen, rCAlph, rSpecGen);
285 
286  // HELPERS:
287  std::map< std::pair<Idx,Idx>, Idx> rcmap;
288 
289  // ALGORITHM:
290  SupTconNBUnchecked(rPlantGen, rCAlph, rFAlph, rPAlph, rSpecGen, rcmap, rResGen);
291 }
292 
293 
294 
295 // supcon for Systems
296 // uses and maintains controllablity from plant
298  const System& rPlantGen,
299  const Generator& rSpecGen,
300  Generator& rResGen) {
301 
302  // prepare result
303  Generator* pResGen = &rResGen;
304  if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
305  pResGen= rResGen.New();
306  }
307 
308  // default preemptable but not controllable
309  EventSet palph;
310  palph.Insert("tick");
311  EventSet calph(rPlantGen.ControllableEvents());
312  calph=calph - palph;
313 
314  // execute
315  SupTconNB(rPlantGen, calph, rPlantGen.ForcibleEvents(), palph, rSpecGen,*pResGen);
316 
317  // copy all attributes of input alphabet
318  pResGen->EventAttributes(rPlantGen.Alphabet());
319 
320  // copy result
321  if(pResGen != &rResGen) {
322  pResGen->Move(rResGen);
323  delete pResGen;
324  }
325 
326 }
327 
328 } // name space
#define FD_WPC(cntnow, contdone, message)
Application callback: optional write progress report to console or application, incl count
#define FD_DF(message)
Debug: optional report on user functions.
Set of indices.
Definition: cfl_indexset.h:78
Idx Insert(void)
Insert new index to set.
Set of indices with symbolic names.
Definition: cfl_nameset.h:69
bool Exists(const Idx &rIndex) const
Test existence of index.
bool Insert(const Idx &rIndex)
Add an element by index.
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Iterator on transition.
Definition: cfl_transset.h:269
const TaEventSet< EventAttr > & Alphabet(void) const
Return const reference to alphabet.
Generator with controllability attributes.
EventSet ControllableEvents(void) const
Get EventSet with controllable events.
EventSet ForcibleEvents(void) const
Get EventSet with forcible events.
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
Write configuration data to a string.
Definition: cfl_types.cpp:169
Base class of all FAUDES generators.
StateSet::Iterator InitStatesBegin(void) const
Iterator to Begin() of mInitStates.
const EventSet & Alphabet(void) const
Return const reference to alphabet.
virtual void Move(vGenerator &rGen)
Destructive copy to other vGenerator.
bool InitStatesEmpty(void) const
Check if set of initial states are empty.
TransSet::Iterator TransRelBegin(void) const
Iterator to Begin() of transition relation.
bool Trim(void)
Make generator trim.
virtual vGenerator * New(void) const
Construct on heap.
void Name(const std::string &rName)
Set the generator's name.
void DelStates(const StateSet &rDelStates)
Delete a set of states Cleans mpStates, mInitStates, mMarkedStates, mpTransrel, and mpStateSymboltabl...
TransSet::Iterator TransRelEnd(void) const
Iterator to End() of transition relation.
std::string EStr(Idx index) const
Pretty printable event name for index (eg for debugging).
bool Empty(void) const
Check if generator is empty (no states)
virtual void EventAttributes(const EventSet &rEventSet)
Set attributes for existing events.
bool StateNamesEnabled(void) const
Whether libFAUEDS functions are requested to generate state names.
Idx Size(void) const
Get generator size (number of states)
std::string SStr(Idx index) const
Return pretty printable state name for index (eg for debugging)
virtual void Clear(void)
Clear generator data.
const StateSet & States(void) const
Return reference to state set.
void InjectAlphabet(const EventSet &rNewalphabet)
Set mpAlphabet without consistency check.
bool Exists(const T &rElem) const
Test existence of element.
Definition: cfl_baseset.h:2115
void SupTconNB(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rFAlph, const EventSet &rPAlph, const Generator &rSpecGen, Generator &rResGen)
Nonblocking Supremal TDES-Controllable Sublanguage.
libFAUDES resides within the namespace faudes.
uint32_t Idx
Type definition for index type (allways 32bit)
void SupTconNBUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rFAlph, const EventSet &rPAlph, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
void SetComposedStateNames(const Generator &rGen1, const Generator &rGen2, const std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rGen12)
Helper: uses composition map to track state names in a paralell composition.
void SupConProduct(const Generator &rPlantGen, const EventSet &rCAlph, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
Parallel composition optimized for the purpose of SupCon (internal function)
Definition: syn_supcon.cpp:386
std::string CollapsString(const std::string &rString, unsigned int len)
Limit length of string, return head and tail of string.
Definition: cfl_helper.cpp:91
void ControlProblemConsistencyCheck(const GeneratorVector &rPlantGenVec, const EventSet &rConAlph, const GeneratorVector &rSpecGenVec)
Compositional synthesis.
void SupTconUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, const EventSet &rFAlph, const EventSet &rPAlph, const EventSet &rCPAlph, Generator &rSupCandGen)
Definition: syn_tsupcon.cpp:40
void SupConClosedUnchecked(const Generator &rPlantGen, const EventSet &rCAlph, Generator &rSupCandGen)
Supremal Controllable Sublangauge (internal function)
Definition: syn_supcon.cpp:57

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