1_generator.cpp File Reference

Tutorial, Generator methods. More...

#include "libfaudes.h"
#include "configuration.h"
#include <cstdlib>
#include <cstring>
#include <limits>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <map>
#include <set>
#include <inttypes.h>
#include "doxygen_groups.h"
#include "cfl_platform.h"
#include "cfl_definitions.h"
#include "cfl_helper.h"
#include <exception>
#include "cfl_exception.h"
#include <list>
#include <vector>
#include <utility>
#include <typeinfo>
#include <algorithm>
#include <assert.h>
#include "cfl_token.h"
#include "cfl_types.h"
#include "cfl_registry.h"
#include "cfl_tokenreader.h"
#include "cfl_tokenwriter.h"
#include "cfl_attributes.h"
#include "cfl_functions.h"
#include "cfl_basevector.h"
#include "cfl_baseset.h"
#include "cfl_indexset.h"
#include "cfl_symboltable.h"
#include "cfl_abaseset.h"
#include "cfl_nameset.h"
#include "cfl_transset.h"
#include <cassert>
#include "cfl_generator.h"
#include <stack>
#include "cfl_agenerator.h"
#include "cfl_parallel.h"
#include "cfl_project.h"
#include "allplugins.h"

Go to the source code of this file.

Functions

int main ()

Detailed Description

Tutorial, Generator methods.

The Generator class implements the 5-tuple automaton G, consisting of

  • Set of States Q,
  • Alphabet Sigma,
  • Transition Relation Delta,
  • Set of Initial States Qo, and
  • Set of Marked States Qm.

This tutorial demonstrates how to insert/erase states, events and transitions. It also demonstrates file IO.

/** @file 1_generator.cpp 

Tutorial, Generator methods. 

The Generator class implements the 5-tuple automaton G, consisting of
- Set of States Q, 
- Alphabet Sigma, 
- Transition Relation Delta,
- Set of Initial States Qo, and
- Set of Marked States Qm.

This tutorial demonstrates how to insert/erase states, events and transitions. 
It also demonstrates file IO.

@ingroup Tutorials 

@include 1_generator.cpp
*/


#include "libfaudes.h"

// make faudes namespace available
using namespace faudes;



/////////////////
// main program
/////////////////

