omg_rabinctrlpartialobs.cpp
Go to the documentation of this file.
1/** @file omg_rabinctrlpartialobs.cpp Rabin control synthesis under partial observation */
2
4
5namespace faudes {
6
7// ============================================================================
8// Helper Functions
9// ============================================================================
10
11// ExtractEventAttributes(rSys, rControllableEvents, rObservableEvents)
13 EventSet& rControllableEvents,
14 EventSet& rObservableEvents) {
15 FD_DF("ExtractEventAttributes()");
16
17 rControllableEvents.Clear();
18 rObservableEvents.Clear();
19
20 // Extract controllable events
21 rControllableEvents = rSys.ControllableEvents();
22
23 // Extract observable events
24 rObservableEvents = rSys.ObservableEvents();
25
26 FD_DF("ExtractEventAttributes: controllable events: " << rControllableEvents.ToString());
27 FD_DF("ExtractEventAttributes: observable events: " << rObservableEvents.ToString());
28}
29
30// RabinCtrlPartialObsConsistencyCheck
32 const RabinAutomaton& rSpec,
33 const EventSet& rControllableEvents,
34 const EventSet& rObservableEvents) {
35 FD_DF("RabinCtrlPartialObsConsistencyCheck()");
36
37 // Check that alphabets match
38 if (rPlant.Alphabet() != rSpec.Alphabet()) {
39 EventSet only_in_plant = rPlant.Alphabet() - rSpec.Alphabet();
40 EventSet only_in_spec = rSpec.Alphabet() - rPlant.Alphabet();
41 only_in_plant.Name("OnlyInPlant");
42 only_in_spec.Name("OnlyInSpec");
43 std::stringstream errstr;
44 errstr << "Alphabets of plant and specification do not match.";
45 if(!only_in_plant.Empty())
46 errstr << " " << only_in_plant.ToString() << ".";
47 if(!only_in_spec.Empty())
48 errstr << " " << only_in_spec.ToString() << ".";
49 throw Exception("RabinCtrlPartialObs", errstr.str(), 100);
50 }
51
52 // Check that controllable events are subset of alphabet
53 if (!(rControllableEvents <= rPlant.Alphabet())) {
54 EventSet not_in_alphabet = rControllableEvents - rPlant.Alphabet();
55 std::stringstream errstr;
56 errstr << "Controllable events not subset of alphabet: "
57 << not_in_alphabet.ToString();
58 throw Exception("RabinCtrlPartialObs", errstr.str(), 305);
59 }
60
61 // Check that observable events are subset of alphabet
62 if (!(rObservableEvents <= rPlant.Alphabet())) {
63 EventSet not_in_alphabet = rObservableEvents - rPlant.Alphabet();
64 std::stringstream errstr;
65 errstr << "Observable events not subset of alphabet: "
66 << not_in_alphabet.ToString();
67 throw Exception("RabinCtrlPartialObs", errstr.str(), 306);
68 }
69
70 // Check that plant and spec are deterministic
71 bool plant_det = rPlant.IsDeterministic();
72 bool spec_det = rSpec.IsDeterministic();
73
74 if (!plant_det && !spec_det) {
75 throw Exception("RabinCtrlPartialObs",
76 "Both plant and specification must be deterministic", 204);
77 } else if (!plant_det) {
78 throw Exception("RabinCtrlPartialObs",
79 "Plant must be deterministic", 201);
80 } else if (!spec_det) {
81 throw Exception("RabinCtrlPartialObs",
82 "Specification must be deterministic", 203);
83 }
84
85 FD_DF("RabinCtrlPartialObsConsistencyCheck: passed all checks");
86}
87
88// ============================================================================
89// Main API Functions
90// ============================================================================
91
92// RabinCtrlPartialObs (System interface - automatic event attribute extraction)
93void RabinCtrlPartialObs(const System& rPlant,
94 const RabinAutomaton& rSpec,
95 RabinAutomaton& rSupervisor) {
96 FD_DF("RabinCtrlPartialObs: System interface");
97
98 // Extract controllable and observable events from System
99 EventSet controllableEvents, observableEvents;
100 ExtractEventAttributes(rPlant, controllableEvents, observableEvents);
101
102 // Events extracted successfully
103
104 // Call main implementation with the System cast to RabinAutomaton
105 RabinCtrlPartialObs(static_cast<const RabinAutomaton&>(rPlant),
106 controllableEvents, observableEvents, rSpec, rSupervisor);
107}
108
109// RabinCtrlPartialObs (explicit event sets)
111 const EventSet& rControllableEvents,
112 const EventSet& rObservableEvents,
113 const RabinAutomaton& rSpec,
114 RabinAutomaton& rSupervisor) {
115 FD_DF("RabinCtrlPartialObs: explicit event sets");
116
117 // CONSISTENCY CHECKS
118 if (rControllableEvents.Empty()) {
119 throw Exception("RabinCtrlPartialObs", "Empty controllable event set", 300);
120 }
121
122 if (rObservableEvents.Empty()) {
123 throw Exception("RabinCtrlPartialObs", "Empty observable event set", 301);
124 }
125
126 if (rSpec.Empty()) {
127 throw Exception("RabinCtrlPartialObs", "Empty specification language", 302);
128 }
129
130 RabinCtrlPartialObsConsistencyCheck(rPlant, rSpec, rControllableEvents, rObservableEvents);
131
132 // PREPARE RESULT
133 RabinAutomaton* pSupervisor = &rSupervisor;
134 if (&rSupervisor == &rPlant || &rSupervisor == &rSpec) {
135 pSupervisor = new RabinAutomaton();
136 }
137 pSupervisor->Clear();
138 pSupervisor->Name("RabinCtrlPartialObs(" + rPlant.Name() + "," + rSpec.Name() + ")");
139
140 try {
141 FD_DF("RabinCtrlPartialObs: Starting synthesis algorithm");
142
143 // STEP 1: Compute synchronous product of plant and specification
144 FD_DF("RabinCtrlPartialObs: Step 1 - Computing product");
146 RabinBuechiProduct(rSpec, rPlant, Product);
147
148 if (Product.Empty()) {
149 throw Exception("RabinCtrlPartialObs",
150 "Product of plant and specification is empty", 302);
151 }
152
153 FD_DF("RabinCtrlPartialObs: Product computed, states: " << Product.Size());
154
155 // STEP 2: Apply epsilon observation directly on product (skip control pattern expansion)
156 FD_DF("RabinCtrlPartialObs: Step 2 - Applying epsilon observation directly on product");
157 RabinAutomaton epsObserved;
158
159 Product.SetControllable(rControllableEvents);
160
161 EventSet allProductEvents = Product.Alphabet();
162 Product.ClrObservable(allProductEvents);
163 Product.SetObservable(rObservableEvents);
164 // Apply epsilon observation directly on the product
165 EpsObservation(Product, epsObserved);
166
167 if (epsObserved.Empty()) {
168 throw Exception("RabinCtrlPartialObs",
169 "Epsilon observation resulted in empty automaton", 303);
170 }
171
172 FD_DF("RabinCtrlPartialObs: Epsilon observation applied, states: " << epsObserved.Size());
173
174 // STEP 3: Pseudo-determinize the result
175 FD_DF("RabinCtrlPartialObs: Step 3 - Pseudo-determinization");
176 PseudoDet(epsObserved, *pSupervisor);
177
178 if (pSupervisor->Empty()) {
179 throw Exception("RabinCtrlPartialObs",
180 "Pseudo-determinization resulted in empty automaton", 303);
181 }
182
183 FD_DF("RabinCtrlPartialObs: Pseudo-determinization completed, states: " << pSupervisor->Size());
184
185 // Keep the alphabet as computed by PseudoDet (includes epsilon events)
186 // Do not reset to original plant alphabet since we need eps events
187
188 FD_DF("RabinCtrlPartialObs: Synthesis completed successfully");
189
190 } catch (const Exception& ex) {
191 FD_DF("RabinCtrlPartialObs: Exception caught: " << ex.What());
192
193 // Clean up and re-throw
194 if (pSupervisor != &rSupervisor) {
195 delete pSupervisor;
196 }
197 throw;
198 }
199
200 // Copy result if needed
201 if (pSupervisor != &rSupervisor) {
202 rSupervisor = *pSupervisor;
203 delete pSupervisor;
204 }
205
206 FD_DF("RabinCtrlPartialObs: completed");
207}
208
209// ControlAut - Apply controller to filter transitions and create Buchi automaton
210void ControlAut(const RabinAutomaton& rsDRA,
211 const TaIndexSet<EventSet>& rController,
212 Generator& rRes) {
213 FD_DF("ControlAut()");
214
215 // Clear result automaton
216 Generator* pRes = &rRes;
217 if (&rRes == &rsDRA) {
218 pRes = new Generator();
219 }
220 pRes->Clear();
221 pRes->Name("ControlAut(" + rsDRA.Name() + ")");
222
223 // Copy alphabet from source automaton
224 pRes->InjectAlphabet(rsDRA.Alphabet());
225
226 // Copy only states that are in the controller
227 StateSet::Iterator sit;
228 for (sit = rsDRA.StatesBegin(); sit != rsDRA.StatesEnd(); ++sit) {
229 if (rController.Exists(*sit)) {
230 pRes->InsState(*sit);
231 }
232 }
233
234 // Set initial states (only if they exist in the controller)
235 StateSet::Iterator iit;
236 for (iit = rsDRA.InitStatesBegin(); iit != rsDRA.InitStatesEnd(); ++iit) {
237 if (rController.Exists(*iit)) {
238 pRes->SetInitState(*iit);
239 }
240 }
241
242 // Mark all states (create Buchi automaton)
243 for (sit = pRes->StatesBegin(); sit != pRes->StatesEnd(); ++sit) {
244 pRes->SetMarkedState(*sit);
245 }
246
247 // Add self-loops for unobservable events in each state (step 2)
248 EventSet unobservableEvents = rsDRA.Alphabet() - rsDRA.ObservableEvents();
249 for (sit = pRes->StatesBegin(); sit != pRes->StatesEnd(); ++sit) {
250 EventSet::Iterator eit;
251 for (eit = unobservableEvents.Begin(); eit != unobservableEvents.End(); ++eit) {
252 pRes->SetTransition(*sit, *eit, *sit);
253 FD_DF("ControlAut: Adding unobservable self-loop " << *sit << " --" <<
254 rsDRA.EventName(*eit) << "--> " << *sit);
255 }
256 }
257
258 // Filter transitions based on controller
260 for (tit = rsDRA.TransRelBegin(); tit != rsDRA.TransRelEnd(); ++tit) {
261 Idx state = tit->X1;
262 Idx event = tit->Ev;
263 Idx nextState = tit->X2;
264
265 // Check if this state has controller restrictions
266 if (rController.Exists(state)) {
267 const EventSet& allowedEvents = rController.Attribute(state);
268 // Only add transition if event is allowed by controller
269 if (allowedEvents.Exists(event)) {
270 pRes->SetTransition(state, event, nextState);
271 FD_DF("ControlAut: Adding transition " << state << " --" <<
272 rsDRA.EventName(event) << "--> " << nextState);
273 } else {
274 FD_DF("ControlAut: Filtering out transition " << state << " --" <<
275 rsDRA.EventName(event) << "--> " << nextState << " (not allowed by controller)");
276 }
277 } else {
278 // Skip transitions from states not in controller (they are deleted)
279 FD_DF("ControlAut: Skipping transition " << state << " --" <<
280 rsDRA.EventName(event) << "--> " << nextState << " (state not in controller)");
281 }
282 }
283
284 // Copy result if needed
285 if (pRes != &rRes) {
286 rRes = *pRes;
287 delete pRes;
288 }
289
290
291 FD_DF("ControlAut: Generated Buchi automaton with " << rRes.Size() <<
292 " states and " << rRes.TransRelSize() << " transitions");
293 FD_DF("ControlAut: All " << rRes.MarkedStatesSize() << " states are marked");
294}
295
296// ============================================================================
297// Epsilon Observation Functions
298// ============================================================================
299
301 rRes = rGen; // Copy original automaton
302
303 // Get unobservable events
304 EventSet unobservableEvents = rRes.UnobservableEvents();
305
306 // If no unobservable events, return original automaton
307 if(unobservableEvents.Size() == 0) {
308 return;
309 }
310
311 // Create single epsilon event
312 std::string epsEventName = "eps";
313 Idx epsEvent = rRes.InsEvent(epsEventName);
314
315 // Set epsilon event as uncontrollable and unobservable
316 rRes.ClrControllable(epsEvent);
317 rRes.ClrObservable(epsEvent);
318 rRes.ClrForcible(epsEvent);
319
320 // Step 1: Replace transitions
321 TransSet originalTransitions = rRes.TransRel(); // Get copy of original transition relation
322
324 for(tit = originalTransitions.Begin(); tit != originalTransitions.End(); ++tit) {
325 if(unobservableEvents.Exists(tit->Ev)) {
326 // This transition uses an unobservable event that should be replaced
327
328 // Remove original transition
329 rRes.ClrTransition(tit->X1, tit->Ev, tit->X2);
330
331 // Add new transition using epsilon
332 rRes.SetTransition(tit->X1, epsEvent, tit->X2);
333 }
334 }
335
336 // Step 2: Remove old unobservable events from alphabet
337 EventSet::Iterator uit;
338 for(uit = unobservableEvents.Begin(); uit != unobservableEvents.End(); ++uit) {
339 rRes.DelEvent(*uit);
340 }
341}
342
343void EpsObservation(const System& rGen, System& rRes) {
344 rRes = rGen; // Copy original generator
345
346 // Get unobservable events
347 EventSet unobservableEvents = rRes.UnobservableEvents();
348
349 // If no unobservable events, return original generator
350 if(unobservableEvents.Size() == 0) {
351 return;
352 }
353
354 // Create single epsilon event
355 std::string epsEventName = "eps";
356 Idx epsEvent = rRes.InsEvent(epsEventName);
357
358 // Set epsilon event as uncontrollable and unobservable
359 rRes.ClrControllable(epsEvent);
360 rRes.ClrObservable(epsEvent);
361 rRes.ClrForcible(epsEvent);
362
363 // Step 1: Replace transitions
364 TransSet originalTransitions = rRes.TransRel(); // Get copy of original transition relation
365
367 for(tit = originalTransitions.Begin(); tit != originalTransitions.End(); ++tit) {
368 if(unobservableEvents.Exists(tit->Ev)) {
369 // This transition uses an unobservable event that should be replaced
370
371 // Remove original transition
372 rRes.ClrTransition(tit->X1, tit->Ev, tit->X2);
373
374 // Add new transition using epsilon
375 rRes.SetTransition(tit->X1, epsEvent, tit->X2);
376 }
377 }
378
379 // Step 2: Remove old unobservable events from alphabet
380 EventSet::Iterator uit;
381 for(uit = unobservableEvents.Begin(); uit != unobservableEvents.End(); ++uit) {
382 rRes.DelEvent(*uit);
383 }
384}
385
386// ============================================================================
387// Language Verification Functions
388// ============================================================================
389
390Generator CreateMutedAutomaton(const Generator& rOriginal, const StateSet& rStatesToMute) {
391 Generator muted = rOriginal;
392
393 // Remove transitions to and from muted states
394 TransSet::Iterator tit = muted.TransRelBegin();
395 while (tit != muted.TransRelEnd()) {
396 if (rStatesToMute.Exists(tit->X1) || rStatesToMute.Exists(tit->X2)) {
397 TransSet::Iterator tit_del = tit;
398 ++tit;
399 muted.ClrTransition(*tit_del);
400 } else {
401 ++tit;
402 }
403 }
404
405 // Remove muted states from state set
406 StateSet::Iterator sit;
407 for (sit = rStatesToMute.Begin(); sit != rStatesToMute.End(); ++sit) {
408 if (muted.ExistsState(*sit)) {
409 muted.DelState(*sit);
410 }
411 }
412
413 return muted;
414}
415
416bool RabinLanguageInclusion(const System& rGenL, const RabinAutomaton& rRabK) {
417 FD_DF("RabinLanguageInclusion(): Starting language inclusion verification");
418
419 // Step 1: Create copies of genL and rabK
420 Generator genL_copy = rGenL; // Buechi automaton to accept L
421 RabinAutomaton rabK_copy = rRabK; // Rabin automaton to accept K
422
423 // Step 2: Apply BuechiTrim and RabinTrim respectively
424 bool genL_trim_result = IsBuechiTrim(genL_copy);
425 bool rabK_trim_result = IsRabinTrim(rabK_copy);
426
427 if (!genL_trim_result) {
428 FD_DF("RabinLanguageInclusion(): genL trim failed");
429 return false;
430 }
431
432 if (!rabK_trim_result) {
433 FD_DF("RabinLanguageInclusion(): rabK trim failed");
434 return false;
435 }
436
437 // Step 3: Mark all states to generate closure(L) and closure(K)
438 genL_copy.InjectMarkedStates(genL_copy.States());
439 rabK_copy.InjectMarkedStates(rabK_copy.States());
440
441 // Step 4: Test ordinary *-language inclusion: closure(L) ⊆ closure(K)
442 bool closure_inclusion = LanguageInclusion(genL_copy, rabK_copy);
443
444 if (closure_inclusion) {
445 std::cout << "✓ closure(SupervisedSystem) ⊆ closure(specification)" << std::endl;
446 return true;
447 }
448 else {
449 std::cout << "RabinLanguageInclusion(): Closure inclusion failed - bailing out" << std::endl;
450 return false;
451 }
452
453 // Step 5: Use Automaton() on original genL and rabK to make them full
454 Generator genL_full = rGenL;
455 RabinAutomaton rabK_full = rRabK;
456
457 // Make automata complete (full)
458 genL_full.Complete();
459 rabK_full.Complete();
460
461 FD_DF("RabinLanguageInclusion(): Step 5: Made automata complete - genL: " << genL_full.Size()
462 << " states, rabK: " << rabK_full.Size() << " states");
463
464 // Step 6: Use RabinBuechiAutomaton to construct product system
465 RabinAutomaton rgProduct;
466 RabinBuechiAutomaton(rabK_full, genL_full, rgProduct);
467 rgProduct.Name("Product System (rabK x genL)");
468
469 if (rgProduct.Size() == 0) {
470 FD_DF("RabinLanguageInclusion(): Empty product system - languages are disjoint");
471 return false;
472 }
473
474 // Make product accessible
475 rgProduct.Accessible();
476
477 // Step 7: Continue with SCC analysis on rgProduct
478
479 // Identify L-marked states in product (corresponding to genL marked states)
480 StateSet lMarkedInProduct;
481 StateSet::Iterator sit;
482 for (sit = rgProduct.StatesBegin(); sit != rgProduct.StatesEnd(); ++sit) {
483 if (rgProduct.ExistsMarkedState(*sit)) {
484 lMarkedInProduct.Insert(*sit);
485 }
486 }
487
488 FD_DF("RabinLanguageInclusion(): Found " << lMarkedInProduct.Size() << " L-marked states in product");
489
490 // Process each Rabin pair from original specification
491 const RabinAcceptance& acceptance = rRabK.RabinAcceptance();
492 RabinAcceptance::CIterator rait;
493
494 for (rait = acceptance.Begin(); rait != acceptance.End(); ++rait) {
495 const StateSet& R = rait->RSet(); // R set (must be visited infinitely often)
496 const StateSet& I = rait->ISet(); // I set (complement will be muted)
497
498 FD_DF("RabinLanguageInclusion(): Processing Rabin pair: R=" << R.ToString() << ", I=" << I.ToString());
499
500 // Create states to mute: L-marked states + complement of I
501 StateSet statesToMute = lMarkedInProduct;
502
503 // Add complement of I to muted states
504 for (sit = rgProduct.StatesBegin(); sit != rgProduct.StatesEnd(); ++sit) {
505 if (!I.Exists(*sit)) {
506 statesToMute.Insert(*sit);
507 }
508 }
509
510 FD_DF("RabinLanguageInclusion(): Muting " << statesToMute.Size() << " states (L-marked + complement of I)");
511
512 // Create muted automaton
513 Generator mutedProduct = CreateMutedAutomaton(rgProduct, statesToMute);
514
515 if (mutedProduct.Size() == 0) {
516 FD_DF("RabinLanguageInclusion(): Muted product is empty - continuing to next Rabin pair");
517 continue;
518 }
519
520 // Compute SCCs in muted product using libFAUDES function
521 std::list<StateSet> sccList;
522 StateSet sccRoots;
523 ComputeScc(mutedProduct, sccList, sccRoots);
524
525 FD_DF("RabinLanguageInclusion(): Found " << sccList.size() << " SCCs in muted system");
526
527 // Check if any SCC contains R-marked states
528 bool foundProblematicSCC = false;
529 std::list<StateSet>::iterator sccIt;
530 int sccIndex = 0;
531 for (sccIt = sccList.begin(); sccIt != sccList.end(); ++sccIt, ++sccIndex) {
532 bool hasRMarked = false;
533 StateSet::Iterator sccit;
534 for (sccit = sccIt->Begin(); sccit != sccIt->End(); ++sccit) {
535 if (R.Exists(*sccit)) {
536 hasRMarked = true;
537 break;
538 }
539 }
540
541 if (hasRMarked && sccIt->Size() > 1) { // Non-trivial SCC with R-marked state
542 FD_DF("RabinLanguageInclusion(): Found problematic SCC " << sccIndex << " with R-marked states");
543 foundProblematicSCC = true;
544 break;
545 }
546 }
547
548 if (foundProblematicSCC) {
549 FD_DF("RabinLanguageInclusion(): Language inclusion violated for Rabin pair");
550 return false;
551 }
552 }
553
554 FD_DF("RabinLanguageInclusion(): All tests passed - language inclusion L ⊆ K holds");
555 return true;
556}
557
558} // namespace faudes
#define FD_DF(message)
virtual const char * What() const
const std::string & Name(void) const
bool Exists(const Idx &rIndex) const
StateSet & RSet(void)
StateSet & ISet(void)
Iterator Begin(void)
Iterator Begin(void) const
Iterator End(void) const
virtual void Clear(void)
bool InsEvent(Idx index)
const TaStateSet< StateAttr > & States(void) const
const TaEventSet< EventAttr > & Alphabet(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
const ATransSet & TransRel(void) const
const Attr & Attribute(const Idx &rElem) const
void ClrControllable(Idx index)
void ClrObservable(Idx index)
EventSet ControllableEvents(void) const
void SetControllable(Idx index)
void ClrForcible(Idx index)
EventSet UnobservableEvents(void) const
EventSet ObservableEvents(void) const
void RabinAcceptance(const faudes::RabinAcceptance &rRabAcc)
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
bool SetTransition(Idx x1, Idx ev, Idx x2)
TransSet::Iterator TransRelBegin(void) const
void ClrTransition(Idx x1, Idx ev, Idx x2)
bool DelEvent(Idx index)
void InjectMarkedStates(const StateSet &rNewMarkedStates)
Idx MarkedStatesSize(void) const
void SetInitState(Idx index)
bool ExistsState(Idx index) const
bool DelState(Idx index)
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
bool IsDeterministic(void) const
void SetMarkedState(Idx index)
bool Empty(void) const
StateSet::Iterator InitStatesEnd(void) const
Idx TransRelSize(void) const
std::string EventName(Idx index) const
Idx Size(void) const
virtual void Clear(void)
bool ExistsMarkedState(Idx index) const
const StateSet & States(void) const
void InjectAlphabet(const EventSet &rNewalphabet)
bool Empty(void) const
bool Exists(const T &rElem) const
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
Idx Size(void) const
vGenerator Generator
bool LanguageInclusion(const Generator &rGen1, const Generator &rGen2)
bool ComputeScc(const Generator &rGen, const SccFilter &rFilter, std::list< StateSet > &rSccList, StateSet &rRoots)
void Product(const Generator &rGen1, const Generator &rGen2, Generator &rResGen)
void RabinBuechiAutomaton(const RabinAutomaton &rRAut, const Generator &rBAut, RabinAutomaton &rRes)
void RabinBuechiProduct(const RabinAutomaton &rRAut, const Generator &rBAut, RabinAutomaton &rRes)
bool IsRabinTrim(const RabinAutomaton &rRAut)
void PseudoDet(const RabinAutomaton &rGen, RabinAutomaton &rRes)
uint32_t Idx
void RabinCtrlPartialObs(const System &rPlant, const RabinAutomaton &rSpec, RabinAutomaton &rSupervisor)
Rabin control synthesis under partial observation (System interface)
void ExtractEventAttributes(const System &rSys, EventSet &rControllableEvents, EventSet &rObservableEvents)
Extract controllable and observable events from System attributes.
bool RabinLanguageInclusion(const System &rGenL, const RabinAutomaton &rRabK)
Verify language inclusion for Rabin automata.
void ControlAut(const RabinAutomaton &rsDRA, const TaIndexSet< EventSet > &rController, Generator &rRes)
Apply controller to filter transitions and create Buchi automaton.
TrGenerator< RabinAcceptance, AttributeVoid, AttributeCFlags, AttributeVoid > RabinAutomaton
Generator CreateMutedAutomaton(const Generator &rOriginal, const StateSet &rStatesToMute)
Create muted automaton by removing specified states and their transitions.
bool IsBuechiTrim(const vGenerator &rGen)
void RabinCtrlPartialObsConsistencyCheck(const RabinAutomaton &rPlant, const RabinAutomaton &rSpec, const EventSet &rControllableEvents, const EventSet &rObservableEvents)
Check consistency of control problem setup.
void EpsObservation(const RabinAutomaton &rGen, RabinAutomaton &rRes)
Epsilon observation for Rabin automata.

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen