omg_hoa.cpp
Go to the documentation of this file.
1 /** @file omg_hoa.cpp Serialisation in HOA format */
2 
3 /* FAU Discrete Event Systems Library (libFAUDES)
4 
5 Copyright (C) 2025 Thomas Moor
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 
24 #include "omg_hoa.h"
25 
26 #pragma GCC diagnostic push
27 #pragma GCC diagnostic ignored "-Wunused-private-field"
28 #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
29 #include "cpphoafparser/consumer/hoa_intermediate_trace.hh"
30 #include "cpphoafparser/consumer/hoa_intermediate_resolve_aliases.hh"
31 #include "cpphoafparser/parser/hoa_parser.hh"
32 #include "cpphoafparser/parser/hoa_parser_helper.hh"
33 #include "cpphoafparser/parser/hoa_parser_exception.hh"
34 #include "cpphoafparser/util/implicit_edge_helper.hh"
35 #include "cpphoafparser/consumer/hoa_consumer.hh"
36 #pragma GCC diagnostic pop
37 
38 // local debug
39 //#undef FD_DF
40 //#define FD_DF(m) FD_WARN(m)
41 
42 namespace faudes {
43 
44 // helper function: convert bit vector to HOA boolean expression
45 std::string omg_hoa_bits2expr(uint32_t bits, int apc) {
46  std::string res;
47  for(int i=0;i<apc;i++) {
48  if(bits & (1L << i)) res+=faudes::ToStringInteger(i);
49  else res+= "!"+faudes::ToStringInteger(i);
50  if(i+1<apc) res+=" & ";
51  }
52  FD_DF("hoa_bits2explr: bits " << bits << " expr " << res);
53  return res;
54 }
55 
56 // write in HOA format
57 void omg_export_hoa(std::ostream& rOutStream, const Generator& rAut, SymbolTable* pSymTab){
58  // inspectors
59  EventSet::Iterator eit;
60  EventSet::Iterator eit_end;
61  StateSet::Iterator sit;
62  StateSet::Iterator sit_end;
64  TransSet::Iterator tit_end;
65  // write Buechi automaton in HOA format: intro
66  rOutStream << "HOA: v1" << std::endl;
67  rOutStream << "name: \"" << rAut.Name() << "\""<< std::endl;
68  // figure number of atomic propositions
69  uint32_t asz=rAut.Alphabet().Size();
70  int apc=1;
71  for(;asz>2;asz=(asz>>1))
72  apc++;
73  //FD_WARN("Atomic propositions: apc " << apc << " asz " << asz);
74  rOutStream << "AP: " << apc;
75  for(int i=0; i<apc; ++i)
76  rOutStream << " \"ap"<<i<<"\"";
77  rOutStream << std::endl;
78  // set up event mapping
79  std::map<Idx,uint32_t> ev2bits;
80  std::map<Idx,std::string> ev2expr;
81  uint32_t cnt=0;
82  eit=rAut.AlphabetBegin();
83  eit_end=rAut.AlphabetEnd();
84  for(;eit!=eit_end;++eit) {
85  ev2bits[*eit]=cnt;
86  ev2expr[*eit]=omg_hoa_bits2expr(cnt,apc);
87  cnt++;
88  }
89  // write event aliases and set up symbol table
90  if(pSymTab) pSymTab->Clear();
91  eit=rAut.AlphabetBegin();
92  eit_end=rAut.AlphabetEnd();
93  for(;eit!=eit_end;++eit) {
94  rOutStream << "Alias: @" << rAut.EventName(*eit) << " " << ev2expr[*eit] << std::endl;
95  if(pSymTab)
96  pSymTab->InsEntry(ev2bits[*eit]+1,rAut.EventName(*eit));
97  }
98  // write initial states
99  rOutStream << "Start:";
100  sit=rAut.InitStatesBegin();
101  sit_end=rAut.InitStatesEnd();
102  for(;sit!=sit_end;++sit)
103  rOutStream << " " << (*sit)-1;
104  rOutStream << std::endl;
105  // write number of states
106  rOutStream << "States: " << rAut.States().Size() << std::endl;
107  // configure for Buchi acceptance
108  rOutStream << "Acceptance: 1 Inf(0)" << std::endl;
109  rOutStream << "acc-name: Buchi" << std::endl;
110  // do the graph structure
111  rOutStream << "--BODY--" << std::endl;
112  // iterate over all states
113  sit=rAut.StatesBegin();
114  sit_end=rAut.StatesEnd();
115  for(;sit!=sit_end;++sit) {
116  // state section
117  rOutStream << "State: " << (*sit)-1;
118  if(rAut.ExistsMarkedState(*sit)) {
119  rOutStream << " {0}";
120  }
121  rOutStream << std::endl;
122  // iterate over transitions from this state
123  tit=rAut.TransRelBegin(*sit);
124  tit_end=rAut.TransRelEnd(*sit);
125  for(;tit!=tit_end;++tit)
126  rOutStream << "[@" << rAut.EventName(tit->Ev) << "] " << tit->X2-1 << std::endl;
127  }
128  // end of graph
129  rOutStream << "--END--" << std::endl;
130 }
131 
132 // API wrapper
133 void ExportHoa(std::ostream& rOutStream, const Generator& rAut, SymbolTable* pSymTab){
134  // refuse trivial
135  if(rAut.States().Size() <1) {
136  throw Exception("ExportHoa", "refusing to export generator with no states", 80);
137  }
138  if(rAut.Alphabet().Size() <1) {
139  throw Exception("ExportHoa", "refusing to export generator with no events", 80);
140  }
141  // do export and catch ios errors
142  try {
143  omg_export_hoa(rOutStream,rAut,pSymTab);
144  } catch (std::ios::failure&) {
145  throw Exception("ExportHoa", "Exception writing to anonymous stream", 2);
146  }
147 }
148 
149 // API wrapper
150 void ExportHoa(const std::string& rFilename, const Generator& rAut, SymbolTable* pSymTab){
151  // refuse trivial
152  if(rAut.States().Size() <1) {
153  throw Exception("ExportHoa", "refusing to export generator with no states", 80);
154  }
155  if(rAut.Alphabet().Size() <1) {
156  throw Exception("ExportHoa", "refusing to export generator with no events", 80);
157  }
158  // open file
159  std::ofstream fout;
160  fout.exceptions(std::ios::badbit|std::ios::failbit);
161  try{
162  fout.open(rFilename.c_str(), std::ios::out|std::ios::trunc);
163  }
164  catch (std::ios::failure&) {
165  std::stringstream errstr;
166  errstr << "Exception opening file \""<< rFilename << "\"";
167  throw Exception("ExportHoa", errstr.str(), 2);
168  }
169  // do export and catch ios exceptions
170  try {
171  omg_export_hoa(fout,rAut,pSymTab);
172  } catch (std::ios::failure&) {
173  std::stringstream errstr;
174  errstr << "Exception weriting to file \""<< rFilename << "\"";
175  throw Exception("ExportHoa", errstr.str(), 2);
176  }
177 }
178 
179 
180 // helper bit vector to faudes event name
181 std::string omg_hoa_bits2event(uint32_t bits, int apc) {
182  std::string res="ev";;
183  for(int i=apc-1;i>=0;--i) {
184  if(bits & (1L << i)) res+="1";
185  else res+= "0";
186  }
187  return res;
188 }
189 
190 // cpphoaparser comsumer to read to generator
191 using namespace cpphoafparser;
192 class HOAConsumerFaudes : public cpphoafparser::HOAConsumer {
193 public:
194  /** Constructor, holding a reference to the generator to read to */
196  rAut(aut), rSymTab(syms), mImplEdgeHlp(0) {}
197  /** Constructs a HOAParserExeption to indicate an unsupported but presumably relevent feature */
198  HOAParserException error(const std::string& msg) {
199  std::stringstream ss;
200  ss << "HOAConsumerFaudes: unsupported feature: " << msg;
201  return HOAParserException(ss.str());
202  }
203  // Unsure about this feature (tmoor)
204  virtual bool parserResolvesAliases() override {
205  return false;
206  }
207  // consume start of header
208  virtual void notifyHeaderStart(const std::string& version) override {
209  // should we the check version?
210  rAut.Clear();
211  }
212  // consume "States:"
213  virtual void setNumberOfStates(unsigned int numberOfStates) override {
214  for(unsigned int i=0;i<numberOfStates;++i) rAut.InsState(i+1);
215  }
216  // consume "Start:"
217  virtual void addStartStates(const int_list& stateConjunction) override {
218  for(unsigned int state : stateConjunction)
219  rAut.InsInitState(state+1);
220  }
221  // consume "Alias: @..."
222  virtual void addAlias(const std::string& name, label_expr::ptr labelExpr) override {
223  throw error("aliases");
224  }
225  // consume "AP: ... "
226  virtual void setAPs(const std::vector<std::string>& aps) override {
227  // record the names
228  int i=0;
229  for (const std::string& ap : aps)
230  mApSymbols[i++]=ap;
231  // set up alphabet
232  mApCount=aps.size();
233  unsigned int evcnt= 1L << mApCount;
234  for(uint32_t i=0;i<evcnt;++i) {
235  std::string evname=omg_hoa_bits2event(i,mApCount);
236  if(rSymTab.Exists(i+1)) // todo: consider to mute unknown
237  evname=rSymTab.Symbol(i+1);
238  rAut.InsEvent(evname);
239  mEdgeBitsToEvIdx[i]=rAut.EventIndex(evname);
240  }
241  }
242  // consume "ACC: ..."
243  virtual void setAcceptanceCondition(unsigned int numberOfSets, acceptance_expr::ptr accExpr) override {
244  if(mRabin) {
245  rAut.RabinAcceptance().Size((numberOfSets+1)/2);
246  return;
247  }
248  throw error("ACC befor acc-name");
249  }
250  // consume "acc-name: ..."
251  virtual void provideAcceptanceName(const std::string& name, const std::vector<IntOrString>& extraInfo) override {
252  if(name=="Rabin")
253  mRabin=true;
254  if(name=="Buchi")
255  mBuechi=true;
256  // can only deal with Rabin
257  if(!mRabin)
258  throw error("acc-name must be Rabin");
259  }
260  // consume "Name: ..."
261  virtual void setName(const std::string& name) override {
262  rAut.Name(name);
263  }
264  // consume "tool: ..."
265  virtual void setTool(const std::string& name, std::shared_ptr<std::string> version) override {
266  }
267  // consume "properties: ..."
268  virtual void addProperties(const std::vector<std::string>& properties) override {
269  }
270  // consume misc
271  virtual void addMiscHeader(const std::string& name, const std::vector<IntOrString>& content) override {
272  }
273  // start graph data
274  virtual void notifyBodyStart() override {
275  mImplEdgeHlp = ImplicitEdgeHelper(mApCount);
276  }
277  // comsume "State: ..."
278  virtual void addState(unsigned int id,
279  std::shared_ptr<std::string> info,
280  label_expr::ptr labelExpr,
281  std::shared_ptr<int_list> accSignature) override {
282  if (labelExpr) {
283  throw error("state label expression");
284  }
285  // have the state (redundant)
286  rAut.InsState(id+1);
287  // record to acceptance condition
288  if (accSignature) {
289  for (unsigned int acc : *accSignature) {
290  RabinPair& rpair = rAut.RabinAcceptance().At(acc/2);
291  bool rnoti = acc%2;
292  if(rnoti) rpair.RSet().Insert(id+1);
293  else rpair.ISet().Insert(id+1);
294  }
295  }
296  // reset event index for implicit edges to come
297  mImplEdgeHlp.startOfState(id);
298  }
299  // cosume implicit edge, i.e., conscutive labels
300  virtual void addEdgeImplicit(
301  unsigned int stateId,
302  const int_list& conjSuccessors,
303  std::shared_ptr<int_list> accSignature) override
304  {
305  if (accSignature)
306  throw error("transition marking");
307  uint32_t edgebits = mImplEdgeHlp.nextImplicitEdge();
308  Idx evindex=mEdgeBitsToEvIdx[edgebits]; // todo: guard this, e.g. mute unknown
309  for (unsigned int succ : conjSuccessors)
310  rAut.SetTransition(stateId+1,evindex,succ+1);
311  }
312  // consume expilcit tarnsitio
313  virtual void addEdgeWithLabel(unsigned int stateId,
314  label_expr::ptr labelExpr,
315  const int_list& conjSuccessors,
316  std::shared_ptr<int_list> accSignature) override
317  {
318  throw error("explicit edge label");
319  /*
320  if (labelExpr) {
321  std::cerr << "[" << *labelExpr << "] ";
322  }
323  */
324  }
325  // end of graph data
326  virtual void notifyEndOfState(unsigned int stateId) override {
327  mImplEdgeHlp.endOfState();
328  }
329  // end of body
330  virtual void notifyEnd() override {
331  // invert ISets
332  RabinAcceptance::Iterator rit=rAut.RabinAcceptance().Begin();
333  for(;rit!=rAut.RabinAcceptance().End();++rit)
334  rit->ISet()=rAut.States() - rit->ISet();
335  }
336  // some sort of parser error
337  virtual void notifyAbort() override {
338  std::cerr << "HAO parser: abort" << std::endl;
339  std::cerr.flush();
340  }
341  // some sort of parser warning
342  virtual void notifyWarning(const std::string& warning) override {
343  std::cerr << "HAO parser: Warning: " << warning << std::endl;
344  std::cerr.flush();
345  }
346 
347 private:
348 
349  /** Payload: automaton to parse to */
352 
353  /** Payload: intermediate parsing results */
354  bool mRabin=false;
355  bool mBuechi=false;
356  int mApCount=0;
357  std::map<int,std::string> mApSymbols;
358  ImplicitEdgeHelper mImplEdgeHlp;
359  std::map<uint32_t,Idx> mEdgeBitsToEvIdx;
360 };
361 
362 
363 // read from HOA formated tream
364  void ImportHoa(std::istream& rInStream, RabinAutomaton& rAut, const SymbolTable* pSymTab, bool resolve, bool trace){
365  // symboltable incl fallback
366  static SymbolTable syms;
367  const SymbolTable* psyms=&syms;
368  if(pSymTab)
369  psyms=pSymTab;
370  // configure parser
371  HOAConsumer::ptr consumer(new HOAConsumerFaudes(rAut,*psyms));
372  if(resolve)
373  consumer.reset(new HOAIntermediateResolveAliases(consumer));
374  if(trace)
375  consumer.reset(new HOAIntermediateTrace(consumer));
376  // run parser
377  try {
378  HOAParser::parse(rInStream, consumer, true);
379  } catch (HOAParserException& e) {
380  std::cerr << e.what() << std::endl; // todo: forward als faudes exception
381  } catch (HOAConsumerException& e) {
382  std::cerr << "Exception: " << e.what() << std::endl; // todo: forward als faudes exception
383  }
384 };
385 
386 // API wrapper
387 void ImportHoa(const std::string& rFilename, RabinAutomaton& rAut, const SymbolTable* pSymTab, bool resolve, bool trace) {
388  // open file
389  std::ifstream fin;
390  fin.exceptions(std::ios::badbit); // dont throw on failbit because the hoa patrser will provoke that
391  try{
392  fin.open(rFilename.c_str(), std::ios::in | std::ios::binary);
393  }
394  catch (std::ios::failure&) {
395  std::stringstream errstr;
396  errstr << "Exception opening file \""<< rFilename << "\"";
397  throw Exception("ImportHoa", errstr.str(), 2);
398  }
399  // pass on
400  ImportHoa(fin,rAut,pSymTab,resolve,trace);
401 }
402 
403 } // namespace faudes
404 
#define FD_DF(message)
const std::string & Name(void) const
Definition: cfl_types.cpp:422
virtual void addEdgeWithLabel(unsigned int stateId, label_expr::ptr labelExpr, const int_list &conjSuccessors, std::shared_ptr< int_list > accSignature) override
Definition: omg_hoa.cpp:313
virtual void setName(const std::string &name) override
Definition: omg_hoa.cpp:261
virtual void setAcceptanceCondition(unsigned int numberOfSets, acceptance_expr::ptr accExpr) override
Definition: omg_hoa.cpp:243
HOAConsumerFaudes(RabinAutomaton &aut, const SymbolTable &syms)
Definition: omg_hoa.cpp:195
virtual void setAPs(const std::vector< std::string > &aps) override
Definition: omg_hoa.cpp:226
virtual void notifyEnd() override
Definition: omg_hoa.cpp:330
virtual void setTool(const std::string &name, std::shared_ptr< std::string > version) override
Definition: omg_hoa.cpp:265
ImplicitEdgeHelper mImplEdgeHlp
Definition: omg_hoa.cpp:358
virtual void addStartStates(const int_list &stateConjunction) override
Definition: omg_hoa.cpp:217
virtual bool parserResolvesAliases() override
Definition: omg_hoa.cpp:204
virtual void provideAcceptanceName(const std::string &name, const std::vector< IntOrString > &extraInfo) override
Definition: omg_hoa.cpp:251
virtual void notifyEndOfState(unsigned int stateId) override
Definition: omg_hoa.cpp:326
HOAParserException error(const std::string &msg)
Definition: omg_hoa.cpp:198
virtual void addState(unsigned int id, std::shared_ptr< std::string > info, label_expr::ptr labelExpr, std::shared_ptr< int_list > accSignature) override
Definition: omg_hoa.cpp:278
virtual void notifyHeaderStart(const std::string &version) override
Definition: omg_hoa.cpp:208
virtual void addProperties(const std::vector< std::string > &properties) override
Definition: omg_hoa.cpp:268
RabinAutomaton & rAut
Definition: omg_hoa.cpp:350
virtual void addAlias(const std::string &name, label_expr::ptr labelExpr) override
Definition: omg_hoa.cpp:222
virtual void notifyWarning(const std::string &warning) override
Definition: omg_hoa.cpp:342
virtual void notifyBodyStart() override
Definition: omg_hoa.cpp:274
std::map< int, std::string > mApSymbols
Definition: omg_hoa.cpp:357
virtual void notifyAbort() override
Definition: omg_hoa.cpp:337
virtual void setNumberOfStates(unsigned int numberOfStates) override
Definition: omg_hoa.cpp:213
std::map< uint32_t, Idx > mEdgeBitsToEvIdx
Definition: omg_hoa.cpp:359
const SymbolTable & rSymTab
Definition: omg_hoa.cpp:351
virtual void addEdgeImplicit(unsigned int stateId, const int_list &conjSuccessors, std::shared_ptr< int_list > accSignature) override
Definition: omg_hoa.cpp:300
virtual void addMiscHeader(const std::string &name, const std::vector< IntOrString > &content) override
Definition: omg_hoa.cpp:271
StateSet & RSet(void)
Definition: omg_rabinacc.h:68
StateSet & ISet(void)
Definition: omg_rabinacc.h:84
Idx InsEntry(Idx index, const std::string &rName)
TBaseSet< Transition, TransSort::X1EvX2 >::Iterator Iterator
Definition: cfl_transset.h:273
StateSet::Iterator StatesBegin(void) const
StateSet::Iterator InitStatesBegin(void) const
const EventSet & Alphabet(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
std::string EventName(Idx index) const
EventSet::Iterator AlphabetEnd(void) const
bool ExistsMarkedState(Idx index) const
const StateSet & States(void) const
Idx Size(void) const
Definition: cfl_baseset.h:1782
void ExportHoa(std::ostream &rOutStream, const Generator &rAut, SymbolTable *pSymTab)
Definition: omg_hoa.cpp:133
void ImportHoa(std::istream &rInStream, RabinAutomaton &rAut, const SymbolTable *pSymTab, bool resolve, bool trace)
Definition: omg_hoa.cpp:364
uint32_t Idx
std::string omg_hoa_bits2event(uint32_t bits, int apc)
Definition: omg_hoa.cpp:181
void omg_export_hoa(std::ostream &rOutStream, const Generator &rAut, SymbolTable *pSymTab)
Definition: omg_hoa.cpp:57
std::string omg_hoa_bits2expr(uint32_t bits, int apc)
Definition: omg_hoa.cpp:45
std::string ToStringInteger(Int number)
Definition: cfl_utils.cpp:43

libFAUDES 2.33h --- 2025.06.18 --- c++ api documentaion by doxygen