hyb_experiment.cpp
Go to the documentation of this file.
1/** @file hyb_experiment.cpp Exhaustive experments on linear hybrid automata */
2
3/*
4 Hybrid systems plug-in for FAU Discrete Event Systems Library
5
6 Copyright (C) 2017 Thomas Moor, Stefan Goetz
7
8*/
9
10#include "hyb_experiment.h"
11#include "hyb_compute.h"
12#include "hyb_reachability.h"
13
14using namespace faudes;
15
16// consructor
18 mpRoot(0),
19 rAlphabet(alph)
20{
21 Clear();
22}
23
24// destructor
26 Clear();
27 delete mpRoot;
28}
29
30// clear all
32 // free nodes
33 Iterator nit=mNodeMap.begin();
34 for(;nit!=mNodeMap.end();++nit) {
35 delete nit->second->mpStates;
36 delete nit->second;
37 }
38 mNodeMap.clear();
39 // setup root
40 mpRoot = new Node;
41 Index(mpRoot)=1;
43 mLeaves.Clear();
44 mLeaves.Insert(1);
45 // aux data
46 mCost=0;
47}
48
49// must set initialstates (we take ownership)
51 if(mpRoot->mpStates) Clear();
52 mpRoot->mpStates = istates;
53}
54
55
56// size
57Idx Experiment::Size(void) const {
58 return mNodeMap.size();
59}
60
61const EventSet& Experiment::Alphabet(void) const{
62 return rAlphabet;
63}
64
65
66// navigate tree, external interface
67Idx Experiment::Root(void) const {
68 return Index(mpRoot);
69}
71 const Node* node = NodePtr(nid);
72 if(!node) {
73 std::stringstream errstr;
74 errstr << "Node #" << nid << " unknown.";
75 throw Exception("Experiment::EnabledEvents(..)", errstr.str(), 90);
76 }
77 EventSet res;
78 Node::Iterator cit = Children(node).begin();
79 Node::Iterator cit_end = Children(node).end();
80 for(;cit!=cit_end;++cit) res.Insert(cit->first);
81 return res;
82}
84 const Node* node = NodePtr(nid);
85 if(!node) return 0;
86 Node::Iterator cit = Children(node).find(ev);
87 if(cit==Children(node).end()) return 0;
88 return Index(cit->second);
89}
90bool Experiment::IsLeave(Idx nid) const {
91 const Node* node = NodePtr(nid);
92 if(!node) return false;
93 /*
94{
95 std::stringstream errstr;
96 errstr << "Node #" << nid << " unknown.";
97 throw Exception("Experiment::IsLeave(..)", errstr.str(), 90);
98 }
99 */
100 return IsLeave(node);
101}
102bool Experiment::IsLock(Idx nid) const {
103 const Node* node = NodePtr(nid);
104 if(!node) {
105 std::stringstream errstr;
106 errstr << "Node #" << nid << " unknown.";
107 throw Exception("Experiment::IsLock(..)", errstr.str(), 90);
108 }
109 return IsLock(node);
110}
112 const Node* node = NodePtr(nid);
113 if(!node) {
114 std::stringstream errstr;
115 errstr << "Node #" << nid << " unknown.";
116 throw Exception("Experiment::CStates(..)", errstr.str(), 90);
117 }
118 if(!node->mpStates) {
119 std::stringstream errstr;
120 errstr << "Node #" << nid << " no compatible states set.";
121 throw Exception("Experiment::CStates(..)", errstr.str(), 90);
122 }
123 return node->mpStates;
124}
125
126
127// access by sequence
128Idx Experiment::Find(const std::deque< Idx >& seq) const {
129 Node* node = mpRoot;
130 std::deque< Idx >::const_iterator eit= seq.begin();
131 std::deque< Idx >::const_iterator eit_end= seq.end();
132 for(;eit!=eit_end;++eit) {
133 Node::Iterator cit = Children(node).find(*eit);
134 if(cit==Children(node).end()) return 0;
135 node=cit->second;
136 }
137 return Index(node);
138}
139std::deque< Idx > Experiment::Sequence(Idx nid) const {
140 const Node* node=NodePtr(nid);
141 if(!node) {
142 std::stringstream errstr;
143 errstr << "Node #" << nid << " unknown.";
144 throw Exception("Experiment::Sequence(..)", errstr.str(), 90);
145 }
146 std::deque< Idx > res;
147 while(node!=mpRoot) {
148 res.push_front(RecEvent(node));
149 node=Parent(node);
150 }
151 return res;
152}
153
154
155
156// inspect for debugging
157void Experiment::DWrite(Idx nid) const{
158 FAUDES_WRITE_CONSOLE("% -------------------------------------------------------------------- ");
159 Node* node= NodePtr(nid);
160 if(!node) {
161 FAUDES_WRITE_CONSOLE("Node Idx " << nid << " (no such node) ");
162 return;
163 }
164 if(node==mpRoot) {
165 FAUDES_WRITE_CONSOLE("Node Idx " << Index(node) << " (Root) ");
166 } else {
167 if(!Parent(node)) {
168 FAUDES_WRITE_CONSOLE("Node Idx " << Index(node) << " No Parent (!) ");
169 } else {
170 FAUDES_WRITE_CONSOLE("Node Idx " << Index(node) << " Parent " << Index(Parent(node)));
171 }
172 }
173 std::deque<Idx> seq = Sequence(Index(node));
174 if(!seq.empty()) {
175 std::string msg;
176 std::deque<Idx>::const_iterator eit = seq.begin();
177 std::deque<Idx>::const_iterator eit_end = seq.end();
178 for(; eit!=eit_end;++eit){
179 msg.append(rAlphabet.SymbolicName(*eit));
180 msg.append(" ");
181 }
182 FAUDES_WRITE_CONSOLE("Event-sequence: " << msg);
183 }
184 if(States(node)) States(node)->DWrite();
185 if(Children(node).size()>0) {
186 std::stringstream msg;
187 Node::Iterator cit=Children(node).begin();
188 for(; cit!=Children(node).end(); ++cit){
189 msg << "(" << rAlphabet.SymbolicName(cit->first) << ")->(" << Index(cit->second) << ") ";
190 }
191 FAUDES_WRITE_CONSOLE(msg.str());
192 }
193}
194void Experiment::DWrite(void) const{
195 FAUDES_WRITE_CONSOLE("% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
196 FAUDES_WRITE_CONSOLE("% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
197 FAUDES_WRITE_CONSOLE("% Dumping experiment ... ");
198 Iterator nit=mNodeMap.begin();
199 for(;nit!=mNodeMap.end();++nit)
200 DWrite(nit->first);
201 FAUDES_WRITE_CONSOLE("% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
202 FAUDES_WRITE_CONSOLE("% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
203}
204
205void Experiment::SWrite(void) const{
206 FAUDES_WRITE_CONSOLE("% +++++++++++++++++++++++++++ ");
207 FAUDES_WRITE_CONSOLE("% Experiment Statistics");
208 std::vector<int> seqcnt;
209 std::vector<int> seqlck;
210 int lockcnt=0;
211 Iterator nit=mNodeMap.begin();
212 for(;nit!=mNodeMap.end();++nit) {
213 Node* node=nit->second;
214 if(seqcnt.size()<Depth(node)+1) {
215 seqcnt.resize(Depth(node)+1);
216 seqlck.resize(Depth(node)+1);
217 }
218 if(IsLeave(node)){
219 seqcnt[Depth(node)]++;
220 }
221 if(IsLock(node)) {
222 seqlck[Depth(node)]++;
223 lockcnt++;
224 }
225 }
226 std::stringstream rep;
227 for(unsigned int i=0; i<seqcnt.size(); ++i) {
228 if(seqcnt[i]==0) continue;
229 rep << "#" << seqcnt[i];
230 if(seqlck[i]>0) rep << "[locks #" << seqlck[i] << "]";
231 rep << "[@" << i << "] ";
232 }
233 FAUDES_WRITE_CONSOLE("% Nodes #" << Size() << " Leaves #" << Leaves().Size() << " Locks #" << lockcnt << " Cost #" << Cost());
234 if(mLeaves.Size()>0)
235 FAUDES_WRITE_CONSOLE("% " << rep.str());
236 FAUDES_WRITE_CONSOLE("% +++++++++++++++++++++++++++ ");
237}
238
239// reprot leaves
240const IndexSet& Experiment::Leaves(void) const {
241 /*
242 const_cast<Experiment*>(this)->mLeaves.Clear();
243 Iterator nit=mNodeMap.begin();
244 for(;nit!=mNodeMap.end();++nit)
245 if(IsLeave(nit->second)) const_cast<Experiment*>(this)->mLeaves.Insert(nit->first);
246 */
247 return mLeaves;
248}
249
250// do the job: refine at specified node
252 Node* node=NodePtr(idx);
253 if(!node) return; // should throw
254 if(!IsLeave(node)) return;
255 FAUDES_WRITE_CONSOLE("Experiment::RefineAt(..): node=#" << idx << " at depth=#" << Depth(node));
256 //DWrite(Index(node));
257 CompatibleStates* cstates = States(node);
258 if(!cstates) return; // should throw
259 // nothing to do
260 if(!IsLeave(node)) return;
261 if(IsLock(node)) return;
262 // do the job
263 cstates->ExecuteTransitions();
264 IsLock(node)=true;
265 mCost+=cstates->Cost();
266 // distribute results
267 EventSet::Iterator eit=rAlphabet.Begin();
268 EventSet::Iterator eit_end=rAlphabet.End();
269 for(; eit!=eit_end;++eit) {
270 CompatibleStates* nstates = cstates->TakeByEvent(*eit);
271 // null: emptyset
272 if(!nstates) continue;
273 // non-null: we take ownership; null: emptyset
274 Node* child=Insert(node,*eit);
275 States(child) = nstates;
276 IsLock(node)=false;
277 }
278 /*
279 if(IsLock(node)) {
280 FAUDES_WRITE_CONSOLE("no successor states --- record lock");
281 } else {
282 std::stringstream msg;
283 msg << "child nodes inserted at d=#" << Depth(node) << ": ";
284 Node::Iterator cit=Children(node).begin();
285 for(; cit!=Children(node).end(); ++cit){
286 msg << "(" << rAlphabet.SymbolicName(cit->first) << ")->(" << Index(cit->second) << ") ";
287 }
288 FAUDES_WRITE_CONSOLE(msg.str());
289 }
290 FAUDES_WRITE_CONSOLE("Experiment::RefineAt(..): done");
291 */
292}
293
294void Experiment::RefineUniformly(unsigned int depth) {
295 std::stack<Node*> todo;
296 todo.push(mpRoot);
297 while(!todo.empty()) {
298 Node* node=todo.top();
299 todo.pop();
300 if(Depth(node)>=depth) continue;
301 if(IsLock(node)) continue;
302 if(!IsLeave(node)) continue;
303 RefineAt(Index(node));
304 Node::Iterator cit=Children(node).begin();
305 Node::Iterator cit_end=Children(node).end();
306 for(;cit!=cit_end;++cit)
307 if(cit->second)
308 todo.push(cit->second);
309 }
310}
311
312// do the job: refine for a sequence (return final node or 0)
313Idx Experiment::RefineSequence(const std::deque< Idx >& seq) {
314 Node* node=mpRoot;
315 unsigned int cnt=0;
316 while(cnt<seq.size()) {
317 if(IsLock(node)) break;
318 if(IsLeave(node)) RefineAt(Index(node));
319 Node::Iterator cit = Children(node).find(seq.at(cnt));
320 if(cit == Children(node).end()) break;
321 node=cit->second;
322 cnt++;
323 }
324 if(cnt==seq.size()) return Index(node);
325 return 0;
326}
327
328
329
330/*
331********************************************************************************************
332********************************************************************************************
333
334Reachability analysis for DES
335
336********************************************************************************************
337********************************************************************************************
338*/
339
340// DES dynamics operator construct
344
345// DES dynamics operator destruct
347 std::map<Idx, StateSet*>::iterator sit=mReachSets.begin();
348 std::map<Idx, StateSet*>::iterator sit_end=mReachSets.end();
349 for(;sit!=sit_end;++sit) {
350 if(sit->second) delete sit->second;
351 }
352 delete mpStates;
353}
354
355// Optional initialisation
362
363// do the job
365 // lopp all events
366 EventSet::Iterator eit=rGen.AlphabetBegin();
367 EventSet::Iterator eit_end=rGen.AlphabetEnd();
368 for(; eit!=eit_end;++eit) {
369 StateSet* nstates=new StateSet;
370 nstates->Name("CompatibleStates");
371 // loop over all current states
372 StateSet::Iterator sit=mpStates->Begin();
373 StateSet::Iterator sit_end=mpStates->End();
374 for(; sit!=sit_end; ++sit ) {
375 TransSet::Iterator tit= rGen.TransRelBegin(*sit,*eit);
376 TransSet::Iterator tit_end= rGen.TransRelEnd(*sit,*eit);
377 for(; tit!=tit_end;++tit) nstates->Insert(tit->X2);
378 }
379 // continue in disabled event
380 if(nstates->Empty()) {delete nstates; continue;}
381 mReachSets[*eit]=nstates;
382 }
383}
384
385// pass on result (give away ownership)
387 std::map<Idx, StateSet*>::iterator sit=mReachSets.find(ev);
388 if(sit==mReachSets.end()) return 0;
389 if(sit->second==0) return 0;
391 delete res->mpStates;
392 res->mpStates= sit->second;
393 sit->second=0;
394 return res;
395}
396
397
398// dump
400 mpStates->DWrite();
401}
402
403
404/*
405********************************************************************************************
406********************************************************************************************
407
408Reachability analysis for LHA
409
410********************************************************************************************
411********************************************************************************************
412*/
413
414
415 // LHA dynamics operator construct
420
421// LHA dynamics operator destruct
423 std::map<Idx, HybridStateSet*>::iterator sit=mHybridReachSets.begin();
424 std::map<Idx, HybridStateSet*>::iterator sit_end=mHybridReachSets.end();
425 for(;sit!=sit_end;++sit) {
426 if(sit->second) delete sit->second;
427 }
428 delete mpStates;
429}
430
431// Optional initialisation
433 mpStates->Clear();
434 StateSet::Iterator qit=rLha.StatesBegin();
435 StateSet::Iterator qit_end=rLha.StatesEnd();
436 for(;qit!=qit_end;++qit){
437 Polyhedron* poly = new Polyhedron(rLha.StateSpace());
438 PolyFinalise(*poly);
439 mpStates->Insert(*qit,poly);
440 }
441}
443 FD_DF("LhaCompatibleStates::InitialiseConstraint()");
444 mpStates->Clear();
445 StateSet::Iterator qit=rLha.InitStatesBegin();
446 StateSet::Iterator qit_end=rLha.InitStatesEnd();
447 for(;qit!=qit_end;++qit){
448 Polyhedron* poly = new Polyhedron(rLha.InitialConstraint(*qit));
450 PolyFinalise(*poly);
451 mpStates->Insert(*qit,poly);
452 }
453 FD_DF("LhaCompatibleStates::InitialiseConstraint(): done");
454}
455
456// do the job
459 FD_DF("ExecuteTransitions():: found successors #" << mHybridReachSets.size());
460}
461
462// pass on result (give away ownership)
464 std::map<Idx, HybridStateSet*>::iterator sit=mHybridReachSets.find(ev);
465 if(sit==mHybridReachSets.end()) return 0;
466 if(sit->second==0) return 0;
468 delete res->mpStates;
469 res->mpStates= sit->second;
470 sit->second=0;
471 return res;
472}
473
474// dump
477}
478
479
480
481
482
#define FAUDES_WRITE_CONSOLE(message)
#define FD_DF(message)
virtual CompatibleStates * TakeByEvent(Idx ev)=0
virtual const int Cost(void)
virtual void DWrite(void) const =0
virtual void ExecuteTransitions(void)=0
virtual void DWrite(void) const
virtual DesCompatibleStates * TakeByEvent(Idx ev)
DesCompatibleStates(const Generator &gen)
std::map< Idx, StateSet * > mReachSets
virtual void ExecuteTransitions(void)
CompatibleStates * mpStates
Node * NodePtr(Idx idx) const
Idx RefineSequence(const std::deque< Idx > &seq)
Node * Insert(Node *parent, Idx ev)
std::map< Idx, Node * > & Children(Node *node)
bool IsLock(Idx nid) const
void DWrite(void) const
bool IsLeave(Idx nid) const
void RefineUniformly(unsigned int depth)
Idx Find(const std::deque< Idx > &seq) const
Idx & Index(Node *node)
EventSet EnabledEvents(Idx nid) const
Experiment(const EventSet &alph)
Idx Root(void) const
std::map< Idx, Node * > mNodeMap
Node *& Parent(Node *node)
const faudes::EventSet & rAlphabet
void InitialStates(CompatibleStates *istates)
Idx Size(void) const
const EventSet & Alphabet(void) const
const IndexSet & Leaves() const
Idx & RecEvent(Node *node)
std::deque< Idx > Sequence(Idx nid) const
std::map< Idx, Node * >::const_iterator Iterator
int Cost(void) const
void SWrite(void) const
const CompatibleStates * States(Idx nid) const
Idx SuccessorNode(Idx nid, Idx ev) const
Idx & Depth(Node *node)
const std::string & Name(void) const
void DWrite(const LinearHybridAutomaton &lha)
std::map< Idx, HybridStateSet * > mHybridReachSets
const LinearHybridAutomaton & rLha
virtual void DWrite(void) const
virtual void ExecuteTransitions(void)
LhaCompatibleStates(const LinearHybridAutomaton &lha)
virtual LhaCompatibleStates * TakeByEvent(Idx ev)
void SymbolicName(Idx index, const std::string &rName)
bool Insert(const Idx &rIndex)
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
const Polyhedron & InitialConstraint(Idx idx) const
const Polyhedron & StateSpace(void) const
void DWrite(const Type *pContext=0) const
virtual Type & Copy(const Type &rSrc)
Definition cfl_types.cpp:82
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
const StateSet & InitStates(void) const
TransSet::Iterator TransRelBegin(void) const
EventSet::Iterator AlphabetBegin(void) const
StateSet::Iterator StatesEnd(void) const
TransSet::Iterator TransRelEnd(void) const
StateSet::Iterator InitStatesEnd(void) const
EventSet::Iterator AlphabetEnd(void) const
const StateSet & States(void) const
bool Empty(void) const
IndexSet StateSet
virtual void Clear(void)
Iterator End(void) const
Iterator Begin(void) const
Idx Size(void) const
void PolyFinalise(const Polyhedron &fpoly)
void PolyIntersection(const Polyhedron &poly, Polyhedron &res)
uint32_t Idx
void LhaReach(const LinearHybridAutomaton &lha, const HybridStateSet &states, std::map< Idx, HybridStateSet * > &ostates, int *pCnt)

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