int main() {

  ////////////////////////////////////////////
  // Constructors (part 1) and filling example
  ////////////////////////////////////////////

  // at first we create an empty Generator object

  Generator g1;

  // do some random "user interaction" stuff with the Generator g1

  g1.InsState("s1");  
  g1.InsState("s2");                  
  g1.InsState("s3");                  

  g1.InsEvent("a");         
  g1.InsEvent("b");

  g1.SetTransition("s1", "a", "s2");  
  g1.SetTransition("s2", "a", "s3");  
  g1.SetTransition("s3", "b", "s1");

  g1.SetInitState("s1");              
  g1.SetMarkedState("s2");
  g1.SetMarkedState("s3");

  // inspect result on console

  std::cout << "################################\n";
  std::cout << "# tutorial, handcraft generator \n";
  g1.Write();
  std::cout << "################################\n";

  // record test case
  FAUDES_TEST_DUMP("g1", g1); 



  ///////////////////////////////////////////////////
  // Constructors (part 2) & Copying and versioning
  ///////////////////////////////////////////////////

  // Create a  1:1 copy of the Generator with the copy constructor ... 

  Generator g_copy(g1);

  // ... with assignment method, or assignement operator

  Generator g2;
  g2.Assign(g1);
  Generator g3=g2;

  // create a Generator copy with versioned events (for testing algorithms):
  // versioning by an integer. E.g. for integer 3 events {"a", "b", "c"}
  // become {"a_3", "b_3", "c_3"}.

  Generator version1;
  g3.Version(3, version1);

  // versioning by a string. "a" -> "a_versionstring"

  Generator version2;
  g3.Version("str", version2);

  // versioning by replacing a pattern  "_str" -> "_machine_3"

  Generator version3;
  version2.Version("_str", "_machine_3",version3);

  // editing by renaming an individual event

  version3.EventRename("a_machine_3","synch");

  // inspect result on console

  std::cout << "################################\n";
  std::cout << "# tutorial, version of generator \n";
  version3.Write();
  std::cout << "################################\n";

  // record test case
  FAUDES_TEST_DUMP("generator", version1); 


  ///////////////////////////////////////////////
  // Methods for Input/Output
  ///////////////////////////////////////////////

  // read a Generator from file 

  g2.Read("data/simplemachine.gen");

  // create a Generator by reading a Generator file

  Generator g4("data/simplemachine.gen");


  // write a Generator to file 

  g4.Write("tmp_simplemachine.gen");

  // write a Generator to file with re-indexed states
  
  g4.ReindexOnWrite(true);
  g4.Write("tmp_simplemachine_ridx.gen");

  // read back files (testing token io)
  g4.Read("tmp_simplemachine.gen");
  g4.Read("tmp_simplemachine_ridx.gen");

  // debug output of Generator to console 

  std::cout << "################################\n";
  std::cout << "# tutorial, debug dump \n";
  g4.DWrite();
  std::cout << "################################\n";

  // create dotfile for further processing by graphviz 
  // (map state indices to begin with 1)

  g4.DotWrite("tmp_simplemachine.dot"); 
  g4.DDotWrite("tmp_simplemachine_debug.dot");

  // there also is a convenience method, that runs graphviz to
  // generate graphical output; requires  "dot" binary in $PATH
  try {
    g4.GraphWrite("tmp_simplemachinie.png");
  } catch(faudes::Exception& exception) {
    std::cout << "1_generator: cannot execute graphviz' dot. " << std::endl;
  } 


  // create a debug string for an event with symbolic name + index

  std::string str_singleevent = g1.EStr(2);

  // create a debug string for a state with symbolic name + index.
  // If there is no symblic name, a symbolic name of the index is constructed.

  std::string str_singlestate = g1.SStr(3);

  // build string of events in the Generator's alphabet

  std::string str_alph =  g1.AlphabetToString();

  // build string of states in the Generator's set of states
  std::string str_states = g1.StatesToString();

  // there also are TransRelToString(), InitStatesToString() and  MarkedStatesToString()  


  //////////////////////////////////////
  // Accessing the Generator's Members
  //////////////////////////////////////

  // get the Generator's name

  std::string str_name = g1.Name();

  // set new name for Generator

  g1.Name("NewName");



  // the core members alphabet, stateset and transitionrelation may be retrieved 
  // as const references; ie. they can be inspected freely, but write access is 
  // exclusively via the provided Generator methods.

  // retrieve a const reference to and copy of the Generator's alphabet

  const EventSet&  eset_ref_alph  = g1.Alphabet();
  EventSet         eset_copy_alph = g1.Alphabet();

  // you cannot alter the alphabet of a generator via an  alphabet method
  // eset_ref_alph.Insert("new_event");  // compile time error!

  // however, the copy can be altered, but with no effect on the original generator

  eset_copy_alph.Insert("new_event"); 
  if(g1.ExistsEvent("new_event")) std::cout << "### THIS CANNOT HAPPEN ###";

  // retrieve a const reference to and copy of the Generator's set of states "mStates"

  const StateSet& sset_ref_states = g1.States();
  StateSet sset_copy_states = g1.States();

  // retrieve a const reference to and a copy of the Generator's transition relation "mTransRel"

  const TransSet& tset_ref_trel = g1.TransRel();
  TransSet tset_copy_trel = g1.TransRel();

  // same with initial states and marked states

  const StateSet& sset_ref_istates = g1.InitStates();
  StateSet sset_copy_istates = g1.InitStates();

  const StateSet& sset_ref_mstates = g1.MarkedStates();
  StateSet sset_copy_mstates = g1.MarkedStates();



  //////////////////////////////////////////////////////////////////////////////
  // Modifying the 5-tuple Generator (X, Sigma, Delta, X0 and Xm)
  //////////////////////////////////////////////////////////////////////////////

  // insert an event by it's symbolic name in the alphabet
  // (if the event is not known so far, a new index for the symbolic name is generated) 
  g1.InsEvent("newevent");


  // insert an existing event into the Generator's alphabet (mAlphabet)
  // (by "existing event" we refer to an event that has been previously inserted to some Generator)

  g1.InsEvent(1);   // of course index 1 is already in the alphabet here...

  // insert a bunch of events (EventSet) and get the integer index if requested

  EventSet eset1;
  eset1.Insert("newevent1");
  Idx idx_tmp = eset1.Insert("newevent2");
  g1.InsEvents(eset1);

  // delete an event from Generator ie delete from alphabet and transition relation

  g1.DelEvent("newevent1"); // by symbolic name
  g1.DelEvent(idx_tmp);     // by index

  // delete a bunch of events
  // g1.DelEvents(eset1); // .. of course we have already deleted them before...

  // insert a new state. The state gets a integer index that is unique within
  // the Generator

  idx_tmp = g1.InsState();            // anonymous state
  idx_tmp = g1.InsState("newstate2"); // named state
  idx_tmp = g1.InsState("77"); // named state

  // insert a new state as initial state

  idx_tmp = g1.InsInitState();
  idx_tmp = g1.InsInitState("newinitstate");

  // ... same for marked states

  idx_tmp = g1.InsMarkedState();
  idx_tmp = g1.InsMarkedState("newmarkedstate");


  // delete single states from Generator ie stateset and transitionrelation

  g1.DelState(idx_tmp); // by index (relatively fast, for algorithms)
  g1.DelState("newinitstate"); // by symbolic name, if name assigned

  // delete a bunch of states 
  // (this should be more efficient than deleting states individually)

  StateSet stateset1;
  stateset1.Insert(1);
  stateset1.Insert(2);
  stateset1.Insert(3);
  g1.DelStates(stateset1);

  // for further proceeding we insert some new states and events...

  Idx idx_s10 = g1.InsState("s10");
  Idx idx_s11 = g1.InsState("s11");
  Idx idx_s12 = g1.InsState("s12");
  Idx idx_e10 = g1.InsEvent("e10");
  Idx idx_e11 = g1.InsEvent("e11");

  // set a state that already exists in Generator as initial state

  g1.SetInitState(idx_s10);

  // set a state that already exists in Generator as marked state

  g1.SetMarkedState(idx_s11);

  // unset an existing state as initial state (does not remove from mStates)

  g1.ClrInitState(idx_s10); 

  // unset an existing state as marked state (does not remove from stateset)

  g1.ClrMarkedState(idx_s10); 

  // clear all initial states (does not remove from stateset)

  //   g1.ClrInitStates();  // we do not really do it here, so it's commented

  // clear all marked states (mStates stays untouched)

  //   g1.ClrMarkedStates();  // we do not really do it here, so it's commented

  // set a transition for existing states and events

  g1.SetTransition(idx_s10, idx_e10, idx_s11); // by indices
  g1.SetTransition("s10", "e11", "s10"); // by symbolic names (slow)


  // report back to console

  std::cout << "################################\n";
  std::cout << "# tutorial, on the way ... \n";
  g1.Write();
  std::cout << "################################\n";


  // clear a transition (does not touch mStates, mInitStates and mMarkedStates)

  g1.ClrTransition(idx_s10, idx_e10, idx_s11); // by index

  // transitions can also be cleared by names (slower) or by an assigned
  // TransSet::Iterator (faster); use ClearTransRel() to remove all transitions


  // clear the symbolic name for a state in the StateSymbolTable

  g1.ClrStateName(idx_s10); 

  // exists event index/name in mAlphabet?

  bool bool_eventexists1 = g1.ExistsEvent("e11"); 
  bool bool_eventexists2 = g1.ExistsEvent(2); 


  // exists state in mStates?

  bool bool_stateexists1 = g1.ExistsState(4); 


  // check if a state is an initial state

  bool bool_initstateexists = g1.ExistsInitState(4); 

  // check if a state is a marked state

  bool bool_ismarkedstate = g1.ExistsMarkedState(4); 

  // look up event name for index in the EventSymbolTable of the event domain

  std::string str_eventname1 = g1.EventName(1);

  // look up event index for name in the EventSymbolTable of the event domain

  Idx idx_eventindex = g1.EventIndex("e11");

  // get symbolic name assigned to state (returns "" if no name assigned).

  std::string str_tmp = g1.StateName(idx_s10);

  // get index for symbolic state name. only possible for state names of states in
  // the Generator 

  idx_tmp = g1.StateIndex("s12");

  // clear Generator (including alphabet)

  g4.Clear();

  // get the number of events in the Generator's alphabet

  Idx idx_eventnum = g1.AlphabetSize();

  // get the number of states

  Idx idx_statenum = g1.Size();

  // get the number of transitions

  Idx idx_transnum = g1.TransRelSize();

  // there also are InitStatesSize(), MarkedStatesSize()

  // is the alphabet of the Generator empty?

  bool bool_alphempty = g1.AlphabetEmpty();

  // is the Generator empty (number of states == 0) ?

  bool bool_isempty = g1.Empty();

  // see also TransRelEmpty, InitStatesEmpty, MarkedStatesEmpty


  // insert a small loop 

  Idx initstate = g1.InsInitState("in");
  Idx markedstate = g1.InsMarkedState("out");
  g1.SetTransition("in","a","out");
  g1.SetTransition("out","a","in");


  // show effect on console 

  std::cout << "################################\n";
  std::cout << "# tutorial, after ins and del \n";
  g1.DWrite();
  std::cout << "################################\n";

  // record test case
  FAUDES_TEST_DUMP("g1, edited", g1); 

  ///////////////////////
  // Iterators
  ///////////////////////

  // since the core members are all implemented as sets, iterators
  // effectively are const_iterators, i.e. you cannot change the 
  // current value of an iterator. instead you may remove the value 
  // and insert the new value.

  // iteration over alphabet indices (member "mAlphabet")

  std::cout << "################################\n";
  std::cout << "# tutorial, iterators 1         \n";
  EventSet::Iterator eit;
  for (eit = g1.AlphabetBegin(); eit != g1.AlphabetEnd(); ++eit) {
    std::cout << "event \"" << g1.EventName(*eit) << "\" with index "<< *eit << std::endl;
  }
  std::cout << "################################\n";

  // iteration over state indices (member "mStates")

  std::cout << "################################\n";
  std::cout << "# tutorial, iterators 2         \n";
  StateSet::Iterator sit;
  for (sit = g1.StatesBegin(); sit != g1.StatesEnd(); ++sit) {
    std::cout << *sit << std::endl;
  }
  std::cout << "################################\n";

  // iteration over complete transition relation (member "mTransRel")

  std::cout << "################################\n";
  std::cout << "# tutorial, iterators 3         \n";
  TransSet::Iterator tit;
  for (tit = g1.TransRelBegin(); tit != g1.TransRelEnd(); ++tit) {
    std::cout << g1.TStr(*tit) << std::endl;
  }
  std::cout << "################################\n";

  // iteration over transitions from a given state; note that we avoid
  // computation of the end of the iteration in every step

  std::cout << "################################\n";
  std::cout << "# tutorial, iterators 4         \n";
  idx_tmp = g1.StateIndex("s1");
  TransSet::Iterator tit_end;
  tit = g1.TransRelBegin(idx_tmp);
  tit_end = g1.TransRelEnd(idx_tmp);
  for (; tit != tit_end; ++tit) {
    std::cout << g1.TStr(*tit) << std::endl;
  }
  std::cout << "################################\n";

  // variations: transitions of given state index + given event index:
  // TransRelBegin(x1, ev) - TransRelEnd(x1, ev)

  // iteration over initial and marked states:
  // InitStatesBegin() - InitStatesEnd()  (member "mInitStates")
  // MarkedStatesBegin() - MarkedStatesEnd() (member "mMarkedStates")


  ////////////////////////////////////////////////////////////
  // retrieve copies of the Generator's transition releation
  // in different sorting orders than X1 -> Ev -> X2
  ////////////////////////////////////////////////////////////

  // note: the availabity of iterator ranges depends on the sorting order;
  // eg iteration with specified x2 requires X2->Ev->X1 or X2->X1->Ev sorting.

  // retrieve a copy that is sorted by X2 -> Ev -> X1 by the binary
  // predicate TransSort::X2EvX1. 
  
  TransSetX2EvX1 tset_x2evx1;
  g1.TransRel(tset_x2evx1);

  // report to console

  std::cout << "################################\n";
  std::cout << "# tutorial, x2-ev-x1 sorting\n";
  TransSetX2EvX1::Iterator tit2;
  for (tit2 = tset_x2evx1.Begin(); tit2 != tset_x2evx1.End(); ++tit2) {
    std::cout << g1.TStr(*tit2) << std::endl;
  }
  std::cout << "################################\n";



  ////////////////////////
  // Convenience Methods
  ////////////////////////

  // remove all events from mAlphabet, that do not have a transition in
  // mTransRel:  g1.MinimizeAlphabet()

  // get an EventSet containing all the events that drive some transition 

  EventSet eset_usedevents = g1.UsedEvents();

  // get an EventSet containing all the events that do not drive any transition

  EventSet eset_unusedevents = g1.UnusedEvents();

  // return the active event set at a given state 

  EventSet eset_activeeventset = g1.ActiveEventSet(idx_s12);

  // return a StateSet containing all the states that are connected by
  // some transition 

  StateSet sset_trel_sspace = g1.TransRelStates();

  // return a StateSet containing all the successor states of a given predecessor
  // state.

  StateSet sset_successors = g1.SuccessorStates(idx_s12);

  // note: if you need predecessor states, use a resorted transition relation

  /////////////////////////////////
  // Symbolic state name handling
  /////////////////////////////////

  // are symbolic state names enabled? depending on this boolean value
  // library functions like Determine or StateMin may create symbolic
  // state names automatically

  bool bool_statenamesenabled = g1.StateNamesEnabled();

  // disable state name creation in resulting generators for functions in
  // the faudes library, that support this feature (nearly all) with
  // "false"; enable state name creation with "true".

  g1.StateNamesEnabled(true); // anyway .. true is the default value

  // clear existing symbolic statenames for states in the Generator

  // g1.ClearStateNames(); 

  // set symbolic names for all states in the generator. the symbolic name becomes
  // the equivalent string representation of the state's integer index. This is
  // only usefull for debugging purposes.

  g1.SetDefaultStateNames();


  // show effect on console 

  std::cout << "################################\n";
  std::cout << "# tutorial, default names \n";
  g1.Write();
  std::cout << "################################\n";


  ///////////////////////////////////
  // Accessible, Coaccessible, Complete, Trim
  ///////////////////////////////////

  // read example generator for reachability analysis
  Generator greach("data/trimness_nottrim.gen");

  std::cout << "################################\n";
  std::cout << "# tutorial, reachability test case  \n";
  greach.Write();
  std::cout << "# tutorial, reachability relevant sets \n";
  StateSet astates = greach.AccessibleSet();
  StateSet cstates = greach.CoaccessibleSet();
  StateSet tstates = greach.TerminalStates();
  astates.Write();
  cstates.Write();
  tstates.Write();   
  std::cout << "# tutorial, reachability analysis \n";
  bool isacc = greach.IsAccessible(); 
  if(isacc) 
    std::cout << "accesibility: ok [error]\n";
  else
    std::cout << "accesibility: failed [expected]\n";
  bool iscoacc = greach.IsCoaccessible(); 
  if(iscoacc) 
    std::cout << "coaccesibility: ok [error]\n";
  else
    std::cout << "coaccesibility: failed [expected]\n";
  bool iscompl = greach.IsComplete(); 
  if(iscompl) 
    std::cout << "completeness: ok [error]\n";
  else
    std::cout << "completeness: failed [expected]\n";
  bool istrim = greach.IsTrim(); 
  if(istrim) 
    std::cout << "trimness: ok [error]\n";
  else
    std::cout << "trimness: failed [expected]\n";
  bool isotrim = greach.IsOmegaTrim(); 
  if(isotrim) 
    std::cout << "w-trimness: ok [error]\n";
  else
    std::cout << "w-trimness: failed [expected]\n";
  std::cout << "################################\n";
  
  // record test case
  FAUDES_TEST_DUMP("acc",astates);
  FAUDES_TEST_DUMP("coacc",cstates);
  FAUDES_TEST_DUMP("term",tstates);

  // Make the Generator accessible by removing transitions and states. 
  // The routine returns true if the generator has an initial state.
  Generator gaccess(greach);
  gaccess.Name("GAccessible");
  bool bool_hasinit = gaccess.Accessible();

  // Make the Generator coaccessible by removing transitions and states.
  // The routine returns true if the generator has a marked state.
  Generator gcoaccess(greach);
  gcoaccess.Name("GCoccessible");
  bool bool_hasmarked = gcoaccess.Coaccessible();

  // Make the Generator complete by removing transitions and states. 
  // The routine returns true if the generator has an initial state.
  Generator gcompl(greach);
  gcompl.Name("GComplete");
  gcompl.Complete();

  // Make the Generator trim by removing transitions and states. 
  // The routine returns true if the generator has an initial state
  // and a marked state.
  Generator gtrim(greach);
  gtrim.Name("GTrim");
  bool bool_isnontrivial = gtrim.Trim();

  // Make the Generator omega-trim by removing transitions and states. 
  // The routine returns true if the generator has an initial state
  // and a marked state.
  Generator gotrim(greach);
  gotrim.Name("GOmegaTrim");
  gotrim.OmegaTrim();

  // show effect on console
  std::cout << "################################\n";
  std::cout << "# tutorial, reachability results \n";
  gaccess.Write();
  gcoaccess.Write();
  gcompl.Write();
  gtrim.Write();
  gotrim.Write();
  std::cout << "################################\n";

  // contribute to html docu
  greach.Write("tmp_greach.gen");
  gaccess.Write("tmp_gaccess.gen");
  gcoaccess.Write("tmp_gcoaccess.gen");
  gcompl.Write("tmp_gcompl.gen");
  gtrim.Write("tmp_gtrim.gen");
  gotrim.Write("tmp_gotrim.gen");

  // Test protocol
  FAUDES_TEST_DUMP("accessible",gaccess);
  FAUDES_TEST_DUMP("coaccessible",gcoaccess);
  FAUDES_TEST_DUMP("complete",gcompl);
  FAUDES_TEST_DUMP("trim",gtrim);
  FAUDES_TEST_DUMP("omega trim",gotrim);
  

  ///////////////////////////////////
  // Generalized Completeness
  ///////////////////////////////////

  // read example generator for generalized completeness
  Generator gsigcomplB("data/trimness_nottrim.gen");
  Generator gsigcomplC("data/trimness_nottrim.gen");
  EventSet sigoB;
  sigoB.FromString("<A> b </A>");
  EventSet sigoC;
  sigoC.FromString("<A> c </A>");

  std::cout << "################################\n";
  std::cout << "# tutorial, sigma_o-completeness test case  \n";
  greach.Write();
  bool issigcompl = gsigcomplB.IsComplete(sigoB); 
  if(iscompl) 
    std::cout << "completeness: ok [error]\n";
  else
    std::cout << "completeness: failed [expected]\n";
  

  // Make the Generator complete by removing transitions and states. 
  // The routine returns true if the generator has an initial state.
  gsigcomplB.Name("GSigoCompleteB");
  gsigcomplB.Complete(sigoB);
  gsigcomplC.Name("GSigoCompleteC");
  gsigcomplC.Complete(sigoC);

  // record test case
  FAUDES_TEST_DUMP("iscmpl",issigcompl);
  FAUDES_TEST_DUMP("gsigcomplB",gsigcomplB);
  FAUDES_TEST_DUMP("gsigcomplC",gsigcomplC);

  // contribute to html docu
  gsigcomplB.Write("tmp_gsigcomplb.gen");
  gsigcomplC.Write("tmp_gsigcomplc.gen");


  ///////////////////////////////////
  // Test case evaluation
  ///////////////////////////////////
  FAUDES_TEST_DIFF();

  return 0;
}



Definition in file 1_generator.cpp.


Function Documentation

int main ( void   ) 

Definition at line 32 of file 1_generator.cpp.

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen