syn_functions.cpp
Go to the documentation of this file.
1/** @file syn_functions.cpp Misc functions related to synthesis */
2
3/* FAU Discrete Event Systems Library (libfaudes)
4
5 Copyright (C) 2010 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//#define FAUDES_DEBUG_FUNCTION
23
24#include "syn_functions.h"
25
26
27namespace faudes {
28
29
30
31
32/*
33***************************************************************************************
34***************************************************************************************
35 Implementation
36***************************************************************************************
37***************************************************************************************
38*/
39
40
41
42//IsRelativelyMarked(rGenPlant,rGenCand)
43bool IsRelativelyMarked(const Generator& rGenPlant, const Generator& rGenCand) {
44
45 // alphabets must match
46 if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
47 std::stringstream errstr;
48 errstr << "Alphabets of generators do not match.";
49 throw Exception("IsRelativelyMarked", errstr.str(), 100);
50 }
51
52#ifdef FAUDES_CHECKED
53 // generators are meant to be nonblocking
54 if ( !IsNonblocking(rGenCand) || !IsNonblocking(rGenPlant)) {
55 std::stringstream errstr;
56 errstr << "Arguments are expected to be nonblocking.";
57 throw Exception("IsRelativelyMarked", errstr.str(), 201);
58 }
59#endif
60
61#ifdef FAUDES_CHECKED
62 // generators are meant to be deterministic
63 if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) {
64 std::stringstream errstr;
65 errstr << "Arguments are expected to be deterministic.";
66 throw Exception("IsRelativelyMarked", errstr.str(), 202);
67 }
68#endif
69
70 // perform composition
71 std::map< std::pair<Idx,Idx> , Idx> revmap;
72 Generator product;
73 product.StateNamesEnabled(false);
74 Product(rGenPlant,rGenCand,revmap,product);
75
76 // test all reachable states
77 std::map< std::pair<Idx,Idx> , Idx>::iterator rit;
78 for(rit=revmap.begin(); rit!=revmap.end(); ++rit) {
79 // ok: not GPlant-marked state is not considered
80 if(!rGenPlant.ExistsMarkedState(rit->first.first))
81 continue;
82 // ok: GPlant-marked state also has GCand-mark
83 if(rGenCand.ExistsMarkedState(rit->first.second))
84 continue;
85 // failure: GPlant-marked state has no GCand-mark
86 break;
87 }
88
89 // ok if loop passed
90 return rit==revmap.end();
91
92}
93
94
95
96//IsRelativelyClosed(rGenPlant,rGenCand)
97bool IsRelativelyClosed(const Generator& rGenPlant, const Generator& rGenCand) {
98
99 FD_DF("IsRelativelyClosed(\"" << rGenPlant.Name() << "\", \"" << rGenCand.Name() << "\")");
100
101 // alphabets must match
102 if ( rGenPlant.Alphabet() != rGenCand.Alphabet()) {
103 std::stringstream errstr;
104 errstr << "Alphabets of generators do not match.";
105 throw Exception("IsRelativelyClosed", errstr.str(), 100);
106 }
107
108#ifdef FAUDES_CHECKED
109 // generators are meant to be nonblocking
110 if ( !IsNonblocking(rGenCand) || !IsNonblocking(rGenPlant)) {
111 std::stringstream errstr;
112 errstr << "Arguments are expected to be nonblocking.";
113 throw Exception("IsRelativelyClosed", errstr.str(), 201);
114 }
115#endif
116
117#ifdef FAUDES_CHECKED
118 // generators are meant to be deterministic
119 if ( !IsDeterministic(rGenCand) || !IsDeterministic(rGenPlant)) {
120 std::stringstream errstr;
121 errstr << "Arguments are expected to be deterministic.";
122 throw Exception("IsRelativelyClosed", errstr.str(), 202);
123 }
124#endif
125
126 // perform composition (variation from cfl_parallel.cpp)
127 FD_DF("IsRelativelyClosed(..): perform product");
128
129 // todo stack
130 std::stack< std::pair<Idx,Idx> > todo;
131 // current pair, new pair
132 std::pair<Idx,Idx> currentstates, newstates;
133 // accessible states
134 std::set< std::pair<Idx,Idx> > productstates;
135 // iterators
136 StateSet::Iterator lit1, lit2;
137 TransSet::Iterator tit1, tit1_end, tit2, tit2_end;
138 std::set< std::pair<Idx,Idx> >::iterator rcit;
139 // sense violation of L(GCand) <= L(GPlant)
140 bool inclusion12=true;
141
142 // push all combinations of initial states on todo stack
143 FD_DF("IsRelativelyClosed(..): perform product: adding all combinations of initial states to todo");
144 for (lit1 = rGenCand.InitStatesBegin();
145 lit1 != rGenCand.InitStatesEnd(); ++lit1) {
146 for (lit2 = rGenPlant.InitStatesBegin();
147 lit2 != rGenPlant.InitStatesEnd(); ++lit2) {
148 currentstates = std::make_pair(*lit1, *lit2);
149 todo.push(currentstates);
150 productstates.insert(currentstates);
151 FD_DF("IsRelativelyClosed(..): perform product: (" <<
152 *lit1 << "|" << *lit2 << ")");
153 }
154 }
155
156 // start algorithm
157 FD_DF("IsRelativelyClosed(..): perform product: Product: processing reachable states:");
158 while (! todo.empty() && inclusion12) {
159 // allow for user interrupt
160 LoopCallback();
161 // get next reachable state from todo stack
162 currentstates = todo.top();
163 todo.pop();
164 FD_DF("Processing (" << currentstates.first << "|"
165 << currentstates.second << ")");
166 // iterate over all rGenCand transitions
167 tit1 = rGenCand.TransRelBegin(currentstates.first);
168 tit1_end = rGenCand.TransRelEnd(currentstates.first);
169 tit2 = rGenPlant.TransRelBegin(currentstates.second);
170 tit2_end = rGenPlant.TransRelEnd(currentstates.second);
171 Idx curev1=0;
172 bool resolved12=true;
173 while((tit1 != tit1_end) && (tit2 != tit2_end)) {
174 // sense new event
175 if(tit1->Ev != curev1) {
176 if(!resolved12) inclusion12=false;
177 curev1=tit1->Ev;
178 resolved12=false;
179 }
180 // shared event
181 if(tit1->Ev == tit2->Ev) {
182 resolved12=true;
183 newstates = std::make_pair(tit1->X2, tit2->X2);
184 // add to todo list if composition state is new
185 rcit = productstates.find(newstates);
186 if(rcit == productstates.end()) {
187 todo.push(newstates);
188 productstates.insert(newstates);
189 FD_DF("Product: todo push: (" << newstates.first << "|"
190 << newstates.second << ")");
191 }
192 ++tit1;
193 ++tit2;
194 }
195 // try resync tit1
196 else if (tit1->Ev < tit2->Ev) {
197 ++tit1;
198 }
199 // try resync tit2
200 else if (tit1->Ev > tit2->Ev) {
201 ++tit2;
202 }
203 }
204 // last event was not resolved in the product
205 if(!resolved12) inclusion12=false;
206 }
207 // report
208#ifdef FAUDES_DEBUG_FUNCTION
209 FD_DF("IsRelativelyClosed(): Product: done");
210 if(!inclusion12) {
211 FD_DF("IsRelativelyClosed(): Product: inclusion L(G1) <= L(G2) not satisfied");
212 }
213#endif
214
215 // bail out when inclusion condition is violated
216 if(!inclusion12) return false;
217
218 // test all reachable states
219 std::set< std::pair<Idx,Idx> >::iterator rit;
220 for(rit=productstates.begin(); rit!=productstates.end(); ++rit) {
221 // ok: state is GPlant-marked and GCand-marked
222 if(rGenPlant.ExistsMarkedState(rit->second))
223 if(rGenCand.ExistsMarkedState(rit->first))
224 continue;
225 // ok: state is neither GPlant-marked nor GCand-marked
226 if(!rGenPlant.ExistsMarkedState(rit->second))
227 if(!rGenCand.ExistsMarkedState(rit->first))
228 continue;
229 // failure: markin mismatch
230 break;
231 }
232
233 // ok if loop passed
234 return rit==productstates.end();
235
236}
237
238
239// SupRelativelyClosed(rPlantGen, rCAlph, rSpecGen, rResGen)
241 const Generator& rPlantGen,
242 const Generator& rSpecGen,
243 Generator& rResGen)
244{
245
246 // CONSISTENCY CHECK: alphabets must match
247 if ( rPlantGen.Alphabet() != rSpecGen.Alphabet()) {
248 EventSet only_in_plant = rPlantGen.Alphabet() - rSpecGen.Alphabet();
249 EventSet only_in_spec = rSpecGen.Alphabet() - rPlantGen.Alphabet();
250 only_in_plant.Name("Only_In_Plant");
251 only_in_spec.Name("Only_In_Specification");
252 std::stringstream errstr;
253 errstr << "Alphabets of generators do not match.";
254 if(!only_in_plant.Empty())
255 errstr << " " << only_in_plant.ToString() << ".";
256 if(!only_in_spec.Empty())
257 errstr << " " << only_in_spec.ToString() << ".";
258 throw Exception("SupCon/SupCon", errstr.str(), 100);
259 }
260
261 // CONSISTENCY CHECK: plant and spec must be deterministic
262 bool plant_det = rPlantGen.IsDeterministic();
263 bool spec_det = rSpecGen.IsDeterministic();
264 if ((plant_det == false) && (spec_det == true)) {
265 std::stringstream errstr;
266 errstr << "Plant generator must be deterministic, "
267 << "but is nondeterministic";
268 throw Exception("ControllableConsistencyCheck", errstr.str(), 201);
269 }
270 else if ((plant_det == true) && (spec_det == false)) {
271 std::stringstream errstr;
272 errstr << "Spec generator must be deterministic, "
273 << "but is nondeterministic";
274 throw Exception("ControllableConsistencyCheck", errstr.str(), 203);
275 }
276 else if ((plant_det == false) && (spec_det == false)) {
277 std::stringstream errstr;
278 errstr << "Plant and spec generator must be deterministic, "
279 << "but both are nondeterministic";
280 throw Exception("ControllableConsistencyCheck", errstr.str(), 204);
281 }
282
283 // HELPERS:
284 std::map< std::pair<Idx,Idx>, Idx> rcmap;
285
286 // ALGORITHM:
287 SupRelativelyClosedUnchecked(rPlantGen, rSpecGen, rcmap, rResGen);
288}
289
290
291// SupRelativelyClosedUnchecked(rPlantGen, rSpecGen, rCompositionMap, rResGen)
293 const Generator& rPlantGen,
294 const Generator& rSpecGen,
295 std::map< std::pair<Idx,Idx>, Idx>& rCompositionMap,
296 Generator& rResGen)
297{
298 FD_DF("SupRelativelyClosed(" << &rPlantGen << "," << &rSpecGen << ")");
299
300 // PREPARE RESULT:
301 Generator* pResGen = &rResGen;
302 if(&rResGen== &rPlantGen || &rResGen== &rSpecGen) {
303 pResGen= rResGen.New();
304 }
305 pResGen->Clear();
306 pResGen->Name(CollapsString("SupRpc(("+rPlantGen.Name()+"),("+rSpecGen.Name()+"))"));
307 pResGen->InjectAlphabet(rPlantGen.Alphabet());
308
309 // ALGORITHM:
310 StateSet pmarked;
311 StateSet smarked;
312 Product(rPlantGen, rSpecGen, rCompositionMap, pmarked, smarked, *pResGen);
313
314 // make resulting generator relatively prefix closed
315 StateSet::Iterator six=pResGen->StatesBegin();
316 while(six!= pResGen->StatesEnd()) {
317 Idx s=*(six++);
318 if(!pmarked.Exists(s)) continue;
319 if(smarked.Exists(s)) continue;
320 pResGen->DelState(s);
321 }
322 pResGen->Trim();
323
324 // copy result
325 if(pResGen != &rResGen) {
326 rResGen.Move(*pResGen);
327 delete pResGen;
328 }
329
330}
331
332
333// lagcy wrappers
334bool IsRelativelyPrefixClosed(const Generator& rGenPlant, const Generator& rGenCand){
335 FD_WARN("SupRelativelyPrefixClosed(): API depreciated; use SupRelativelyClosed()");
336 return IsRelativelyClosed(rGenPlant,rGenCand);
337}
338void SupRelativelyPrefixClosed(const Generator& rPlantGen, const Generator& rSpecGen,
339 Generator& rResGen) {
340 FD_WARN("SupRelativelyPrefixClosed(): API depreciated; use SupRelativelyClosed()");
341 SupRelativelyClosed(rPlantGen,rSpecGen,rResGen);
342}
343
344
345
346} // name space
#define FD_WARN(message)
#define FD_DF(message)
const std::string & Name(void) const
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
const EventSet & Alphabet(void) const
TransSet::Iterator TransRelBegin(void) const
virtual vGenerator & Move(Type &rGen)
virtual vGenerator * New(void) const
bool DelState(Idx index)
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
bool IsDeterministic(void) const
bool StateNamesEnabled(void) const
StateSet::Iterator InitStatesEnd(void) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
void InjectAlphabet(const EventSet &rNewalphabet)
bool Empty(void) const
bool Exists(const T &rElem) const
void Product(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
bool IsDeterministic(const vGenerator &rGen)
bool IsRelativelyMarked(const Generator &rGenPlant, const Generator &rGenCand)
void SupRelativelyClosed(const Generator &rPlantGen, const Generator &rSpecGen, Generator &rResGen)
bool IsRelativelyClosed(const Generator &rGenPlant, const Generator &rGenCand)
uint32_t Idx
void SupRelativelyClosedUnchecked(const Generator &rPlantGen, const Generator &rSpecGen, std::map< std::pair< Idx, Idx >, Idx > &rCompositionMap, Generator &rResGen)
void LoopCallback(void)
bool IsNonblocking(const GeneratorVector &rGvec)
bool IsRelativelyPrefixClosed(const Generator &rGenPlant, const Generator &rGenCand)
void SupRelativelyPrefixClosed(const Generator &rPlantGen, const Generator &rSpecGen, Generator &rResGen)
std::string CollapsString(const std::string &rString, unsigned int len)
Definition cfl_utils.cpp:91

libFAUDES 2.34d --- 2026.03.11 --- c++ api documentaion by doxygen