#!/usr/bin/python

import sys

def genFiles (dir):
    ############################################################
    f = open (dir + "/" + "bfs.h", "w")
    f.write ("\
#ifndef LIB_BFS\n\
#define LIB_BFS\n\
\n\
#include \"includes.h\"\n\
#include \"report.h\"\n\
#include \"state.h\"\n\
#include \"event.h\"\n\
#include \"storage.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
typedef struct {\n\
  storage_id_t s;\n\
  unsigned int l;\n\
#ifdef WITH_TRACE\n\
  unsigned char * trace;\n\
#endif\n\
} bfs_queue_item_t;\n\
\n\
void bfs\n\
(report_t r);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "bfs.c", "w")
    f.write ("\
#include \"bfs.h\"\n\
#include \"bfs_queue.h\"\n\
#include \"report.h\"\n\
#include \"prop.h\"\n\
#include \"graph.h\"\n\
\n\
static report_t R;\n\
static bfs_queue_t Q;\n\
\n\
void set_bfs_report_trace\n\
(report_t report,\n\
 unsigned int len,\n\
 unsigned char * trace,\n\
 state_t f) {\n\
#ifdef WITH_TRACE\n\
  event_t * tr;\n\
  state_t s = state_initial ();\n\
  unsigned int i, num;\n\
\n\
  report_faulty_state (R, f);\n\
  tr = mem_alloc (SYSTEM_HEAP, sizeof(event_t) * len);\n\
  for (i = 0; i < len; i ++) {\n\
    event_set_t en = state_enabled_events (s);\n\
    event_t e = event_set_nth (en, trace[i]);\n\
    event_exec (e, s);\n\
    tr[i] = event_copy (e);\n\
    event_set_free (en);\n\
  }\n\
  report->trace = tr;\n\
  report->trace_len = len;\n\
  state_free (s);\n\
#else\n\
  report_faulty_state (R, f);\n\
#endif\n\
}\n\
\n\
void * bfs_worker\n\
(void * arg) {\n\
  storage_t storage = R->storage;\n\
  node_t num;\n\
  char t;\n\
  unsigned int l, en_size;\n\
  state_t s, succ;\n\
  storage_id_t id, id_new;\n\
  event_set_t en;\n\
  bfs_queue_item_t el;\n\
  int i, k;\n\
  unsigned char * tr;\n\
  worker_id_t w = (worker_id_t) (unsigned long int) arg;\n\
  char heap_name[100];\n\
  bool_t fully_expanded;\n\
  unsigned int arcs;\n\
  \n\
  sprintf (heap_name, \"bfs heap of worker %d\", w);\n\
  heap_t heap = bounded_heap_new (heap_name, 1024 * 1024);\n\
\n\
  while (!(bfs_queue_is_empty (Q)) && R->keep_searching) {\n\
\n\
    /*\n\
     *  dequeue a state, get its successors and a valid stubborn set\n\
     */\n\
    el = bfs_queue_dequeue (Q);\n\
    l = el.l;\n\
#ifdef WITH_TRACE\n\
    tr = el.trace;\n\
#endif\n\
    id = el.s;\n\
    heap_reset (heap);\n\
    s = storage_get_mem (storage, id, w, heap);\n\
    en = state_enabled_events_mem (s, heap);\n\
    en_size = event_set_size (en);\n\
    if (0 == en_size) {\n\
      R->states_dead[w] ++;\n\
    }\n\
    report_update_bfs_levels (R, el.l + 1);\n\
#ifdef POR\n\
    en_size = event_set_size (en);\n\
    state_stubborn_set (s, en);\n\
    fully_expanded = (en_size == event_set_size (en)) ? TRUE : FALSE;\n\
#endif\n\
\n\
    /*\n\
     *  check the state property\n\
     */\n\
#ifdef ACTION_CHECK_SAFETY\n\
    if (state_check_property (s, en)) {\n\
      set_bfs_report_trace (R, l, tr, s);\n\
    }\n\
#endif\n\
    \n\
    /*\n\
     *  expand the current state and put its unprocessed successors in\n\
     *  the queue\n\
     */\n\
  state_expansion:\n\
    arcs = 0;\n\
    en_size = event_set_size (en);\n\
\n\
    /*\n\
     *  print the node informations in the reachability graph file\n\
     */\n\
#ifdef ACTION_BUILD_RG\n\
    t = GT_NODE;\n\
    fwrite (&t, 1, 1, R->graph_file);\n\
    num = storage_get_num (storage, id);\n\
    fwrite (&num, sizeof (node_t), 1, R->graph_file);\n\
    fwrite (&en_size, sizeof (uint8_t), 1, R->graph_file);\n\
#endif\n\
\n\
    for (i = 0; i < en_size; i ++) {\n\
      event_t e = event_set_nth (en, i);\n\
      event_id_t e_id = event_set_nth_id (en, i);\n\
      bool_t is_new;\n\
      large_unsigned_t queue_size;\n\
\n\
      arcs ++;\n\
      R->events_executed[w] ++;\n\
      event_exec (e, s);\n\
      storage_insert (storage, s, &id, &e_id, l + 1, w, &is_new, &id_new);\n\
\n\
      /*\n\
       *  if new, enqueue the successor after setting its trace and\n\
       *  level\n\
       */\n\
      if (is_new) {\n\
	el.l = l + 1;\n\
#ifdef WITH_TRACE\n\
	el.trace = mem_alloc (SYSTEM_HEAP, sizeof (unsigned char) * el.l);\n\
	for (k = 0; k < el.l - 1; k ++) { el.trace[k] = tr[k]; }\n\
	el.trace[k] = i;\n\
#endif\n\
	el.s = id_new;\n\
	queue_size = bfs_queue_enqueue (Q, el);\n\
	report_update_max_unproc_size (R, queue_size);\n\
      } else {\n\
\n\
	/*\n\
	 *  if the successor state is not new it must be in the queue\n\
	 *  for the proviso to be satisfied\n\
	 */\n\
#if defined(POR) && defined(PROVISO)\n\
	if (!fully_expanded && !storage_get_in_unproc (storage, id_new)) {\n\
	  fully_expanded = TRUE;\n\
	  event_undo (e, s);\n\
	  event_set_free (en);\n\
	  en = state_enabled_events_mem (s, heap);\n\
	  goto state_expansion;\n\
	}\n\
#endif\n\
      }\n\
      event_undo (e, s);\n\
\n\
      /*\n\
       *  print the edge in the reachability graph file\n\
       */\n\
#ifdef ACTION_BUILD_RG\n\
      num = storage_get_num (storage, id_new);\n\
      fwrite (&e_id, sizeof (edge_num_t), 1, R->graph_file);\n\
      fwrite (&num, sizeof (node_t), 1, R->graph_file);\n\
#endif\n\
\n\
    }\n\
    state_free (s);\n\
    event_set_free (en);\n\
#ifdef WITH_TRACE\n\
    if (tr) {\n\
      free (tr);\n\
    }\n\
#endif\n\
\n\
    /*\n\
     *  the state leaves the queue\n\
     */\n\
    R->arcs[w] += arcs;\n\
    R->states_visited[w] ++;\n\
    storage_set_in_unproc (storage, id, FALSE);\n\
#ifdef ALGO_FRONTIER\n\
    storage_remove (storage, id);\n\
#endif\n\
  }\n\
  heap_free (heap);\n\
}\n\
\n\
void bfs\n\
(report_t r) {\n\
  state_t s = state_initial ();\n\
  bool_t is_new;\n\
  storage_id_t id;\n\
  worker_id_t w;\n\
  void * dummy;\n\
  bfs_queue_item_t el;\n\
\n\
  Q = bfs_queue_init ();\n\
  R = r;\n\
  storage_insert (R->storage, s, NULL, NULL, 0, 0, &is_new, &id);\n\
  R->graph_file = open_graph_file ();\n\
  el.s = id;\n\
  state_free (s);\n\
#ifdef WITH_TRACE\n\
  el.trace = NULL;\n\
#endif\n\
  el.l = 0;\n\
  bfs_queue_enqueue (Q, el);\n\
  \n\
  /*\n\
   *  start the threads and wait for their termination\n\
   */\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_create (&(r->workers[w]), NULL, &bfs_worker, (void *) (long) w);\n\
  }\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_join (r->workers[w], &dummy);\n\
  }\n\
\n\
  bfs_queue_free (Q);\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "bfs_queue.h", "w")
    f.write ("\
#ifndef LIB_BFS_QUEUE\n\
#define LIB_BFS_QUEUE\n\
\n\
#include \"bfs.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
struct struct_bfs_queue_node_t {\n\
  bfs_queue_item_t  elements [BFS_QUEUE_NODE_SIZE];\n\
  struct struct_bfs_queue_node_t * prev;\n\
  struct struct_bfs_queue_node_t * next;\n\
};\n\
\n\
typedef struct struct_bfs_queue_node_t struct_bfs_queue_node_t;\n\
\n\
typedef struct_bfs_queue_node_t * bfs_queue_node_t;\n\
\n\
typedef struct {\n\
  bfs_queue_node_t first;\n\
  bfs_queue_node_t last;\n\
  large_unsigned_t first_index;\n\
  large_unsigned_t last_index;\n\
  large_unsigned_t size;\n\
  bool_t shared;\n\
} struct_bfs_queue_t;\n\
\n\
typedef struct_bfs_queue_t * bfs_queue_t;\n\
\n\
\n\
bfs_queue_t bfs_queue_init\n\
();\n\
\n\
bool_t bfs_queue_is_empty\n\
(bfs_queue_t q);\n\
\n\
void bfs_queue_free\n\
(bfs_queue_t q);\n\
\n\
large_unsigned_t bfs_queue_size\n\
(bfs_queue_t q);\n\
\n\
large_unsigned_t bfs_queue_enqueue\n\
(bfs_queue_t  q,\n\
 bfs_queue_item_t s);\n\
\n\
bfs_queue_item_t bfs_queue_dequeue\n\
(bfs_queue_t q);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "bfs_queue.c", "w")
    f.write ("\
#include \"bfs_queue.h\"\n\
\n\
bfs_queue_t bfs_queue_init\n\
() {\n\
  bfs_queue_t result = (bfs_queue_t)\n\
    malloc (sizeof (struct_bfs_queue_t));\n\
  result->first = NULL;\n\
  result->last = NULL;\n\
  result->first_index = 0;\n\
  result->last_index = 0;\n\
  result->size = 0;\n\
  return result;\n\
}\n\
\n\
bool_t bfs_queue_is_empty\n\
(bfs_queue_t q) {\n\
  bool_t result;\n\
  result = (q->size == 0) ? TRUE : FALSE;\n\
  return result;\n\
}\n\
\n\
void bfs_queue_free\n\
(bfs_queue_t q) {\n\
  bfs_queue_node_t tmp = q->first, next;\n\
  while(tmp) {\n\
    next = tmp->next;\n\
    free (tmp);\n\
    tmp = next;\n\
  }\n\
  free (q);\n\
}\n\
\n\
large_unsigned_t bfs_queue_size\n\
(bfs_queue_t q) {\n\
  large_unsigned_t result;\n\
  result = q->size;\n\
  return result;\n\
}\n\
\n\
large_unsigned_t bfs_queue_enqueue\n\
(bfs_queue_t  q,\n\
 bfs_queue_item_t s) {\n\
  large_unsigned_t result;\n\
  if(!q->first) {\n\
    q->last_index = 0;\n\
    q->last = (bfs_queue_node_t)\n\
      malloc (sizeof (struct_bfs_queue_node_t));\n\
    q->first = q->last;\n\
    q->first->next = NULL;\n\
    q->first->prev = NULL;\n\
  }\n\
  else if(BFS_QUEUE_NODE_SIZE == q->last_index) {\n\
    q->last_index = 0;\n\
    q->last->next = (bfs_queue_node_t)\n\
      malloc (sizeof (struct_bfs_queue_node_t));\n\
    q->last->next->next = NULL;\n\
    q->last->next->prev = q->last;\n\
    q->last = q->last->next;\n\
  }\n\
  q->last->elements[q->last_index] = s;\n\
  q->last_index ++;\n\
  q->size ++;\n\
  result = q->size;\n\
  return result;\n\
}\n\
\n\
bfs_queue_item_t bfs_queue_dequeue\n\
(bfs_queue_t q) {\n\
  bfs_queue_item_t  result;\n\
  if(BFS_QUEUE_NODE_SIZE == q->first_index) {\n\
    bfs_queue_node_t tmp = q->first->next;\n\
    free(q->first);\n\
    q->first = tmp;\n\
    q->first_index = 0;\n\
  }\n\
  result = q->first->elements[q->first_index];\n\
  q->first_index ++;\n\
  q->size --;\n\
  return result;\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "buchi.h", "w")
    f.write ("\
#ifndef LIB_BUCHI\n\
#define LIB_BUCHI\n\
\n\
#include \"common.h\"\n\
#include \"includes.h\"\n\
#include \"model.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
typedef int bstate_t;\n\
\n\
typedef struct {\n\
  bstate_t from;\n\
  bstate_t to;\n\
} bevent_t;\n\
\n\
bstate_t bstate_initial\n\
();\n\
\n\
bool_t bstate_accepting\n\
(bstate_t b);\n\
\n\
void bstate_succs\n\
(bstate_t b,\n\
 mstate_t s,\n\
 bstate_t * succs,\n\
 unsigned int * no_succs);\n\
\n\
unsigned int bstate_char_width\n\
();\n\
\n\
order_t bevent_cmp\n\
(bevent_t e,\n\
 bevent_t f);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "common.h", "w")
    f.write ("\
#ifndef LIB_COMMON\n\
#define LIB_COMMON\n\
\n\
#include \"includes.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void init_common ();\n\
void free_common ();\n\
\n\
int crc32_tab[256];\n\
\n\
char * glob_error_msg;\n\
\n\
typedef char termination_state_t;\n\
#define SUCCESS             0\n\
#define ERROR               1\n\
#define INTERRUPTION        2\n\
#define SEARCH_TERMINATED   3\n\
#define NO_ERROR            4\n\
#define MEMORY_EXHAUSTED    5\n\
#define TIME_ELAPSED        6\n\
#define STATE_LIMIT_REACHED 7\n\
#define FAILURE             8\n\
\n\
typedef unsigned short state_sizeof_t;\n\
\n\
typedef char * bit_vector_t;\n\
\n\
typedef uint64_t large_unsigned_t;\n\
\n\
typedef uint32_t hash_key_t;\n\
\n\
typedef uint32_t state_num_t;\n\
\n\
typedef uint8_t worker_id_t;\n\
\n\
typedef int32_t priority_t;\n\
\n\
typedef uint8_t bool_t;\n\
#define FALSE 0\n\
#define TRUE  1\n\
\n\
typedef uint8_t order_t; \n\
#define LESS    1\n\
#define EQUAL   2\n\
#define GREATER 3\n\
\n\
typedef uint32_t rseed_t;\n\
\n\
rseed_t random_seed (worker_id_t w);\n\
\n\
rseed_t random_int (rseed_t * seed);\n\
\n\
typedef struct {\n\
  struct timeval start;\n\
  large_unsigned_t value;\n\
} lna_timer_t;\n\
\n\
void lna_timer_init\n\
(lna_timer_t * t);\n\
\n\
void lna_timer_start\n\
(lna_timer_t * t);\n\
\n\
void lna_timer_stop\n\
(lna_timer_t * t);\n\
\n\
large_unsigned_t lna_timer_value\n\
(lna_timer_t t);\n\
\n\
large_unsigned_t duration\n\
(struct timeval t0,\n\
 struct timeval t1);\n\
\n\
hash_key_t bit_vector_hash\n\
(bit_vector_t v,\n\
 unsigned int len);\n\
\n\
#define MALLOC(ptr, ptr_type, size) {				\\\n\
    if (!((ptr) = (ptr_type) malloc(size))) {			\\\n\
      stop_search (MEMORY_EXHAUSTED);				\\\n\
    }								\\\n\
  }\n\
\n\
#define fatal_error(msg) {						\\\n\
    printf (\"file       : %s\\n\", __FILE__);				\\\n\
    printf (\"line       : %d\\n\", __LINE__);				\\\n\
    printf (\"fatal error: %s\\n\", msg);					\\\n\
    printf (\"please send a mail with a file that caused this bug to\\n\"); \\\n\
    printf (\"      sami.evangelista@lipn.univ-paris13.fr\\n\");		\\\n\
    exit (EXIT_FAILURE);						\\\n\
  }\n\
\n\
bool_t raise_error\n\
(char * msg);\n\
\n\
void flush_error\n\
();\n\
\n\
void stop_search\n\
(termination_state_t state);\n\
\n\
FILE * open_graph_file\n\
();\n\
\n\
large_unsigned_t do_large_sum\n\
(large_unsigned_t * array,\n\
 unsigned int       nb);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "common.c", "w")
    f.write ("\
#include \"common.h\"\n\
#include \"report.h\"\n\
\n\
void init_common () {\n\
  unsigned int i = 0;\n\
  glob_error_msg = NULL;\n\
  crc32_tab[i++] = 0x00000000;\n\
  crc32_tab[i++] = 0x77073096;\n\
  crc32_tab[i++] = 0xee0e612c;\n\
  crc32_tab[i++] = 0x990951ba;\n\
  crc32_tab[i++] = 0x076dc419;\n\
  crc32_tab[i++] = 0x706af48f;\n\
  crc32_tab[i++] = 0xe963a535;\n\
  crc32_tab[i++] = 0x9e6495a3;\n\
  crc32_tab[i++] = 0x0edb8832;\n\
  crc32_tab[i++] = 0x79dcb8a4;\n\
  crc32_tab[i++] = 0xe0d5e91e;\n\
  crc32_tab[i++] = 0x97d2d988;\n\
  crc32_tab[i++] = 0x09b64c2b;\n\
  crc32_tab[i++] = 0x7eb17cbd;\n\
  crc32_tab[i++] = 0xe7b82d07;\n\
  crc32_tab[i++] = 0x90bf1d91;\n\
  crc32_tab[i++] = 0x1db71064;\n\
  crc32_tab[i++] = 0x6ab020f2;\n\
  crc32_tab[i++] = 0xf3b97148;\n\
  crc32_tab[i++] = 0x84be41de;\n\
  crc32_tab[i++] = 0x1adad47d;\n\
  crc32_tab[i++] = 0x6ddde4eb;\n\
  crc32_tab[i++] = 0xf4d4b551;\n\
  crc32_tab[i++] = 0x83d385c7;\n\
  crc32_tab[i++] = 0x136c9856;\n\
  crc32_tab[i++] = 0x646ba8c0;\n\
  crc32_tab[i++] = 0xfd62f97a;\n\
  crc32_tab[i++] = 0x8a65c9ec;\n\
  crc32_tab[i++] = 0x14015c4f;\n\
  crc32_tab[i++] = 0x63066cd9;\n\
  crc32_tab[i++] = 0xfa0f3d63;\n\
  crc32_tab[i++] = 0x8d080df5;\n\
  crc32_tab[i++] = 0x3b6e20c8;\n\
  crc32_tab[i++] = 0x4c69105e;\n\
  crc32_tab[i++] = 0xd56041e4;\n\
  crc32_tab[i++] = 0xa2677172;\n\
  crc32_tab[i++] = 0x3c03e4d1;\n\
  crc32_tab[i++] = 0x4b04d447;\n\
  crc32_tab[i++] = 0xd20d85fd;\n\
  crc32_tab[i++] = 0xa50ab56b;\n\
  crc32_tab[i++] = 0x35b5a8fa;\n\
  crc32_tab[i++] = 0x42b2986c;\n\
  crc32_tab[i++] = 0xdbbbc9d6;\n\
  crc32_tab[i++] = 0xacbcf940;\n\
  crc32_tab[i++] = 0x32d86ce3;\n\
  crc32_tab[i++] = 0x45df5c75;\n\
  crc32_tab[i++] = 0xdcd60dcf;\n\
  crc32_tab[i++] = 0xabd13d59;\n\
  crc32_tab[i++] = 0x26d930ac;\n\
  crc32_tab[i++] = 0x51de003a;\n\
  crc32_tab[i++] = 0xc8d75180;\n\
  crc32_tab[i++] = 0xbfd06116;\n\
  crc32_tab[i++] = 0x21b4f4b5;\n\
  crc32_tab[i++] = 0x56b3c423;\n\
  crc32_tab[i++] = 0xcfba9599;\n\
  crc32_tab[i++] = 0xb8bda50f;\n\
  crc32_tab[i++] = 0x2802b89e;\n\
  crc32_tab[i++] = 0x5f058808;\n\
  crc32_tab[i++] = 0xc60cd9b2;\n\
  crc32_tab[i++] = 0xb10be924;\n\
  crc32_tab[i++] = 0x2f6f7c87;\n\
  crc32_tab[i++] = 0x58684c11;\n\
  crc32_tab[i++] = 0xc1611dab;\n\
  crc32_tab[i++] = 0xb6662d3d;\n\
  crc32_tab[i++] = 0x76dc4190;\n\
  crc32_tab[i++] = 0x01db7106;\n\
  crc32_tab[i++] = 0x98d220bc;\n\
  crc32_tab[i++] = 0xefd5102a;\n\
  crc32_tab[i++] = 0x71b18589;\n\
  crc32_tab[i++] = 0x06b6b51f;\n\
  crc32_tab[i++] = 0x9fbfe4a5;\n\
  crc32_tab[i++] = 0xe8b8d433;\n\
  crc32_tab[i++] = 0x7807c9a2;\n\
  crc32_tab[i++] = 0x0f00f934;\n\
  crc32_tab[i++] = 0x9609a88e;\n\
  crc32_tab[i++] = 0xe10e9818;\n\
  crc32_tab[i++] = 0x7f6a0dbb;\n\
  crc32_tab[i++] = 0x086d3d2d;\n\
  crc32_tab[i++] = 0x91646c97;\n\
  crc32_tab[i++] = 0xe6635c01;\n\
  crc32_tab[i++] = 0x6b6b51f4;\n\
  crc32_tab[i++] = 0x1c6c6162;\n\
  crc32_tab[i++] = 0x856530d8;\n\
  crc32_tab[i++] = 0xf262004e;\n\
  crc32_tab[i++] = 0x6c0695ed;\n\
  crc32_tab[i++] = 0x1b01a57b;\n\
  crc32_tab[i++] = 0x8208f4c1;\n\
  crc32_tab[i++] = 0xf50fc457;\n\
  crc32_tab[i++] = 0x65b0d9c6;\n\
  crc32_tab[i++] = 0x12b7e950;\n\
  crc32_tab[i++] = 0x8bbeb8ea;\n\
  crc32_tab[i++] = 0xfcb9887c;\n\
  crc32_tab[i++] = 0x62dd1ddf;\n\
  crc32_tab[i++] = 0x15da2d49;\n\
  crc32_tab[i++] = 0x8cd37cf3;\n\
  crc32_tab[i++] = 0xfbd44c65;\n\
  crc32_tab[i++] = 0x4db26158;\n\
  crc32_tab[i++] = 0x3ab551ce;\n\
  crc32_tab[i++] = 0xa3bc0074;\n\
  crc32_tab[i++] = 0xd4bb30e2;\n\
  crc32_tab[i++] = 0x4adfa541;\n\
  crc32_tab[i++] = 0x3dd895d7;\n\
  crc32_tab[i++] = 0xa4d1c46d;\n\
  crc32_tab[i++] = 0xd3d6f4fb;\n\
  crc32_tab[i++] = 0x4369e96a;\n\
  crc32_tab[i++] = 0x346ed9fc;\n\
  crc32_tab[i++] = 0xad678846;\n\
  crc32_tab[i++] = 0xda60b8d0;\n\
  crc32_tab[i++] = 0x44042d73;\n\
  crc32_tab[i++] = 0x33031de5;\n\
  crc32_tab[i++] = 0xaa0a4c5f;\n\
  crc32_tab[i++] = 0xdd0d7cc9;\n\
  crc32_tab[i++] = 0x5005713c;\n\
  crc32_tab[i++] = 0x270241aa;\n\
  crc32_tab[i++] = 0xbe0b1010;\n\
  crc32_tab[i++] = 0xc90c2086;\n\
  crc32_tab[i++] = 0x5768b525;\n\
  crc32_tab[i++] = 0x206f85b3;\n\
  crc32_tab[i++] = 0xb966d409;\n\
  crc32_tab[i++] = 0xce61e49f;\n\
  crc32_tab[i++] = 0x5edef90e;\n\
  crc32_tab[i++] = 0x29d9c998;\n\
  crc32_tab[i++] = 0xb0d09822;\n\
  crc32_tab[i++] = 0xc7d7a8b4;\n\
  crc32_tab[i++] = 0x59b33d17;\n\
  crc32_tab[i++] = 0x2eb40d81;\n\
  crc32_tab[i++] = 0xb7bd5c3b;\n\
  crc32_tab[i++] = 0xc0ba6cad;\n\
  crc32_tab[i++] = 0xedb88320;\n\
  crc32_tab[i++] = 0x9abfb3b6;\n\
  crc32_tab[i++] = 0x03b6e20c;\n\
  crc32_tab[i++] = 0x74b1d29a;\n\
  crc32_tab[i++] = 0xead54739;\n\
  crc32_tab[i++] = 0x9dd277af;\n\
  crc32_tab[i++] = 0x04db2615;\n\
  crc32_tab[i++] = 0x73dc1683;\n\
  crc32_tab[i++] = 0xe3630b12;\n\
  crc32_tab[i++] = 0x94643b84;\n\
  crc32_tab[i++] = 0x0d6d6a3e;\n\
  crc32_tab[i++] = 0x7a6a5aa8;\n\
  crc32_tab[i++] = 0xe40ecf0b;\n\
  crc32_tab[i++] = 0x9309ff9d;\n\
  crc32_tab[i++] = 0x0a00ae27;\n\
  crc32_tab[i++] = 0x7d079eb1;\n\
  crc32_tab[i++] = 0xf00f9344;\n\
  crc32_tab[i++] = 0x8708a3d2;\n\
  crc32_tab[i++] = 0x1e01f268;\n\
  crc32_tab[i++] = 0x6906c2fe;\n\
  crc32_tab[i++] = 0xf762575d;\n\
  crc32_tab[i++] = 0x806567cb;\n\
  crc32_tab[i++] = 0x196c3671;\n\
  crc32_tab[i++] = 0x6e6b06e7;\n\
  crc32_tab[i++] = 0xfed41b76;\n\
  crc32_tab[i++] = 0x89d32be0;\n\
  crc32_tab[i++] = 0x10da7a5a;\n\
  crc32_tab[i++] = 0x67dd4acc;\n\
  crc32_tab[i++] = 0xf9b9df6f;\n\
  crc32_tab[i++] = 0x8ebeeff9;\n\
  crc32_tab[i++] = 0x17b7be43;\n\
  crc32_tab[i++] = 0x60b08ed5;\n\
  crc32_tab[i++] = 0xd6d6a3e8;\n\
  crc32_tab[i++] = 0xa1d1937e;\n\
  crc32_tab[i++] = 0x38d8c2c4;\n\
  crc32_tab[i++] = 0x4fdff252;\n\
  crc32_tab[i++] = 0xd1bb67f1;\n\
  crc32_tab[i++] = 0xa6bc5767;\n\
  crc32_tab[i++] = 0x3fb506dd;\n\
  crc32_tab[i++] = 0x48b2364b;\n\
  crc32_tab[i++] = 0xd80d2bda;\n\
  crc32_tab[i++] = 0xaf0a1b4c;\n\
  crc32_tab[i++] = 0x36034af6;\n\
  crc32_tab[i++] = 0x41047a60;\n\
  crc32_tab[i++] = 0xdf60efc3;\n\
  crc32_tab[i++] = 0xa867df55;\n\
  crc32_tab[i++] = 0x316e8eef;\n\
  crc32_tab[i++] = 0x4669be79;\n\
  crc32_tab[i++] = 0xcb61b38c;\n\
  crc32_tab[i++] = 0xbc66831a;\n\
  crc32_tab[i++] = 0x256fd2a0;\n\
  crc32_tab[i++] = 0x5268e236;\n\
  crc32_tab[i++] = 0xcc0c7795;\n\
  crc32_tab[i++] = 0xbb0b4703;\n\
  crc32_tab[i++] = 0x220216b9;\n\
  crc32_tab[i++] = 0x5505262f;\n\
  crc32_tab[i++] = 0xc5ba3bbe;\n\
  crc32_tab[i++] = 0xb2bd0b28;\n\
  crc32_tab[i++] = 0x2bb45a92;\n\
  crc32_tab[i++] = 0x5cb36a04;\n\
  crc32_tab[i++] = 0xc2d7ffa7;\n\
  crc32_tab[i++] = 0xb5d0cf31;\n\
  crc32_tab[i++] = 0x2cd99e8b;\n\
  crc32_tab[i++] = 0x5bdeae1d;\n\
  crc32_tab[i++] = 0x9b64c2b0;\n\
  crc32_tab[i++] = 0xec63f226;\n\
  crc32_tab[i++] = 0x756aa39c;\n\
  crc32_tab[i++] = 0x026d930a;\n\
  crc32_tab[i++] = 0x9c0906a9;\n\
  crc32_tab[i++] = 0xeb0e363f;\n\
  crc32_tab[i++] = 0x72076785;\n\
  crc32_tab[i++] = 0x05005713;\n\
  crc32_tab[i++] = 0x95bf4a82;\n\
  crc32_tab[i++] = 0xe2b87a14;\n\
  crc32_tab[i++] = 0x7bb12bae;\n\
  crc32_tab[i++] = 0x0cb61b38;\n\
  crc32_tab[i++] = 0x92d28e9b;\n\
  crc32_tab[i++] = 0xe5d5be0d;\n\
  crc32_tab[i++] = 0x7cdcefb7;\n\
  crc32_tab[i++] = 0x0bdbdf21;\n\
  crc32_tab[i++] = 0x86d3d2d4;\n\
  crc32_tab[i++] = 0xf1d4e242;\n\
  crc32_tab[i++] = 0x68ddb3f8;\n\
  crc32_tab[i++] = 0x1fda836e;\n\
  crc32_tab[i++] = 0x81be16cd;\n\
  crc32_tab[i++] = 0xf6b9265b;\n\
  crc32_tab[i++] = 0x6fb077e1;\n\
  crc32_tab[i++] = 0x18b74777;\n\
  crc32_tab[i++] = 0x88085ae6;\n\
  crc32_tab[i++] = 0xff0f6a70;\n\
  crc32_tab[i++] = 0x66063bca;\n\
  crc32_tab[i++] = 0x11010b5c;\n\
  crc32_tab[i++] = 0x8f659eff;\n\
  crc32_tab[i++] = 0xf862ae69;\n\
  crc32_tab[i++] = 0x616bffd3;\n\
  crc32_tab[i++] = 0x166ccf45;\n\
  crc32_tab[i++] = 0xa00ae278;\n\
  crc32_tab[i++] = 0xd70dd2ee;\n\
  crc32_tab[i++] = 0x4e048354;\n\
  crc32_tab[i++] = 0x3903b3c2;\n\
  crc32_tab[i++] = 0xa7672661;\n\
  crc32_tab[i++] = 0xd06016f7;\n\
  crc32_tab[i++] = 0x4969474d;\n\
  crc32_tab[i++] = 0x3e6e77db;\n\
  crc32_tab[i++] = 0xaed16a4a;\n\
  crc32_tab[i++] = 0xd9d65adc;\n\
  crc32_tab[i++] = 0x40df0b66;\n\
  crc32_tab[i++] = 0x37d83bf0;\n\
  crc32_tab[i++] = 0xa9bcae53;\n\
  crc32_tab[i++] = 0xdebb9ec5;\n\
  crc32_tab[i++] = 0x47b2cf7f;\n\
  crc32_tab[i++] = 0x30b5ffe9;\n\
  crc32_tab[i++] = 0xbdbdf21c;\n\
  crc32_tab[i++] = 0xcabac28a;\n\
  crc32_tab[i++] = 0x53b39330;\n\
  crc32_tab[i++] = 0x24b4a3a6;\n\
  crc32_tab[i++] = 0xbad03605;\n\
  crc32_tab[i++] = 0xcdd70693;\n\
  crc32_tab[i++] = 0x54de5729;\n\
  crc32_tab[i++] = 0x23d967bf;\n\
  crc32_tab[i++] = 0xb3667a2e;\n\
  crc32_tab[i++] = 0xc4614ab8;\n\
  crc32_tab[i++] = 0x5d681b02;\n\
  crc32_tab[i++] = 0x2a6f2b94;\n\
  crc32_tab[i++] = 0xb40bbe37;\n\
  crc32_tab[i++] = 0xc30c8ea1;\n\
  crc32_tab[i++] = 0x5a05df1b;\n\
  crc32_tab[i++] = 0x2d02ef8d;\n\
}\n\
void free_common () {}\n\
\n\
hash_key_t bit_vector_hash\n\
(bit_vector_t v,\n\
 unsigned int len) {\n\
  unsigned int i;\n\
  hash_key_t result = 0;\n\
  for(i = 0; i < len; i++)\n\
    result = crc32_tab[(result ^ v[i]) & 0xff] ^ (result >> 8);\n\
  return result;\n\
}\n\
\n\
void lna_timer_init\n\
(lna_timer_t * t) {\n\
  t->value = 0;\n\
}\n\
\n\
void lna_timer_start\n\
(lna_timer_t * t) {\n\
  gettimeofday (&t->start, NULL);\n\
}\n\
\n\
void lna_timer_stop\n\
(lna_timer_t * t) {\n\
  struct timeval end;\n\
  gettimeofday (&end, NULL);\n\
  t->value += (large_unsigned_t)\n\
    (end.tv_sec * 1000000 + end.tv_usec) -\n\
    (t->start.tv_sec * 1000000 + t->start.tv_usec);\n\
}\n\
\n\
large_unsigned_t lna_timer_value\n\
(lna_timer_t t) {\n\
  return t.value;\n\
}\n\
\n\
large_unsigned_t duration\n\
(struct timeval t0,\n\
 struct timeval t1) {\n\
  large_unsigned_t t0_time = t0.tv_sec * 1000000 + t0.tv_usec;\n\
  large_unsigned_t t1_time = t1.tv_sec * 1000000 + t1.tv_usec;\n\
  return (large_unsigned_t) t1_time - t0_time;\n\
}\n\
\n\
uint32_t random_seed\n\
(worker_id_t w) {\n\
  struct timeval t;\n\
  \n\
  gettimeofday (&t, NULL);\n\
  return t.tv_sec * 1000000 + t.tv_usec + w;\n\
}\n\
\n\
#define RANDOM_MULT 1664525\n\
#define RANDOM_CONS 1\n\
#define RANDOM_MASK 0xFFFF\n\
#define RANDOM_LOW(X) (X&RANDOM_MASK)\n\
#define RANDOM_HIGH(X) ((X>>16)&RANDOM_MASK)\n\
\n\
uint32_t random_int\n\
(uint32_t * seed) {\n\
  uint32_t lo, hi;\n\
  uint32_t s = *seed;\n\
  lo = RANDOM_LOW (RANDOM_LOW (s) * RANDOM_LOW (RANDOM_MULT) + RANDOM_CONS);\n\
  hi = RANDOM_LOW (RANDOM_HIGH (s) * RANDOM_LOW (RANDOM_MULT))\n\
    + RANDOM_LOW (RANDOM_HIGH (RANDOM_MULT) * RANDOM_LOW (s))\n\
    + RANDOM_HIGH (RANDOM_LOW (s) * RANDOM_LOW (RANDOM_MULT) + RANDOM_CONS);\n\
  *seed = (hi << 16 | lo);\n\
  return *seed;\n\
}\n\
\n\
bool_t raise_error\n\
(char * msg) {\n\
#ifdef ACTION_SIMULATE\n\
  if (!glob_error_msg) {\n\
    glob_error_msg = mem_alloc (SYSTEM_HEAP, sizeof(char) * strlen(msg) + 1);\n\
    strcpy (glob_error_msg, msg);\n\
  }\n\
  return TRUE;\n\
#else\n\
  return report_error (msg);\n\
#endif\n\
}\n\
\n\
void flush_error\n\
() {\n\
#ifdef ACTION_SIMULATE\n\
  if (glob_error_msg) {\n\
    mem_free (SYSTEM_HEAP, glob_error_msg);\n\
    glob_error_msg = NULL;\n\
  }\n\
#endif\n\
}\n\
\n\
void stop_search\n\
(termination_state_t state) {\n\
  report_stop_search (state);\n\
}\n\
\n\
FILE * open_graph_file () {\n\
  FILE * result = NULL;\n\
#ifdef ACTION_BUILD_RG\n\
  result = fopen (GRAPH_FILE, \"w\");\n\
#endif\n\
  return result;\n\
}\n\
\n\
large_unsigned_t do_large_sum\n\
(large_unsigned_t * array,\n\
 unsigned int       nb) {\n\
  large_unsigned_t result = 0;\n\
  unsigned int i = 0;\n\
  for (i = 0; i < nb; i ++) {\n\
    result += array[i];\n\
  }\n\
  return result;\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "dfs.h", "w")
    f.write ("\
#ifndef LIB_DFS\n\
#define LIB_DFS\n\
\n\
#include \"includes.h\"\n\
#include \"report.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void dfs\n\
(report_t r);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "dfs.c", "w")
    f.write ("\
#include \"dfs.h\"\n\
#include \"model.h\"\n\
#include \"storage.h\"\n\
#include \"dfs_stack.h\"\n\
#include \"prop.h\"\n\
\n\
static report_t R;\n\
\n\
state_t dfs_main\n\
(state_t      now,\n\
 storage_id_t id,\n\
 heap_t       heap,\n\
 bool_t       red,\n\
 dfs_stack_t  blue_stack,\n\
 dfs_stack_t  red_stack) {\n\
  dfs_stack_item_t item;\n\
  storage_id_t id_seed;\n\
  storage_t storage = R->storage;\n\
  bool_t push;\n\
  worker_id_t w = 0;\n\
  storage_state_attr_t attr;\n\
  dfs_stack_t stack = red ? red_stack : blue_stack;\n\
  state_t copy;\n\
  event_t e;\n\
  event_id_t e_id;\n\
\n\
  /*\n\
   *  push the root state on the stack\n\
   */\n\
  item.id = id;\n\
  dfs_stack_push (stack, item);\n\
  item.en = dfs_stack_compute_events (stack, now, TRUE, NULL);\n\
  if (red) {\n\
    id_seed = id;\n\
  }\n\
\n\
#ifdef ACTION_CHECK_SAFETY\n\
  if (state_check_property (now, item.en)) {\n\
    report_faulty_state (R, now);\n\
    dfs_stack_create_trace (blue_stack, red_stack, R);\n\
  }\n\
#endif\n\
\n\
  /*\n\
   *  search loop\n\
   */\n\
  while (dfs_stack_size (stack) && R->keep_searching) {\n\
  loop_start:\n\
    item = dfs_stack_top (stack);\n\
\n\
    /*\n\
     *  reinitialise the heap if we do not have enough space\n\
     */\n\
    if (heap_space_left (heap) <= 1024) {\n\
      copy = state_copy (now);\n\
      heap_reset (heap);\n\
      now = state_copy_mem (copy, heap);\n\
      state_free (copy);\n\
    }\n\
\n\
    /*\n\
     *  all events of the top state have been executed => the state\n\
     *  has been expanded and we must pop it\n\
     */\n\
    if (item.n == event_set_size (item.en)) {\n\
\n\
      /*\n\
       *  check if proviso is verified.  if not we reexpand the state\n\
       */\n\
#if defined(POR) && defined(PROVISO)\n\
      if ((!item.prov_ok) && (!item.fully_expanded)) {\n\
	event_set_free (item.en);\n\
	dfs_stack_pop (stack);\n\
	dfs_stack_push (stack, item);\n\
	dfs_stack_compute_events (stack, now, FALSE, NULL);\n\
	goto loop_start;\n\
      }\n\
#endif\n\
\n\
      /*\n\
       *  we check an ltl property => launch the red search if the\n\
       *  state is accepting\n\
       */\n\
#ifdef ACTION_CHECK_LTL\n\
      if (!red && state_accepting (now)) {\n\
	R->states_accepting[w] ++;\n\
	dfs_main (now, item.id, heap, TRUE, blue_stack, red_stack);\n\
	if (!R->keep_searching) {\n\
	  return now;\n\
	}\n\
      }\n\
#endif\n\
\n\
      if (!red || (EQUAL != storage_id_cmp (id_seed, item.id))) {\n\
	storage_set_in_unproc (storage, item.id, FALSE);\n\
      }\n\
      R->states_visited[w] ++;\n\
      dfs_stack_pop (stack);\n\
      if (dfs_stack_size (stack)) {\n\
	item = dfs_stack_top (stack);\n\
	event_undo (event_set_nth (item.en, item.n - 1), now);\n\
      }\n\
    }\n\
\n\
    /*\n\
     *  some events of the top state remain to be executed => we\n\
     *  execute the next one\n\
     */\n\
    else {\n\
      e = event_set_nth (item.en, item.n);\n\
      e_id = event_set_nth_id (item.en, item.n);\n\
      item.n ++;\n\
      dfs_stack_update_top (stack, item);\n\
      event_exec (e, now);\n\
      R->events_executed[w] ++;\n\
      if (red) {\n\
#ifdef ACTION_CHECK_LTL\n\
	storage_get_attr (storage, now, w, &push, &id, &attr);\n\
	push = push && (!attr.is_red);\n\
	if (push) {\n\
	  storage_set_is_red (storage, id);\n\
	  storage_set_in_unproc (storage, item.id, TRUE);\n\
	}\n\
#endif\n\
      } else {\n\
	R->arcs[w] ++;\n\
	storage_insert (storage, now, &item.id, &e_id,\n\
			dfs_stack_size (stack), w, &push, &id);\n\
      }\n\
\n\
      /*\n\
       *  if the state reached is not new we undo the event used to\n\
       *  reach it.  otherwise we push it on the stack\n\
       */\n\
      if (!push) {\n\
    	event_undo (e, now);\n\
#if defined(POR) && defined(PROVISO)\n\
	if (storage_get_in_unproc (storage, id)) {\n\
	  item.prov_ok = FALSE;\n\
	  dfs_stack_update_top (stack, item);\n\
	}\n\
#endif\n\
      }\n\
      else {\n\
    	item.id = id;\n\
	dfs_stack_push (stack, item);\n\
    	item.en = dfs_stack_compute_events (stack, now, TRUE, &e);\n\
    	report_update_max_unproc_size\n\
	  (R, dfs_stack_size (red_stack) + dfs_stack_size (blue_stack));\n\
	if (!red && (0 == event_set_size (item.en))) {\n\
	  R->states_dead[w] ++;\n\
	}\n\
\n\
	/*\n\
	 *  check if the state property is verified and stop the\n\
	 *  search if not after setting the trace\n\
	 */\n\
#ifdef ACTION_CHECK_SAFETY\n\
	if (state_check_property (now, item.en)) {\n\
	  report_faulty_state (R, now);\n\
	  dfs_stack_create_trace (blue_stack, red_stack, R);\n\
	}\n\
#endif\n\
\n\
	/*\n\
	 *  if we check an LTL property, test whether the state\n\
	 *  reached is the seed\n\
	 */\n\
#ifdef ACTION_CHECK_LTL\n\
	if (red && (EQUAL == storage_id_cmp (id, id_seed))) {\n\
	  R->keep_searching = FALSE;\n\
	  R->result = FAILURE;\n\
	  dfs_stack_create_trace (blue_stack, red_stack, R);\n\
	}\n\
#endif\n\
      }\n\
    }\n\
  }\n\
  if (red) {\n\
    storage_set_is_red (storage, id_seed);\n\
  }\n\
  return now;\n\
}\n\
\n\
void * dfs_worker\n\
(void * arg) {\n\
  bool_t dummy;\n\
  storage_id_t id;\n\
  bounded_heap_t heap = bounded_heap_new (\"state heap\", 1024 * 100);\n\
  state_t now = state_initial_mem (heap);\n\
  dfs_stack_t blue_stack = dfs_stack_new (0);\n\
#ifdef ACTION_CHECK_LTL\n\
  dfs_stack_t red_stack = dfs_stack_new (1);\n\
#else\n\
  dfs_stack_t red_stack = NULL;\n\
#endif\n\
\n\
  storage_insert (R->storage, now, NULL, NULL, 0, 0, &dummy, &id);\n\
  now = dfs_main (now, id, heap, FALSE, blue_stack, red_stack);\n\
  dfs_stack_free (blue_stack);\n\
  dfs_stack_free (red_stack);\n\
  state_free (now);\n\
  heap_free (heap);\n\
}\n\
\n\
void dfs\n\
(report_t r) {\n\
  worker_id_t w;\n\
  void * dummy;\n\
\n\
  R = r;\n\
\n\
  /*\n\
   *  start the threads and wait for their termination\n\
   */\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_create (&(r->workers[w]), NULL, &dfs_worker, (void *) (long) w);\n\
  }\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_join (r->workers[w], &dummy);\n\
  }\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "dfs_stack.h", "w")
    f.write ("\
#ifndef LIB_DFS_STACK\n\
#define LIB_DFS_STACK\n\
\n\
#include \"includes.h\"\n\
#include \"report.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
#define DFS_STACK_SLOT_SIZE 10000\n\
#define DFS_STACK_SLOTS 2\n\
\n\
typedef struct {\n\
  unsigned char n;\n\
  storage_id_t  id;\n\
  event_set_t   en;\n\
  heap_t        heap_pos;\n\
#if defined(POR) && defined(PROVISO)\n\
  bool_t        prov_ok;\n\
  bool_t        fully_expanded;\n\
#endif\n\
} dfs_stack_item_t;\n\
\n\
typedef struct {\n\
  dfs_stack_item_t items[DFS_STACK_SLOT_SIZE];\n\
} struct_dfs_stack_slot_t;\n\
\n\
typedef struct_dfs_stack_slot_t * dfs_stack_slot_t;\n\
\n\
typedef struct {\n\
  dfs_stack_slot_t slots[DFS_STACK_SLOTS];\n\
  heap_t heaps[DFS_STACK_SLOTS];\n\
  unsigned char current;\n\
  int top;\n\
  unsigned int size;\n\
  unsigned int files;\n\
  int id;\n\
} struct_dfs_stack_t;\n\
\n\
typedef struct_dfs_stack_t * dfs_stack_t;\n\
\n\
dfs_stack_t dfs_stack_new\n\
(int id);\n\
\n\
void dfs_stack_free\n\
(dfs_stack_t stack);\n\
\n\
unsigned int dfs_stack_size\n\
(dfs_stack_t stack);\n\
\n\
void dfs_stack_push\n\
(dfs_stack_t      stack,\n\
 dfs_stack_item_t item);\n\
\n\
void dfs_stack_pop\n\
(dfs_stack_t stack);\n\
\n\
dfs_stack_item_t dfs_stack_top\n\
(dfs_stack_t stack);\n\
\n\
void dfs_stack_update_top\n\
(dfs_stack_t      stack,\n\
 dfs_stack_item_t item);\n\
\n\
event_set_t dfs_stack_compute_events\n\
(dfs_stack_t stack,\n\
 state_t     s,\n\
 bool_t      filter,\n\
 event_t *   exec);\n\
\n\
void dfs_stack_create_trace\n\
(dfs_stack_t blue_stack,\n\
 dfs_stack_t red_stack,\n\
 report_t    r);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "dfs_stack.c", "w")
    f.write ("\
#include \"dfs_stack.h\"\n\
#include \"model.h\"\n\
\n\
void dfs_stack_slot_free\n\
(dfs_stack_slot_t slot) {\n\
  free (slot);\n\
}\n\
\n\
dfs_stack_slot_t dfs_stack_slot_new\n\
() {\n\
  dfs_stack_slot_t result;\n\
\n\
  result = mem_alloc (SYSTEM_HEAP, sizeof (struct_dfs_stack_slot_t));\n\
  return result;\n\
}\n\
\n\
dfs_stack_t dfs_stack_new\n\
(int id) {\n\
  dfs_stack_t result;\n\
  int i;\n\
  char name[100];\n\
\n\
  result = mem_alloc (SYSTEM_HEAP, sizeof(struct_dfs_stack_t));\n\
  result->id = id;\n\
  result->top = - 1;\n\
  result->size = 0;\n\
  result->current = 0;\n\
  result->files = 0;\n\
  for (i = 0; i < DFS_STACK_SLOTS; i ++) {\n\
    sprintf (name, \"DFS stack heap\");\n\
    result->heaps[i] = bounded_heap_new (name, DFS_STACK_SLOT_SIZE * 1024);\n\
    result->slots[i] = dfs_stack_slot_new ();\n\
  }\n\
  return result;\n\
}\n\
\n\
void dfs_stack_free\n\
(dfs_stack_t stack) {\n\
  int i;\n\
\n\
  if (stack) {\n\
    for (i = 0; i < DFS_STACK_SLOTS; i ++) {\n\
      if (stack->slots[i]) {\n\
	dfs_stack_slot_free (stack->slots[i]);\n\
      }\n\
      if (stack->heaps[i]) {\n\
	heap_free (stack->heaps[i]);\n\
      }\n\
    }\n\
    free (stack);\n\
  }\n\
}\n\
\n\
unsigned int dfs_stack_size\n\
(dfs_stack_t stack) {\n\
  if (stack) {\n\
    return stack->size;\n\
  } else {\n\
    return 0;\n\
  }\n\
}\n\
\n\
void dfs_stack_write\n\
(dfs_stack_t stack) {\n\
  int i;\n\
  unsigned int w;\n\
  FILE * f;\n\
  char buffer[10000];\n\
  dfs_stack_slot_t slot = stack->slots[0];\n\
  \n\
  sprintf (buffer, \"STACK-%d-%d\", stack->id, stack->files);\n\
  f = fopen (buffer, \"w\");\n\
  for (i = 0; i < DFS_STACK_SLOT_SIZE; i ++) {\n\
    w = event_set_char_width (slot->items[i].en);\n\
    fwrite (&(slot->items[i].n), sizeof (unsigned char), 1, f);\n\
    event_set_serialise (slot->items[i].en, &(buffer[0]));\n\
    event_set_free (slot->items[i].en);\n\
    fwrite (&w, sizeof (unsigned int), 1, f);\n\
    fwrite (&(buffer[0]), w, 1, f);\n\
    storage_id_serialise (slot->items[i].id, &(buffer[0]));\n\
    fwrite (&(buffer[0]), storage_id_char_width, 1, f);\n\
#if defined(POR) && defined(PROVISO)\n\
    fwrite (&(slot->items[i].prov_ok), sizeof(bool_t), 1, f);\n\
    fwrite (&(slot->items[i].fully_expanded), sizeof(bool_t), 1, f);\n\
#endif\n\
  }\n\
  fclose (f);\n\
  stack->files ++;\n\
}\n\
\n\
void dfs_stack_read\n\
(dfs_stack_t stack) {\n\
  int i;\n\
  unsigned int w;\n\
  FILE * f;\n\
  char buffer[10000], name[16];\n\
  dfs_stack_item_t item;\n\
\n\
  stack->files --;\n\
  sprintf (name, \"STACK-%d-%d\", stack->id, stack->files);\n\
  f = fopen (name, \"r\");\n\
  heap_reset (stack->heaps[0]);\n\
  for (i = 0; i < DFS_STACK_SLOT_SIZE; i ++) {\n\
    fread (&item.n, sizeof (unsigned char), 1, f);\n\
    fread (&w, sizeof (unsigned int), 1, f);\n\
    fread (&(buffer[0]), w, 1, f);\n\
    item.heap_pos = heap_get_position (stack->heaps[0]);\n\
    item.en = event_set_unserialise_mem (&buffer[0], stack->heaps[0]);\n\
    fread (&(buffer[0]), storage_id_char_width, 1, f);\n\
    item.id = storage_id_unserialise (&(buffer[0]));\n\
#if defined(POR) && defined(PROVISO)\n\
    fread (&(item.prov_ok), sizeof(bool_t), 1, f);\n\
    fread (&(item.fully_expanded), sizeof(bool_t), 1, f);\n\
#endif\n\
    stack->slots[0]->items[i] = item;\n\
  }\n\
  fclose (f);\n\
  remove (name);\n\
}\n\
\n\
void dfs_stack_push\n\
(dfs_stack_t      stack,\n\
 dfs_stack_item_t item) {\n\
  char name[100];\n\
  stack->top ++;\n\
  stack->size ++;\n\
  if (stack->top == DFS_STACK_SLOT_SIZE) {\n\
    if (stack->current == 1) {\n\
      dfs_stack_write (stack);\n\
      dfs_stack_slot_free (stack->slots[0]);\n\
      stack->slots[0] = stack->slots[1];\n\
      stack->slots[1] = dfs_stack_slot_new ();\n\
      heap_free (stack->heaps[0]);\n\
      stack->heaps[0] = stack->heaps[1];\n\
      sprintf (name, \"DFS stack heap\");\n\
      stack->heaps[1] = bounded_heap_new (name, DFS_STACK_SLOT_SIZE * 1024);\n\
    }\n\
    stack->current = 1;\n\
    stack->top = 0;\n\
  }\n\
  stack->slots[stack->current]->items[stack->top] = item;\n\
}\n\
\n\
void dfs_stack_pop\n\
(dfs_stack_t stack) {\n\
  if (stack->size == 0) {\n\
    fatal_error (\"dfs_stack_pop: empty stack\");\n\
  }\n\
  heap_set_position (stack->heaps[stack->current],\n\
		     stack->slots[stack->current]->items[stack->top].heap_pos);\n\
  event_set_free (stack->slots[stack->current]->items[stack->top].en);\n\
  stack->top --;\n\
  stack->size --;\n\
  if (stack->size > 0 && stack->top == -1) {\n\
    if (stack->current == 0) {\n\
      if (stack->files <= 0) {\n\
	fatal_error (\"dfs_stack_read: no file to read from\");\n\
      }\n\
      dfs_stack_read (stack);\n\
    }\n\
    stack->current = 0;\n\
    stack->top = DFS_STACK_SLOT_SIZE - 1;\n\
  }\n\
}\n\
\n\
dfs_stack_item_t dfs_stack_top\n\
(dfs_stack_t stack) {\n\
  if (stack->size == 0) {\n\
    fatal_error (\"dfs_stack_top: empty stack\");\n\
  }\n\
  return stack->slots[stack->current]->items[stack->top];\n\
}\n\
\n\
void dfs_stack_update_top\n\
(dfs_stack_t      stack,\n\
 dfs_stack_item_t item) {\n\
  stack->slots[stack->current]->items[stack->top] = item;\n\
}\n\
\n\
event_set_t dfs_stack_compute_events\n\
(dfs_stack_t stack,\n\
 state_t     s,\n\
 bool_t      filter,\n\
 event_t *   exec) {\n\
  event_set_t result;\n\
  unsigned int en_size;\n\
  dfs_stack_item_t item = stack->slots[stack->current]->items[stack->top];\n\
\n\
  if (stack->size == 0) {\n\
    fatal_error (\"dfs_stack_compute_events: empty stack\");\n\
  }\n\
  item.n = 0;\n\
  item.heap_pos = heap_get_position (stack->heaps[stack->current]);\n\
  result = state_enabled_events_mem (s, stack->heaps[stack->current]);\n\
#ifdef POR\n\
  if (filter) {\n\
    en_size = event_set_size (result);\n\
    state_stubborn_set (s, result);\n\
#ifdef PROVISO\n\
    item.prov_ok = TRUE;\n\
    item.fully_expanded = (en_size == event_set_size (result)) ? TRUE : FALSE;\n\
  } else {\n\
    item.prov_ok = TRUE;\n\
    item.fully_expanded = TRUE;\n\
#endif\n\
  }\n\
#endif\n\
#ifdef EDGE_LEAN\n\
  if (exec != NULL) {\n\
    bool_t keep_event (event_t e) {\n\
      return (LESS == event_cmp (*exec, e) ||\n\
	      !event_are_independent (e, *exec));\n\
    }\n\
    event_set_filter (result, keep_event);\n\
  }\n\
#endif\n\
  item.en = result;\n\
  stack->slots[stack->current]->items[stack->top] = item;\n\
  return result;\n\
}\n\
\n\
void dfs_stack_create_trace\n\
(dfs_stack_t blue_stack,\n\
 dfs_stack_t red_stack,\n\
 report_t    r) {\n\
  int now;\n\
  dfs_stack_t stack, stacks[2];\n\
  dfs_stack_item_t item;\n\
  int i;\n\
\n\
  stacks[0] = red_stack;\n\
  stacks[1] = blue_stack;\n\
  r->trace_len = blue_stack->size - 1;\n\
  if (red_stack) {\n\
    r->trace_len += red_stack->size - 1;\n\
  }\n\
  r->trace = mem_alloc (SYSTEM_HEAP, sizeof (event_t) * r->trace_len);\n\
  now = r->trace_len - 1;\n\
\n\
  for (i = 0; i < 2; i ++) {\n\
    stack = stacks[i];\n\
    if (stack) {\n\
      dfs_stack_pop (stack);\n\
      while (stack->size > 0) {\n\
	item = dfs_stack_top (stack);\n\
	r->trace[now --] = event_copy (event_set_nth (item.en, item.n - 1));\n\
	dfs_stack_pop (stack);\n\
      }\n\
    }\n\
  }\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "event.h", "w")
    f.write ("\
#ifndef LIB_EVENT\n\
#define LIB_EVENT\n\
\n\
#include \"model.h\"\n\
#include \"heap.h\"\n\
#include \"prop.h\"\n\
#include \"state.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
#ifdef ACTION_CHECK_LTL\n\
\n\
\n\
\n\
/*\n\
 *  event definition when doing LTL model checking\n\
 */\n\
\n\
typedef struct {\n\
  bool_t dummy;\n\
  mevent_id_t  m;\n\
  uint8_t b;\n\
} event_id_t;\n\
\n\
typedef struct {\n\
  bool_t dummy;\n\
  mevent_t m;\n\
  bevent_t b;\n\
} event_t;\n\
\n\
typedef struct {\n\
  mevent_set_t m;\n\
  bevent_t * b;\n\
  unsigned int b_size;\n\
  heap_t heap;\n\
} struct_event_set_t;\n\
typedef struct_event_set_t * event_set_t;\n\
\n\
bool_t event_is_dummy\n\
(event_t e);\n\
\n\
event_t event_copy\n\
(event_t e);\n\
\n\
void event_exec\n\
(event_t e,\n\
 state_t s);\n\
\n\
void event_undo\n\
(event_t e,\n\
 state_t s);\n\
\n\
void event_to_xml\n\
(event_t e,\n\
 FILE * f);\n\
\n\
unsigned int event_char_width\n\
(event_t e);\n\
\n\
void event_serialise\n\
(event_t e,\n\
 bit_vector_t v);\n\
\n\
event_t event_unserialise\n\
(bit_vector_t v);\n\
\n\
event_t event_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap);\n\
\n\
order_t event_cmp\n\
(event_t e,\n\
 event_t f);\n\
\n\
bool_t event_are_independent\n\
(event_t e,\n\
 event_t f);\n\
\n\
void event_set_free\n\
(event_set_t en);\n\
\n\
event_t event_set_nth\n\
(event_set_t en,\n\
 unsigned int n);\n\
\n\
event_id_t event_set_nth_id\n\
(event_set_t en,\n\
 unsigned int n);\n\
\n\
unsigned int event_set_size\n\
(event_set_t en);\n\
\n\
void event_set_serialise\n\
(event_set_t en,\n\
 bit_vector_t v);\n\
\n\
event_set_t event_set_unserialise\n\
(bit_vector_t v);\n\
\n\
event_set_t event_set_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap);\n\
\n\
unsigned int event_set_char_width\n\
(event_set_t en);\n\
\n\
event_set_t state_enabled_events\n\
(state_t s);\n\
\n\
event_set_t state_enabled_events_mem\n\
(state_t s,\n\
 heap_t heap);\n\
\n\
event_t state_enabled_event\n\
(state_t s,\n\
 event_id_t id);\n\
\n\
event_t state_enabled_event_mem\n\
(state_t s,\n\
 event_id_t id,\n\
 heap_t heap);\n\
\n\
void state_stubborn_set\n\
(state_t s,\n\
 event_set_t en);\n\
\n\
state_t state_succ\n\
(state_t s,\n\
 event_t e);\n\
\n\
state_t state_succ_mem\n\
(state_t s,\n\
 event_t e,\n\
 heap_t heap);\n\
\n\
state_t state_pred\n\
(state_t s,\n\
 event_t e);\n\
\n\
state_t state_pred_mem\n\
(state_t s,\n\
 event_t e,\n\
 heap_t heap);\n\
\n\
#else\n\
\n\
\n\
\n\
/*\n\
 *  event definition when not doing LTL model checking\n\
 */\n\
\n\
typedef mevent_id_t event_id_t;\n\
\n\
typedef mevent_t event_t;\n\
#define event_is_dummy(e) FALSE\n\
#define event_copy mevent_copy\n\
#define event_exec mevent_exec\n\
#define event_undo mevent_undo\n\
#define event_to_xml mevent_to_xml\n\
#define event_char_width mevent_char_width\n\
#define event_serialise mevent_serialise\n\
#define event_unserialise mevent_unserialise\n\
#define event_cmp mevent_cmp\n\
#define event_are_independent mevent_are_independent\n\
\n\
typedef mevent_set_t event_set_t;\n\
#define event_set_free mevent_set_free\n\
#define event_set_nth mevent_set_nth\n\
#define event_set_nth_id mevent_set_nth_id\n\
#define event_set_size mevent_set_size\n\
#define event_set_serialise mevent_set_serialise\n\
#define event_set_unserialise mevent_set_unserialise\n\
#define event_set_char_width mevent_set_char_width\n\
#define event_set_filter mevent_set_filter\n\
\n\
#define state_enabled_events mstate_enabled_events\n\
#define state_enabled_event mstate_enabled_event\n\
#define state_stubborn_set mstate_stubborn_set\n\
#define state_succ mstate_succ\n\
#define state_pred mstate_pred\n\
\n\
#ifdef USE_HELENA_HEAPS\n\
#define event_unserialise_mem mevent_unserialise_mem\n\
#define event_set_unserialise_mem mevent_set_unserialise_mem\n\
#define state_enabled_events_mem mstate_enabled_events_mem\n\
#define state_enabled_event_mem mstate_enabled_event_mem\n\
#define state_succ_mem mstate_succ_mem\n\
#define state_pred_mem mstate_pred_mem\n\
#else\n\
#define event_unserialise_mem(v, heap) mevent_unserialise (v)\n\
#define event_set_unserialise_mem(v, heap) mevent_set_unserialise (v)\n\
#define state_enabled_events_mem(s, heap) mstate_enabled_events (s)\n\
#define state_enabled_event_mem(s, heap) mstate_enabled_event (s)\n\
#define state_succ_mem(s, e, heap) mstate_succ (s, e)\n\
#define state_pred_mem(s, e, heap) mstate_pred (s, e)\n\
#endif\n\
\n\
#endif\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "event.c", "w")
    f.write ("\
#include \"event.h\"\n\
\n\
#ifdef ACTION_CHECK_LTL\n\
\n\
bool_t event_is_dummy\n\
(event_t e) {\n\
  return e.dummy;\n\
}\n\
\n\
event_t event_copy\n\
(event_t e) {\n\
  event_t result;\n\
  result.dummy = e.dummy;\n\
  result.b = e.b;\n\
  if (!e.dummy) {\n\
    result.m = mevent_copy (e.m);\n\
  }\n\
  return result;\n\
}\n\
\n\
void event_exec\n\
(event_t e,\n\
 state_t s) {\n\
  if (!e.dummy) {\n\
    mevent_exec (e.m, s->m);\n\
  }\n\
  s->b = e.b.to;\n\
}\n\
\n\
void event_undo\n\
(event_t e,\n\
 state_t s) {\n\
  if (!e.dummy) {\n\
    mevent_undo (e.m, s->m);\n\
  }\n\
  s->b = e.b.from;\n\
}\n\
\n\
void event_to_xml\n\
(event_t e,\n\
 FILE * f) {\n\
  if (!e.dummy) {\n\
    mevent_to_xml (e.m, f);\n\
  } else {\n\
    fatal_error (\"event_to_xml: called with dummy event\");\n\
  }\n\
}\n\
\n\
unsigned int event_char_width\n\
(event_t e) {\n\
  return 1 + 2 * bstate_char_width () +\n\
    (e.dummy ? 0 : mevent_char_width (e.m));\n\
}\n\
\n\
void event_serialise\n\
(event_t e,\n\
 bit_vector_t v) {\n\
  unsigned int bsize = bstate_char_width ();\n\
  memcpy (v, &(e.b.from), bsize);\n\
  memcpy (v + bsize, &(e.b.to), bsize);\n\
  v[bsize + bsize] = e.dummy;\n\
  if (!e.dummy) {\n\
    mevent_serialise (e.m, v + bsize + bsize + 1);\n\
  }\n\
}\n\
\n\
event_t event_unserialise\n\
(bit_vector_t v) {\n\
  return event_unserialise_mem (v, SYSTEM_HEAP);\n\
}\n\
\n\
order_t event_cmp\n\
(event_t e,\n\
 event_t f) {\n\
  order_t cmp;\n\
  if ((cmp = bevent_cmp (e.b, f.b)) != EQUAL) return cmp;\n\
  else if (e.dummy && f.dummy) return EQUAL;\n\
  else if (e.dummy) return LESS;\n\
  else if (f.dummy) return GREATER;\n\
  else return mevent_cmp (e.m, f.m);\n\
}\n\
\n\
bool_t event_are_independent\n\
(event_t e,\n\
 event_t f) {\n\
  fatal_error (\"event_are_independent: unimplemented feature\");\n\
}\n\
\n\
void event_set_free\n\
(event_set_t en) {\n\
  mevent_set_free (en->m);\n\
  mem_free (en->heap, en->b);\n\
  mem_free (en->heap, en);\n\
}\n\
\n\
unsigned int event_set_size\n\
(event_set_t en) {\n\
  if (en->b_size == 0) {\n\
    return 0;\n\
  }\n\
  if (mevent_set_size (en->m) == 0) {\n\
    return en->b_size;\n\
  }\n\
  return mevent_set_size (en->m) * en->b_size;\n\
}\n\
\n\
event_t event_set_nth\n\
(event_set_t en,\n\
 unsigned int n) {\n\
  event_t result;\n\
  if (en->b_size == 0) {\n\
    fatal_error (\"event_set_nth: empty set\");\n\
  }\n\
  if (mevent_set_size (en->m) == 0) {\n\
    result.dummy = TRUE;\n\
    result.b = en->b[n];\n\
  } else {\n\
    result.dummy = FALSE;\n\
    result.m = mevent_set_nth (en->m, n / en->b_size);\n\
    result.b = en->b[n % en->b_size];\n\
  }\n\
  return result;\n\
}\n\
\n\
event_id_t event_set_nth_id\n\
(event_set_t en,\n\
 unsigned int n) {\n\
  event_id_t result;\n\
  if (en->b_size == 0) {\n\
    fatal_error (\"event_set_nth_id: empty set\");\n\
  }\n\
  if (mevent_set_size (en->m) == 0) {\n\
    result.dummy = TRUE;\n\
    result.b = n;\n\
  } else {\n\
    result.dummy = FALSE;\n\
    result.m = mevent_set_nth_id (en->m, n / en->b_size);\n\
    result.b = n % en->b_size;\n\
  }\n\
  return result;\n\
}\n\
\n\
void event_set_serialise\n\
(event_set_t en,\n\
 bit_vector_t v) {\n\
  unsigned int bs = en->b_size * sizeof (bevent_t);\n\
  v[0] = en->b_size;\n\
  if (bs) {\n\
    memcpy (v + 1, en->b, bs);\n\
  }\n\
  mevent_set_serialise (en->m, v + 1 + bs);\n\
}\n\
\n\
event_set_t event_set_unserialise\n\
(bit_vector_t v) {\n\
  return event_set_unserialise_mem (v, SYSTEM_HEAP);\n\
}\n\
\n\
unsigned int event_set_char_width\n\
(event_set_t en) {\n\
  return 1 + (en->b_size * sizeof (bevent_t)) + mevent_set_char_width (en->m);\n\
}\n\
\n\
event_set_t state_enabled_events\n\
(state_t s) {\n\
  return state_enabled_events_mem (s, SYSTEM_HEAP);\n\
}\n\
\n\
event_t state_enabled_event\n\
(state_t s,\n\
 event_id_t id) {\n\
  return state_enabled_event_mem (s, id, SYSTEM_HEAP);\n\
}\n\
\n\
void state_stubborn_set\n\
(state_t s,\n\
 event_set_t en) {\n\
  mstate_stubborn_set (s->m, en->m);\n\
}\n\
\n\
state_t state_succ\n\
(state_t s,\n\
 event_t e) {\n\
  return state_succ_mem (s, e, SYSTEM_HEAP);\n\
}\n\
\n\
state_t state_pred\n\
(state_t s,\n\
 event_t e) {\n\
  return state_pred_mem (s, e, SYSTEM_HEAP);\n\
}\n\
\n\
event_t event_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap) {\n\
  event_t result;\n\
  unsigned int bsize = bstate_char_width ();\n\
  result.b.from = 0;\n\
  result.b.to = 0;\n\
  memcpy (&(result.b.from), v, bsize);\n\
  memcpy (&(result.b.to), v + bsize, bsize);\n\
  result.dummy = v[bsize + bsize];\n\
  if (!result.dummy) {\n\
    result.m = mevent_unserialise_mem (v + bsize + bsize + 1, heap);\n\
  }\n\
  return result;\n\
}\n\
\n\
event_set_t event_set_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap) {\n\
  event_set_t result = mem_alloc (heap, sizeof (struct_event_set_t));\n\
  unsigned int bs;\n\
  result->heap = heap;\n\
  result->b_size = v[0];\n\
  bs = result->b_size * sizeof (bevent_t);\n\
  result->b = mem_alloc (heap, sizeof(bevent_t) * result->b_size);\n\
  memcpy (result->b, v + 1, bs);\n\
  result->m = mevent_set_unserialise_mem (v + 1 + bs, heap);\n\
  return result;\n\
}\n\
\n\
event_set_t state_enabled_events_mem\n\
(state_t s,\n\
 heap_t heap) {\n\
  bstate_t succs[256];\n\
  unsigned int i;\n\
  event_set_t result = mem_alloc (heap, sizeof (struct_event_set_t));\n\
  result->heap = heap;\n\
  result->m = mstate_enabled_events_mem (s->m, heap);\n\
  bstate_succs (s->b, s->m, &succs[0], &(result->b_size));\n\
  result->b = mem_alloc (heap, sizeof (bevent_t) * result->b_size);\n\
  for (i = 0; i < result->b_size; i ++) {\n\
    result->b[i].from = s->b;\n\
    result->b[i].to = succs[i];\n\
  }\n\
  return result;\n\
}\n\
\n\
event_t state_enabled_event_mem\n\
(state_t s,\n\
 event_id_t id,\n\
 heap_t heap) {\n\
  event_t result;\n\
  bstate_t succs[256];\n\
  unsigned int b_size;\n\
\n\
  bstate_succs (s->b, s->m, &succs[0], &b_size);\n\
  result.b.from = s->b;\n\
  result.b.to = succs[id.b];\n\
  result.dummy = id.dummy;\n\
  if (!result.dummy) {\n\
    result.m = mstate_enabled_event_mem (s->m, id.m, heap);\n\
  }\n\
  return result;\n\
}\n\
\n\
state_t state_succ_mem\n\
(state_t s,\n\
 event_t e,\n\
 heap_t heap) {\n\
  state_t result;\n\
  result = mem_alloc (heap, sizeof (struct_state_t));\n\
  result->heap = heap;\n\
  result->m = mstate_succ_mem (s->m, e.m, heap);\n\
  result->b = e.b.to;\n\
  return result;\n\
}\n\
\n\
state_t state_pred_mem\n\
(state_t s,\n\
 event_t e,\n\
 heap_t heap) {\n\
  state_t result;\n\
  result = mem_alloc (heap, sizeof (struct_state_t));\n\
  result->heap = heap;\n\
  result->m = mstate_pred_mem (s->m, e.m, heap);\n\
  result->b = e.b.from;\n\
  return result;\n\
}\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "hash_array.h", "w")
    f.write ("\
#ifndef LIB_HASH_ARRAY\n\
#define LIB_HASH_ARRAY\n\
\n\
#include \"common.h\"\n\
#include \"heap.h\"\n\
\n\
typedef hash_key_t harray_key_t;\n\
\n\
typedef uint32_t harray_index_t;\n\
\n\
typedef uint32_t harray_size_t;\n\
\n\
typedef uint8_t harray_status_t;\n\
\n\
typedef void * harray_value_t;\n\
\n\
typedef void * harray_iter_data_t;\n\
\n\
typedef void (* harray_iter_func_t) (harray_key_t, harray_value_t,\n\
				     harray_iter_data_t);\n\
\n\
typedef bool_t (* harray_pred_func_t) (harray_key_t, harray_value_t,\n\
				       harray_iter_data_t);\n\
\n\
typedef harray_key_t (* harray_hash_func_t) (harray_value_t);\n\
\n\
typedef order_t (* harray_cmp_func_t) (harray_value_t, harray_value_t);\n\
\n\
typedef void (* harray_free_func_t) (harray_value_t);\n\
\n\
typedef struct {\n\
  heap_t             heap;\n\
  harray_size_t      num_items;\n\
  harray_size_t      size;\n\
  harray_status_t *  status;\n\
  harray_key_t *     keys;\n\
  harray_value_t *   values;\n\
  harray_hash_func_t fhash;\n\
  harray_cmp_func_t  fcmp;\n\
  harray_free_func_t ffree;\n\
} struct_harray_t;\n\
\n\
typedef struct_harray_t * harray_t;\n\
\n\
harray_t harray_new\n\
(heap_t             heap,\n\
 harray_size_t      size,\n\
 harray_hash_func_t fhash,\n\
 harray_cmp_func_t  fcmp,\n\
 harray_free_func_t ffree);\n\
\n\
void harray_free\n\
(harray_t harray);\n\
\n\
harray_size_t harray_num_items\n\
(harray_t harray);\n\
\n\
bool_t harray_insert\n\
(harray_t       harray,\n\
 harray_value_t val);\n\
\n\
void harray_delete\n\
(harray_t       harray,\n\
 harray_value_t val);\n\
\n\
harray_value_t harray_lookup\n\
(harray_t       harray,\n\
 harray_value_t val);\n\
\n\
void harray_app\n\
(harray_t           harray,\n\
 harray_iter_func_t f,\n\
 harray_iter_data_t data);\n\
\n\
void harray_filter\n\
(harray_t           harray,\n\
 harray_pred_func_t f,\n\
 harray_iter_data_t data);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "hash_array.c", "w")
    f.write ("\
#include \"hash_array.h\"\n\
\n\
#define HARRAY_NONE 0\n\
#define HARRAY_SOME 1\n\
#define HARRAY_DEL  2\n\
\n\
harray_t harray_new\n\
(heap_t             heap,\n\
 harray_size_t      size,\n\
 harray_hash_func_t fhash,\n\
 harray_cmp_func_t  fcmp,\n\
 harray_free_func_t ffree) {\n\
  harray_index_t i;\n\
  harray_t result = mem_alloc (heap, sizeof (struct_harray_t));\n\
  result->num_items = 0;\n\
  result->heap = heap;\n\
  result->size = size;\n\
  result->fhash = fhash;\n\
  result->fcmp = fcmp;\n\
  result->ffree = ffree;\n\
  result->status = mem_alloc (heap, size * sizeof (harray_status_t));\n\
  result->keys = mem_alloc (heap, size * sizeof (harray_key_t));\n\
  result->values = mem_alloc (heap, size * sizeof (harray_value_t));\n\
  for (i = 0; i < size; i ++) {\n\
    result->status[i] = HARRAY_NONE;\n\
  }\n\
  return result;\n\
}\n\
\n\
void harray_free\n\
(harray_t harray) {\n\
  harray_index_t i;\n\
  if (harray->ffree) {\n\
    for (i = 0; i < harray->size; i ++) {\n\
      if (harray->status[i] == HARRAY_SOME) {\n\
	(*harray->ffree) (harray->values[i]);\n\
      }\n\
    }\n\
  }\n\
  mem_free (harray->heap, harray->status);\n\
  mem_free (harray->heap, harray->keys);\n\
  mem_free (harray->heap, harray->values);\n\
  mem_free (harray->heap, harray);\n\
}\n\
\n\
harray_size_t harray_num_items\n\
(harray_t harray) {\n\
  return harray->num_items;\n\
}\n\
\n\
bool_t harray_insert\n\
(harray_t       harray,\n\
 harray_value_t val) {\n\
  harray_key_t key = (*harray->fhash) (val);\n\
  harray_index_t new_pos, pos = key % harray->size, fst_pos = pos;\n\
  bool_t loop = TRUE;\n\
  bool_t pos_found = FALSE;\n\
  bool_t result = FALSE;\n\
\n\
  while (loop) {\n\
    switch (harray->status[pos]) {\n\
    case HARRAY_NONE: {\n\
      if (pos_found) {\n\
	pos = new_pos;\n\
      }\n\
      harray->status[pos] = HARRAY_SOME;\n\
      harray->keys[pos] = key;\n\
      harray->values[pos] = val;\n\
      harray->num_items ++;\n\
      loop = FALSE;\n\
      result = TRUE;\n\
      break;\n\
    }\n\
    case HARRAY_SOME: {\n\
      if ((harray->keys[pos] == key) &&\n\
	  (EQUAL == (*harray->fcmp) (val, harray->values[pos]))) {\n\
	loop = FALSE;\n\
      } else {\n\
	pos = (pos + 1) % harray->size;\n\
      }\n\
      break;\n\
    }\n\
    case HARRAY_DEL: {\n\
      if (!pos_found) {\n\
	pos_found = TRUE;\n\
	new_pos = pos;\n\
      }\n\
      pos = (pos + 1) % harray->size;\n\
      break;\n\
    }\n\
    }\n\
    if (loop && pos == fst_pos) {\n\
      fatal_error (\"harray_insert: resizing not implemented\");\n\
    }\n\
  }\n\
  return result;\n\
}\n\
\n\
void harray_delete\n\
(harray_t       harray,\n\
 harray_value_t val) {\n\
  fatal_error (\"harray_delete: function not implemented\");\n\
}\n\
\n\
harray_value_t harray_lookup\n\
(harray_t       harray,\n\
 harray_value_t val) {\n\
  harray_value_t result = NULL;\n\
  harray_key_t key = (*harray->fhash) (val);\n\
  harray_index_t pos = key % harray->size;\n\
  bool_t loop = TRUE;\n\
\n\
  while (loop) {\n\
    switch (harray->status[pos]) {\n\
    case HARRAY_NONE: {\n\
      loop = FALSE;\n\
    }\n\
    case HARRAY_DEL: {\n\
      pos = (pos + 1) % harray->size;\n\
      break;\n\
    }\n\
    case HARRAY_SOME: {\n\
      if ((harray->keys[pos] == key) &&\n\
	  (EQUAL == (*harray->fcmp) (val, harray->values[pos]))) {\n\
	result = harray->values[pos];\n\
	loop = FALSE;\n\
      } else {\n\
	pos = (pos + 1) % harray->size;\n\
      }\n\
      break;\n\
    }\n\
    }\n\
  }  \n\
  return result;\n\
}\n\
\n\
void harray_app\n\
(harray_t           harray,\n\
 harray_iter_func_t f,\n\
 harray_iter_data_t data) {\n\
  harray_index_t i;\n\
\n\
  for (i = 0; i < harray->size; i ++) {\n\
    if (HARRAY_SOME == harray->status[i]) {\n\
      (*f) (harray->keys[i], harray->values[i], data);\n\
    }\n\
  }\n\
}\n\
\n\
void harray_filter\n\
(harray_t           harray,\n\
 harray_pred_func_t f,\n\
 harray_iter_data_t data) {\n\
  harray_index_t i;\n\
\n\
  for (i = 0; i < harray->size; i ++) {\n\
    if (HARRAY_SOME == harray->status[i]\n\
	&& (!(*f) (harray->keys[i], harray->values[i], data))) {\n\
      harray->status[i] = HARRAY_DEL;\n\
      if (harray->ffree) {\n\
	(*harray->ffree) (harray->values[i]);\n\
      }\n\
    }\n\
  }\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "hash_storage.h", "w")
    f.write ("\
#ifndef LIB_HASH_STORAGE\n\
#define LIB_HASH_STORAGE\n\
\n\
#include \"state.h\"\n\
#include \"event.h\"\n\
#include \"heap.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void init_hash_storage ();\n\
void free_hash_storage ();\n\
\n\
typedef uint8_t pos_t;\n\
\n\
typedef struct {\n\
  hash_key_t h;\n\
  pos_t p;\n\
} hash_storage_id_t;\n\
\n\
#ifdef STORAGE_HASH\n\
typedef bit_vector_t encoded_state_t;\n\
#elif defined (STORAGE_DELTA)\n\
#define ENCODED_STATE_CHAR_WIDTH			\\\n\
  (ATTRIBUTES_CHAR_WIDTH + sizeof (bit_vector_t))\n\
typedef char encoded_state_t[ENCODED_STATE_CHAR_WIDTH];\n\
#elif defined (STORAGE_HASH_COMPACTION)\n\
#define ENCODED_STATE_CHAR_WIDTH		\\\n\
  (ATTRIBUTES_CHAR_WIDTH + sizeof (hash_key_t))\n\
typedef char encoded_state_t[ENCODED_STATE_CHAR_WIDTH];\n\
#endif\n\
\n\
typedef struct {\n\
#ifdef ATTRIBUTE_NUM\n\
  uint32_t num;\n\
#endif\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
  bool_t in_unproc;\n\
#endif\n\
#ifdef ATTRIBUTE_REFS\n\
  unsigned int refs;\n\
#endif\n\
#ifdef ATTRIBUTE_PRED\n\
  hash_storage_id_t pred;\n\
#endif\n\
#ifdef ATTRIBUTE_IS_RED\n\
  bool_t is_red;\n\
#endif\n\
} hash_storage_state_attr_t;\n\
\n\
typedef void (* hash_storage_fold_func_t) (state_t, hash_storage_id_t, void *);\n\
\n\
hash_storage_id_t null_hash_storage_id;\n\
\n\
unsigned int hash_storage_id_char_width;\n\
\n\
bool_t hash_storage_id_is_null\n\
(hash_storage_id_t id);\n\
\n\
void hash_storage_id_serialise\n\
(hash_storage_id_t id,\n\
 bit_vector_t v);\n\
\n\
hash_storage_id_t hash_storage_id_unserialise\n\
(bit_vector_t v);\n\
\n\
order_t hash_storage_id_cmp\n\
(hash_storage_id_t id1,\n\
 hash_storage_id_t id2);\n\
\n\
typedef struct {\n\
  large_unsigned_t  hash_size;\n\
  large_unsigned_t  events_executed[NO_WORKERS];\n\
  large_unsigned_t  state_cmps[NO_WORKERS];\n\
  unsigned short    no_states[HASH_SIZE];\n\
  encoded_state_t * states[HASH_SIZE];\n\
  state_num_t       state_next_num;\n\
  unsigned int      seed;\n\
#ifdef STORAGE_DELTA\n\
  heap_t            reconstruction_heaps[NO_WORKERS];\n\
#endif\n\
#ifdef STATE_CACHING\n\
  hash_storage_id_t cache[STATE_CACHING_CACHE_SIZE];\n\
  unsigned int      cache_size;\n\
  unsigned int      cache_ctr;\n\
#endif\n\
} struct_hash_storage_t;\n\
\n\
typedef struct_hash_storage_t * hash_storage_t;\n\
\n\
hash_storage_t hash_storage_default_new\n\
();\n\
\n\
hash_storage_t hash_storage_new\n\
(large_unsigned_t hash_size);\n\
\n\
void hash_storage_free\n\
(hash_storage_t storage);\n\
\n\
void hash_storage_insert\n\
(hash_storage_t      storage,\n\
 state_t             s,\n\
 hash_storage_id_t * pred,\n\
 event_id_t *        exec,\n\
 unsigned int        depth,\n\
 worker_id_t         w,\n\
 bool_t *            is_new,\n\
 hash_storage_id_t * id);\n\
\n\
void hash_storage_remove\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id);\n\
\n\
large_unsigned_t storage_size\n\
(hash_storage_t storage);\n\
\n\
order_t hash_storage_id_cmp\n\
(hash_storage_id_t id1,\n\
 hash_storage_id_t id2);\n\
\n\
state_t hash_storage_get\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t ptr,\n\
 worker_id_t       w);\n\
\n\
state_t hash_storage_get_mem\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t ptr,\n\
 worker_id_t       w,\n\
 heap_t            heap);\n\
\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
void hash_storage_set_in_unproc\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 bool_t            in_unproc);\n\
#else\n\
#define hash_storage_set_in_unproc(s, i, val) {}\n\
#endif\n\
\n\
bool_t hash_storage_get_in_unproc\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id);\n\
\n\
state_num_t hash_storage_get_num\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id);\n\
\n\
void hash_storage_update_refs\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 int               update);\n\
\n\
large_unsigned_t hash_storage_size\n\
(hash_storage_t storage);\n\
\n\
void hash_storage_get_attr\n\
(hash_storage_t              storage,\n\
 state_t                     s,\n\
 worker_id_t                 w,\n\
 bool_t *                    found,\n\
 hash_storage_id_t *         id,\n\
 hash_storage_state_attr_t * attrs);\n\
\n\
void hash_storage_build_trace\n\
(hash_storage_t    storage,\n\
 worker_id_t       w,\n\
 hash_storage_id_t id,\n\
 event_t **        trace,\n\
 unsigned int *    trace_len);\n\
\n\
void hash_storage_set_is_red\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id);\n\
\n\
void hash_storage_fold\n\
(hash_storage_t           storage,\n\
 worker_id_t              w,\n\
 hash_storage_fold_func_t f,\n\
 void *                   data);\n\
\n\
void hash_storage_output_stats\n\
(hash_storage_t storage,\n\
 FILE *         out);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "hash_storage.c", "w")
    f.write ("\
#include \"hash_storage.h\"\n\
#include \"report.h\"\n\
#include \"math.h\"\n\
#include \"vectors.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
#define DELTA_STATE    0\n\
#define EXPLICIT_STATE 1\n\
\n\
#define move_to_attribute(bits, pos) { \\\n\
    VECTOR_start (bits);	       \\\n\
    VECTOR_move (bits, pos);	       \\\n\
  }\n\
\n\
#define hash_storage_id_serialise_bits(id, bits) {	\\\n\
    VECTOR_set_size32 ((bits), (id).h);			\\\n\
    VECTOR_set_size8 ((bits), (id).p);			\\\n\
  }\n\
\n\
#define hash_storage_id_unserialise_bits(bits, id) {	\\\n\
    VECTOR_get_size32 ((bits), (id).h);			\\\n\
    VECTOR_get_size8 ((bits), (id).p);			\\\n\
}\n\
\n\
#ifdef STORAGE_HASH\n\
#define hash_storage_copy_encoded_state(src, dest) { (dest) = (src); }\n\
#else\n\
#define hash_storage_copy_encoded_state(src, dest) {			\\\n\
    unsigned int cp_idx = 0;						\\\n\
    for (cp_idx = 0; cp_idx < sizeof (encoded_state_t); cp_idx ++) {	\\\n\
      dest[cp_idx] = src[cp_idx];					\\\n\
    }									\\\n\
  }\n\
#endif\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_id_is_null\n\
 *\n\
 *****/\n\
bool_t hash_storage_id_is_null\n\
(hash_storage_id_t id) {\n\
  return\n\
    ((id.h == null_hash_storage_id.h) && (id.p == null_hash_storage_id.p)) ?\n\
    TRUE : FALSE;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_id_serialise\n\
 *\n\
 *****/\n\
void hash_storage_id_serialise\n\
(hash_storage_id_t id,\n\
 bit_vector_t      v) {\n\
  vector bits;\n\
  bits.vector = v;\n\
  VECTOR_start (bits);\n\
  hash_storage_id_serialise_bits (id, bits);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_id_unserialise\n\
 *\n\
 *****/\n\
hash_storage_id_t hash_storage_id_unserialise\n\
(bit_vector_t v) {\n\
  hash_storage_id_t result;\n\
  vector bits;\n\
  bits.vector = v;\n\
  VECTOR_start (bits);\n\
  hash_storage_id_unserialise_bits (bits, result);\n\
  return result;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_id_cmp\n\
 *\n\
 *****/\n\
order_t hash_storage_id_cmp\n\
(hash_storage_id_t id1,\n\
 hash_storage_id_t id2) {\n\
  if (id1.h < id2.h) return LESS;\n\
  if (id1.h > id2.h) return GREATER;\n\
  if (id1.p < id2.p) return LESS;\n\
  if (id1.p > id2.p) return GREATER;\n\
  return EQUAL;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_cache_state\n\
 *\n\
 *****/\n\
void hash_storage_cache_state\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
#ifdef STATE_CACHING\n\
  if (storage->cache_size < STATE_CACHING_CACHE_SIZE) {\n\
    storage->cache[storage->cache_size] = id;\n\
    storage->cache_size ++;\n\
  } else {\n\
    hash_storage_id_t to_rem;\n\
#if STATE_CACHING_CACHE_SIZE == 0\n\
    to_rem = id;\n\
#else\n\
    if (0 != storage->cache_ctr) {\n\
      to_rem = id;\n\
    } else {\n\
      unsigned int rep =\n\
	random_int (&storage->seed) % STATE_CACHING_CACHE_SIZE;\n\
      to_rem = storage->cache[rep];\n\
      storage->cache[rep] = id;\n\
    }\n\
    storage->cache_ctr = (storage->cache_ctr + 1) % STATE_CACHING_PROP;      \n\
#endif\n\
    hash_storage_remove (storage, to_rem);\n\
  }\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_default_new\n\
 *\n\
 *****/\n\
hash_storage_t hash_storage_default_new\n\
() {\n\
  return hash_storage_new (HASH_SIZE);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_new\n\
 *\n\
 *****/\n\
hash_storage_t hash_storage_new\n\
(large_unsigned_t hash_size) {\n\
  int i;\n\
  hash_storage_t result;\n\
  worker_id_t w;\n\
  char name[100];\n\
  \n\
  result = mem_alloc (SYSTEM_HEAP, sizeof (struct_hash_storage_t));\n\
  result->hash_size = hash_size;\n\
  for (i = 0; i < result->hash_size; i ++) {\n\
    result->no_states[i] = 0;\n\
    result->states[i] = NULL;\n\
  }\n\
  result->state_next_num = 0;\n\
  result->seed = random_seed (0);\n\
#ifdef STATE_CACHING\n\
  result->cache_size = 0;\n\
  result->cache_ctr = 0;\n\
#endif\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    result->state_cmps[w] = 0;\n\
    result->events_executed[w] = 0;\n\
  }\n\
#ifdef STORAGE_DELTA\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    sprintf (name, \"reconstruction heap of worker %d\", w);\n\
    result->reconstruction_heaps[w] = bounded_heap_new (name, 1024 * 1024);\n\
  }\n\
#endif\n\
  return result;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_free\n\
 *\n\
 *****/\n\
void hash_storage_free\n\
(hash_storage_t storage) {\n\
  int i, j;\n\
  worker_id_t w;\n\
  bit_vector_t v;\n\
  vector bits;\n\
  unsigned char t;\n\
\n\
  for (i = 0; i < storage->hash_size; i ++) {\n\
    if (storage->states[i]) {\n\
      for (j = 0; j < storage->no_states[i]; j ++) {\n\
#if   defined(STORAGE_HASH)\n\
	mem_free (SYSTEM_HEAP, storage->states[i][j]);\n\
#elif defined(STORAGE_DELTA)\n\
	bits.vector = storage->states[i][j];\n\
	move_to_attribute (bits, ATTRIBUTE_TYPE_POS);\n\
	VECTOR_get_size1 (bits, t);\n\
	if (EXPLICIT_STATE == t) {\n\
	  memcpy (&v, &bits.vector[ATTRIBUTES_CHAR_WIDTH],\n\
		  sizeof (bit_vector_t));\n\
	  mem_free (SYSTEM_HEAP, v);\n\
	}\n\
#endif\n\
      }\n\
      mem_free (SYSTEM_HEAP, storage->states[i]);\n\
    }\n\
  }\n\
#ifdef STORAGE_DELTA\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    heap_free (storage->reconstruction_heaps[w]);\n\
  }\n\
#endif\n\
  mem_free (SYSTEM_HEAP, storage);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_size\n\
 *\n\
 *****/\n\
large_unsigned_t hash_storage_size\n\
(hash_storage_t storage) {\n\
  large_unsigned_t result = 0;\n\
  unsigned int i = 0;\n\
  for (i = 0; i < storage->hash_size; i ++) {\n\
    result += (large_unsigned_t) storage->no_states[i];\n\
  }\n\
  return result;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_get_vector\n\
 *\n\
 *****/\n\
bit_vector_t hash_storage_get_vector\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
  unsigned int slot = id.h % storage->hash_size, i;\n\
  bit_vector_t result;\n\
  vector bits;\n\
  pos_t p;\n\
  for (i = 0; i < storage->no_states[slot]; i ++) {\n\
    bits.vector = storage->states[slot][i];\n\
    VECTOR_start (bits);\n\
    VECTOR_get_size8 (bits, p);\n\
    if (p == id.p) {\n\
      result = storage->states[slot][i];\n\
      return result;\n\
    }\n\
  }\n\
  return NULL;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_reconstruct_delta_state\n\
 *\n\
 *****/\n\
#ifdef STORAGE_DELTA\n\
\n\
state_t hash_storage_reconstruct_delta_state\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 worker_id_t       w,\n\
 heap_t            heap);\n\
\n\
state_t hash_storage_reconstruct_delta_state_vec\n\
(hash_storage_t storage,\n\
 bit_vector_t   v,\n\
 worker_id_t    w,\n\
 heap_t         heap) {\n\
  state_t result;\n\
  vector bits;\n\
  bool_t found;\n\
  unsigned char t;\n\
  bit_vector_t e;\n\
  hash_storage_id_t id_pred;\n\
  event_id_t exec;\n\
  event_t ev;\n\
\n\
  /*\n\
   *  decode attributes of the state\n\
   */\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_TYPE_POS);\n\
  VECTOR_get_size1(bits, t);\n\
\n\
  switch (t) {\n\
\n\
    /*\n\
     *  it is an explicit state => simply decode it\n\
     */\n\
  case EXPLICIT_STATE:\n\
    memcpy (&e, v + ATTRIBUTES_CHAR_WIDTH, sizeof (bit_vector_t));\n\
    result = state_unserialise_mem (e, heap);\n\
    break;\n\
\n\
    /*\n\
     *  it is a delta state => reconstruct the predecessor and execute\n\
     *  the event\n\
     */\n\
  case DELTA_STATE: {    \n\
    move_to_attribute (bits, ATTRIBUTE_PRED_POS);\n\
    hash_storage_id_unserialise_bits (bits, id_pred);\n\
\n\
    /*\n\
     *  no predecessor => we have reached the initial state.\n\
     *  otherwise, we reconstruct the predecessor, decode the event\n\
     *  and execute it\n\
     */\n\
    if (hash_storage_id_is_null (id_pred)) {\n\
      result = state_initial_mem (heap);\n\
    } else {\n\
      memcpy (&exec, v + ATTRIBUTES_CHAR_WIDTH, sizeof (event_id_t));\n\
      result = hash_storage_reconstruct_delta_state (storage, id_pred,\n\
						     w, heap);\n\
      ev = state_enabled_event_mem (result, exec, heap);\n\
      event_exec (ev, result);\n\
      storage->events_executed[w] ++;\n\
    }\n\
    break;\n\
  }\n\
  default:\n\
    fatal_error\n\
      (\"hash_storage_reconstruct_delta_state_vec: impossible state type\");\n\
    break;\n\
  }\n\
  return result;\n\
}\n\
\n\
state_t hash_storage_reconstruct_delta_state\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 worker_id_t       w,\n\
 heap_t            heap) {\n\
  bit_vector_t v = hash_storage_get_vector (storage, id);\n\
  if (!v) {\n\
    fatal_error (\"hash_storage_reconstruct_delta_state: could not find state\");\n\
  }\n\
  return hash_storage_reconstruct_delta_state_vec (storage, v, w, heap);\n\
}\n\
#endif\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_check_state\n\
 *\n\
 *  check if state s is the state encoded in vector v\n\
 *\n\
 *****/\n\
bool_t hash_storage_check_state\n\
(hash_storage_t storage,\n\
 bit_vector_t   v,\n\
 state_t        s,\n\
 hash_key_t     h,\n\
 worker_id_t    w) {\n\
#if   defined(STORAGE_HASH)\n\
  return state_cmp_vector (s, v + ATTRIBUTES_CHAR_WIDTH);\n\
#elif defined(STORAGE_DELTA)\n\
  state_t t;\n\
  bool_t result;\n\
  heap_reset (storage->reconstruction_heaps[w]);\n\
  t = hash_storage_reconstruct_delta_state_vec\n\
    (storage, v, w, storage->reconstruction_heaps[w]);\n\
  result = state_equal (s, t);\n\
  state_free (t);\n\
  return result;\n\
#elif defined(STORAGE_HASH_COMPACTION)\n\
  hash_key_t k;\n\
  memcpy (&k, v + ATTRIBUTES_CHAR_WIDTH, sizeof (hash_key_t));\n\
  return (k == h) ? TRUE : FALSE;\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_insert\n\
 *\n\
 *****/\n\
void hash_storage_insert\n\
(hash_storage_t      storage,\n\
 state_t             s,\n\
 hash_storage_id_t * id_pred,\n\
 event_id_t *        exec,\n\
 unsigned int        depth,\n\
 worker_id_t         w,\n\
 bool_t *            is_new,\n\
 hash_storage_id_t * id) {\n\
  vector bits;\n\
  unsigned int slot; \n\
  int i, j;\n\
  unsigned char t;\n\
  state_num_t no;\n\
  encoded_state_t * new_states, es;\n\
  unsigned int len;\n\
  bit_vector_t v;\n\
  pos_t pos, new_pos;\n\
  bool_t pos_found = FALSE;\n\
\n\
  id->h = state_hash (s);\n\
  slot = id->h % storage->hash_size;\n\
  *is_new = TRUE;\n\
\n\
  /*\n\
   *  look for the state in the slot\n\
   */\n\
  new_pos = storage->no_states[slot];\n\
  for (i = 0; i < storage->no_states[slot]; i ++) {\n\
    storage->state_cmps[w] ++;\n\
    bits.vector = storage->states[slot][i];\n\
    VECTOR_start (bits);\n\
    VECTOR_get_size8 (bits, pos);\n\
    if (i != pos && (!pos_found)) {\n\
      pos_found = TRUE;\n\
      new_pos = i;\n\
    }\n\
    if (hash_storage_check_state (storage, storage->states[slot][i],\n\
				  s, id->h, w)) {\n\
      id->p = pos;\n\
      *is_new = FALSE;\n\
      break;\n\
    }\n\
  }\n\
\n\
  if (*is_new) {\n\
    \n\
    /*\n\
     *  compute the size of the state vector\n\
     */\n\
#if   defined(STORAGE_HASH)\n\
    len = state_char_width (s) + ATTRIBUTES_CHAR_WIDTH;\n\
    es = mem_alloc (SYSTEM_HEAP, len);\n\
    for (j = 0; j < len; j ++) {\n\
      es[j] = 0;\n\
    }\n\
#elif defined(STORAGE_DELTA)\n\
    t = (depth % STORAGE_DELTA_K == 0) ? EXPLICIT_STATE : DELTA_STATE;\n\
    if (EXPLICIT_STATE == t) {\n\
      len = state_char_width (s);\n\
      v = mem_alloc (SYSTEM_HEAP, len);\n\
      for (j = 0; j < len; j ++) {\n\
	v[j] = 0;\n\
      }\n\
    }\n\
#endif\n\
\n\
    /*\n\
     *  encode attributes of the state\n\
     */\n\
    bits.vector = &es[0];\n\
    id->p = new_pos;\n\
    VECTOR_start (bits);\n\
    VECTOR_set_size8 (bits, new_pos);\n\
#ifdef ATTRIBUTE_NUM\n\
    move_to_attribute (bits, ATTRIBUTE_NUM_POS);\n\
    no = storage->state_next_num;\n\
    storage->state_next_num ++;\n\
    VECTOR_set_size32 (bits, no);\n\
#endif\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
    move_to_attribute (bits, ATTRIBUTE_IN_UNPROC_POS);\n\
    VECTOR_set_size1 (bits, TRUE);\n\
#endif\n\
#ifdef ATTRIBUTE_TYPE\n\
    move_to_attribute (bits, ATTRIBUTE_TYPE_POS);\n\
    VECTOR_set_size1 (bits, t);\n\
#endif\n\
#ifdef ATTRIBUTE_REFS\n\
    move_to_attribute (bits, ATTRIBUTE_REFS_POS);\n\
    VECTOR_set (bits, 1, ATTRIBUTE_REFS_WIDTH);\n\
#endif\n\
#ifdef ATTRIBUTE_PRED\n\
    move_to_attribute (bits, ATTRIBUTE_PRED_POS);\n\
    if (id_pred == NULL) {\n\
      hash_storage_id_serialise_bits (null_hash_storage_id, bits);\n\
    } else {\n\
      hash_storage_id_serialise_bits (*id_pred, bits);\n\
#ifdef ATTRIBUTE_REFS\n\
      hash_storage_update_refs (storage, *id_pred, 1);\n\
#endif\n\
    }\n\
#endif\n\
#ifdef ATTRIBUTE_IS_RED\n\
    move_to_attribute (bits, ATTRIBUTE_IS_RED_POS);\n\
    VECTOR_set_size1 (bits, FALSE);\n\
#endif\n\
\n\
    /*\n\
     *  encode the state\n\
     */\n\
#if   defined(STORAGE_HASH)\n\
    state_serialise (s, es + ATTRIBUTES_CHAR_WIDTH);\n\
#elif defined(STORAGE_DELTA)\n\
    if (EXPLICIT_STATE == t) {\n\
      state_serialise (s, v);\n\
      memcpy (es + ATTRIBUTES_CHAR_WIDTH, &v, sizeof (bit_vector_t));\n\
    } else {\n\
      if (id_pred != NULL) {\n\
	memcpy (es + ATTRIBUTES_CHAR_WIDTH, exec, sizeof (event_id_t));\n\
      }\n\
    }\n\
#elif defined(STORAGE_HASH_COMPACTION)\n\
    bits.vector = es + ATTRIBUTES_CHAR_WIDTH;\n\
    memcpy (es + ATTRIBUTES_CHAR_WIDTH, &id->h, sizeof (hash_key_t));\n\
#endif\n\
\n\
    /*\n\
     *  and finally replace the slot in the hash table\n\
     */\n\
    new_states =\n\
      mem_alloc (SYSTEM_HEAP,\n\
		 sizeof (encoded_state_t) * (storage->no_states[slot] + 1));\n\
    for (j = 0; j < new_pos; j ++) {\n\
      hash_storage_copy_encoded_state (storage->states[slot][j],\n\
				       new_states[j]);\n\
    }\n\
    hash_storage_copy_encoded_state (es, new_states[j]);\n\
    for (; j < storage->no_states[slot]; j ++) {\n\
      hash_storage_copy_encoded_state (storage->states[slot][j],\n\
				       new_states[j + 1]);\n\
    }\n\
    if (storage->states[slot]) {\n\
      free (storage->states[slot]);\n\
    }\n\
    storage->states[slot] = new_states;\n\
    storage->no_states[slot] ++;\n\
  }\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_remove\n\
 *\n\
 *  removes from storage the state with specified id\n\
 *\n\
 *****/\n\
void hash_storage_remove\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
  unsigned int slot = id.h % storage->hash_size, i, j, k;\n\
  vector bits;\n\
  bool_t found = FALSE;\n\
  pos_t p;\n\
  encoded_state_t * new_states;\n\
  hash_storage_id_t id_pred;\n\
  unsigned char t;\n\
  bit_vector_t v;\n\
\n\
  for (i = 0; i < storage->no_states[slot]; i ++) {\n\
    bits.vector = storage->states[slot][i];\n\
    VECTOR_start (bits);\n\
    VECTOR_get_size8 (bits, p);\n\
    if (p == id.p) {\n\
#if defined(ATTRIBUTE_REFS) && defined(ATTRIBUTE_PRED)\n\
      id_pred = null_hash_storage_id;\n\
      move_to_attribute (bits, ATTRIBUTE_PRED_POS);\n\
      hash_storage_id_unserialise_bits (bits, id_pred);\n\
#endif\n\
      found = TRUE;\n\
#if defined(STORAGE_HASH)\n\
      free (storage->states[slot][i]);\n\
#elif defined(STORAGE_DELTA)\n\
      move_to_attribute (bits, ATTRIBUTE_TYPE_POS);\n\
      VECTOR_get_size1 (bits, t);\n\
      if (EXPLICIT_STATE == t) {\n\
	memcpy (&v, bits.vector + ATTRIBUTES_CHAR_WIDTH,\n\
		sizeof (bit_vector_t));\n\
	free (v);\n\
      }\n\
#endif\n\
      storage->no_states[slot] --;\n\
      if (0 == storage->no_states[slot]) {\n\
	new_states = NULL;\n\
      }\n\
      else {\n\
	new_states =\n\
	  mem_alloc (SYSTEM_HEAP,\n\
		     sizeof (encoded_state_t) * storage->no_states[slot]);\n\
	k = 0;\n\
	for (j = 0; j <= storage->no_states[slot]; j ++) {\n\
	  if (j != i) {\n\
	    hash_storage_copy_encoded_state (storage->states[slot][j],\n\
					     new_states[k]);\n\
	    k ++;\n\
	  }\n\
	}\n\
      }\n\
      free (storage->states[slot]);\n\
      storage->states[slot] = new_states;\n\
#if defined(ATTRIBUTE_REFS) && defined(ATTRIBUTE_PRED)\n\
      if (!hash_storage_id_is_null (id_pred)) {\n\
	hash_storage_update_refs (storage, id_pred, -1);\n\
      }\n\
#endif\n\
      break;\n\
    }\n\
  }\n\
  if (!found) {\n\
    fatal_error (\"storage_remove could not find state\");\n\
  }\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_get\n\
 *\n\
 *  get from storage the state with specified id\n\
 *\n\
 *****/\n\
state_t hash_storage_get_mem\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 worker_id_t       w,\n\
 heap_t            heap) {\n\
  state_t result;\n\
  bit_vector_t v;\n\
  \n\
#if   defined(STORAGE_HASH_COMPACTION)\n\
  fatal_error (\"storage_get impossible with hash-compaction\");\n\
  return NULL;\n\
#elif defined(STORAGE_HASH)\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_get_mem: could not find state\");\n\
  }\n\
  else {\n\
    result = state_unserialise_mem (v + ATTRIBUTES_CHAR_WIDTH, heap);\n\
  }\n\
#elif defined(STORAGE_DELTA)\n\
  result = hash_storage_reconstruct_delta_state (storage, id, w, heap);\n\
#endif\n\
  return result;\n\
}\n\
\n\
state_t hash_storage_get\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 worker_id_t       w) {\n\
  return hash_storage_get_mem (storage, id, w, SYSTEM_HEAP);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_set_in_unproc\n\
 *\n\
 *****/\n\
void hash_storage_set_in_unproc\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 bool_t            in_unproc) {\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
  bit_vector_t v;\n\
  vector bits;\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_set_in_unproc could not find state\");\n\
  }\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_IN_UNPROC_POS);\n\
  VECTOR_set_size1 (bits, in_unproc);\n\
  if (!in_unproc) {\n\
#ifdef ATTRIBUTE_REFS\n\
    hash_storage_update_refs (storage, id, -1);\n\
#elif defined (STATE_CACHING)\n\
    hash_storage_cache_state (storage, id);\n\
#endif\n\
  }\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_get_in_unproc\n\
 *\n\
 *****/\n\
bool_t hash_storage_get_in_unproc\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
  bool_t result;\n\
  bit_vector_t v;\n\
  vector bits;\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_get_in_unproc: could not find state\");\n\
  }\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_IN_UNPROC_POS);\n\
  VECTOR_get_size1 (bits, result);\n\
  result = result ? TRUE : FALSE;\n\
  return result;\n\
#else\n\
  return FALSE;\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_get_num\n\
 *\n\
 *****/\n\
state_num_t hash_storage_get_num\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
#ifdef ATTRIBUTE_NUM\n\
  state_num_t result;\n\
  bit_vector_t v;\n\
  vector bits;\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_get_num: could not find state\");\n\
  }\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_NUM_POS);\n\
  VECTOR_get_size32 (bits, result);\n\
  return result;\n\
#else\n\
  return 0;\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_update_refs\n\
 *\n\
 *  add update to the reference counter of state with identifier id\n\
 *\n\
 *****/\n\
void hash_storage_update_refs\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id,\n\
 int               update) {\n\
#ifdef ATTRIBUTE_REFS\n\
  if (hash_storage_id_is_null (id)) {\n\
    return;\n\
  }\n\
  bit_vector_t v;\n\
  vector bits;\n\
  int refs;\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_update_refs: could not find state\");\n\
  }\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_REFS_POS);\n\
  VECTOR_get (bits, refs, ATTRIBUTE_REFS_WIDTH);\n\
  refs += update;\n\
  move_to_attribute (bits, ATTRIBUTE_REFS_POS);\n\
  VECTOR_set (bits, refs, ATTRIBUTE_REFS_WIDTH);\n\
  if (refs < 0) {\n\
    fatal_error (\"hash_storage_update_refs: negative reference counter\");\n\
  }\n\
  \n\
#ifdef STATE_CACHING\n\
  if (refs == 0) {\n\
    hash_storage_cache_state (storage, id);\n\
  }\n\
#endif\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_set_is_red\n\
 *\n\
 *****/\n\
void hash_storage_set_is_red\n\
(hash_storage_t    storage,\n\
 hash_storage_id_t id) {\n\
#ifdef ATTRIBUTE_IS_RED\n\
  bit_vector_t v;\n\
  vector bits;\n\
  if ((v = hash_storage_get_vector (storage, id)) == NULL) {\n\
    fatal_error (\"hash_storage_set_is_red could not find state\");\n\
  }\n\
  bits.vector = v;\n\
  move_to_attribute (bits, ATTRIBUTE_IS_RED_POS);\n\
  VECTOR_set_size1 (bits, TRUE);\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_get_attr\n\
 *\n\
 *  get the attributes of state with identifier id\n\
 *\n\
 *****/\n\
void hash_storage_get_attr\n\
(hash_storage_t              storage,\n\
 state_t                     s,\n\
 worker_id_t                 w,\n\
 bool_t *                    found,\n\
 hash_storage_id_t *         id,\n\
 hash_storage_state_attr_t * attrs) {\n\
  unsigned int i, slot;\n\
  vector bits;\n\
\n\
  id->h = state_hash (s);\n\
  slot = id->h % storage->hash_size;\n\
  *found = FALSE;\n\
\n\
  /*\n\
   *  look for the state in the slot\n\
   */\n\
  for (i = 0; i < storage->no_states[slot]; i ++) {\n\
    storage->state_cmps[w] ++;\n\
    if (hash_storage_check_state (storage, storage->states[slot][i],\n\
				  s, id->h, w)) {\n\
      bits.vector = storage->states[slot][i];\n\
      VECTOR_start (bits);\n\
      VECTOR_get_size8 (bits, id->p);\n\
      *found = TRUE;\n\
      break;\n\
    }\n\
  }\n\
\n\
  if (*found) {\n\
#ifdef ATTRIBUTE_NUM\n\
    move_to_attribute (bits, ATTRIBUTE_NUM_POS);\n\
    VECTOR_get_size32 (bits, attrs->num);\n\
#endif\n\
#ifdef ATTRIBUTE_IN_UNPROC\n\
    move_to_attribute (bits, ATTRIBUTE_IN_UNPROC_POS);\n\
    VECTOR_get_size1 (bits, attrs->in_unproc);\n\
#endif\n\
#ifdef ATTRIBUTE_REFS\n\
    move_to_attribute (bits, ATTRIBUTE_REFS_POS);\n\
    VECTOR_get (bits, attrs->refs, ATTRIBUTE_REFS_WIDTH);\n\
#endif\n\
#ifdef ATTRIBUTE_PRED\n\
    move_to_attribute (bits, ATTRIBUTE_PRED_POS);\n\
    hash_storage_id_unserialise_bits (bits, attrs->pred);\n\
#endif\n\
#ifdef ATTRIBUTE_IS_RED\n\
    move_to_attribute (bits, ATTRIBUTE_IS_RED_POS);\n\
    VECTOR_get_size1 (bits, attrs->is_red);\n\
#endif\n\
  }\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_build_trace\n\
 *\n\
 *****/\n\
void hash_storage_build_trace\n\
(hash_storage_t    storage,\n\
 worker_id_t       w,\n\
 hash_storage_id_t id,\n\
 event_t **        trace,\n\
 unsigned int *    trace_len) {\n\
#ifndef ATTRIBUTE_PRED\n\
  fatal_error (\"hash_storage_build_trace: unable to reconstruct trace\");\n\
#else\n\
  fatal_error (\"hash_storage_build_trace: unimplemented feature\");\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: hash_storage_fold\n\
 *\n\
 *****/\n\
void hash_storage_fold\n\
(hash_storage_t           storage,\n\
 worker_id_t              w,\n\
 hash_storage_fold_func_t f,\n\
 void *                   data) {\n\
  hash_storage_id_t id;\n\
  uint32_t i, j;\n\
  state_t s;\n\
  heap_t heap = bounded_heap_new (\"fold heap\", 1048576);\n\
  vector bits;\n\
  for (i = 0; i < storage->hash_size; i ++) {\n\
    id.h = i;\n\
    for (j = 0; j < storage->no_states[i]; j ++) {\n\
      bits.vector = storage->states[i][j];\n\
      VECTOR_start (bits);\n\
      VECTOR_get_size8 (bits, id.p);\n\
      heap_reset (heap);\n\
      s = hash_storage_get_mem (storage, id, w, heap);\n\
      (*f) (s, id, data);\n\
    }\n\
  }\n\
  heap_free (heap);\n\
}\n\
\n\
void hash_storage_output_stats\n\
(hash_storage_t   storage,\n\
 FILE           * out) {\n\
  fprintf (out, \"<hashTableStatistics>\\n\");\n\
  fprintf (out, \"<stateComparisons>%llu</stateComparisons>\\n\",\n\
	   do_large_sum (storage->state_cmps, NO_WORKERS));\n\
#ifdef STORAGE_DELTA\n\
  fprintf (out, \"<eventsExecutedDelta>%llu</eventsExecutedDelta>\\n\",\n\
	   do_large_sum (storage->events_executed, NO_WORKERS));\n\
#endif\n\
  fprintf (out, \"</hashTableStatistics>\\n\");\n\
}\n\
\n\
\n\
\n\
void init_hash_storage () {\n\
  null_hash_storage_id.h = 0;\n\
  null_hash_storage_id.p = 0xff;\n\
  hash_storage_id_char_width = sizeof (hash_storage_id_t);\n\
}\n\
\n\
void free_hash_storage () {\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "heap.h", "w")
    f.write ("\
#ifndef LIB_HEAP\n\
#define LIB_HEAP\n\
\n\
#include \"common.h\"\n\
\n\
#define SYSTEM_HEAP      NULL\n\
#define BOUNDED_HEAP     0\n\
#define EVERGROWING_HEAP 1\n\
\n\
#define HEAP_TYPES 2\n\
\n\
\n\
void init_heap ();\n\
void free_heap ();\n\
\n\
typedef unsigned long long int mem_size_t;\n\
\n\
\n\
\n\
/*\n\
 *  bounded size heap without free operation\n\
 */\n\
typedef struct {\n\
  unsigned char type;\n\
  char * name;\n\
  void * ptr;\n\
  mem_size_t next;\n\
  mem_size_t size;\n\
} struct_bounded_heap_t;\n\
\n\
typedef struct_bounded_heap_t * bounded_heap_t;\n\
\n\
void * bounded_heap_new\n\
(char *     name,\n\
 mem_size_t size);\n\
\n\
\n\
\n\
/*\n\
 *  evergrowing heap\n\
 */\n\
typedef struct struct_evergrowing_heap_node_t {\n\
  void * ptr;\n\
  mem_size_t size;\n\
  struct struct_evergrowing_heap_node_t * next;\n\
} struct_evergrowing_heap_node_t;\n\
\n\
typedef struct_evergrowing_heap_node_t * evergrowing_heap_node_t;\n\
\n\
typedef struct {\n\
  unsigned char type;\n\
  char * name;\n\
  mem_size_t block_size;\n\
  mem_size_t next;\n\
  evergrowing_heap_node_t fst;\n\
  evergrowing_heap_node_t last;\n\
} struct_evergrowing_heap_t;\n\
\n\
typedef struct_evergrowing_heap_t * evergrowing_heap_t;\n\
\n\
void * evergrowing_heap_new\n\
(char *     name,\n\
 mem_size_t block_size);\n\
\n\
\n\
\n\
/*\n\
 *  generic heap operations\n\
 */\n\
typedef void * heap_t;\n\
\n\
void * mem_alloc\n\
(heap_t     heap,\n\
 mem_size_t size);\n\
\n\
void mem_free\n\
(heap_t heap,\n\
 void * ptr);\n\
\n\
void heap_reset\n\
(heap_t heap);\n\
\n\
void heap_free\n\
(heap_t heap);\n\
\n\
void * heap_get_position\n\
(heap_t heap);\n\
\n\
void heap_set_position\n\
(heap_t heap,\n\
 void * pos);\n\
\n\
mem_size_t heap_space_left\n\
(heap_t heap);\n\
\n\
bool_t heap_has_mem_free\n\
(heap_t heap);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "heap.c", "w")
    f.write ("\
#include \"heap.h\"\n\
\n\
/*\n\
 *  bounded size heap without free operation\n\
 */\n\
void * bounded_heap_new\n\
(char *     name,\n\
 mem_size_t size) {\n\
#ifdef USE_HELENA_HEAPS\n\
  bounded_heap_t result;\n\
  MALLOC (result, bounded_heap_t, sizeof (struct_bounded_heap_t));\n\
  MALLOC (result->name, char *, strlen (name) + 1);\n\
  MALLOC (result->ptr, void *, size);\n\
  result->type = BOUNDED_HEAP;\n\
  result->next = 0;\n\
  result->size = size;\n\
  strcpy (result->name, name);\n\
  return result;\n\
#else\n\
  return SYSTEM_HEAP;\n\
#endif\n\
}\n\
\n\
bounded_heap_t bounded_heap_free\n\
(bounded_heap_t heap) {\n\
  free (heap->name);\n\
  free (heap->ptr);\n\
  free (heap);\n\
}\n\
\n\
void * bounded_heap_reset\n\
(bounded_heap_t heap) {\n\
  heap->next = 0;\n\
}\n\
\n\
void * bounded_heap_mem_alloc\n\
(bounded_heap_t heap,\n\
 mem_size_t     size) {\n\
  void * result;\n\
\n\
  if (heap->next + size > heap->size) {\n\
    char msg[100];\n\
    sprintf (msg, \"bounded heap \\\"%s\\\" too small\", heap->name);\n\
    fatal_error (msg);\n\
  }\n\
  result = heap->ptr + heap->next;\n\
  heap->next += size;\n\
  return result;\n\
}\n\
\n\
void * bounded_heap_mem_free\n\
(bounded_heap_t heap,\n\
 void *         ptr) {\n\
}\n\
\n\
void * bounded_heap_get_position\n\
(bounded_heap_t heap) {\n\
  return heap->ptr + heap->next;\n\
}\n\
\n\
void bounded_heap_set_position\n\
(bounded_heap_t heap,\n\
 void *         pos) {\n\
  heap->next = pos - heap->ptr;\n\
}\n\
\n\
mem_size_t bounded_heap_space_left\n\
(bounded_heap_t heap) {\n\
  return heap->size - heap->next;\n\
}\n\
\n\
bool_t bounded_heap_has_mem_free\n\
(bounded_heap_t heap) {\n\
  return FALSE;\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  evergrowing heap\n\
 */\n\
void * evergrowing_heap_new\n\
(char *     name,\n\
 mem_size_t block_size) {\n\
#ifdef USE_HELENA_HEAPS\n\
  evergrowing_heap_t result;\n\
  MALLOC (result, evergrowing_heap_t, sizeof (struct_evergrowing_heap_t));\n\
  MALLOC (result->name, char *, strlen (name) + 1);\n\
  result->type = EVERGROWING_HEAP;\n\
  strcpy (result->name, name);\n\
  result->block_size = block_size;\n\
  result->next = 0;\n\
  result->last = result->fst = NULL;\n\
  return result;\n\
#else\n\
  return SYSTEM_HEAP;\n\
#endif\n\
}\n\
\n\
evergrowing_heap_t evergrowing_heap_free\n\
(evergrowing_heap_t heap) {\n\
  evergrowing_heap_node_t tmp = heap->fst, next;\n\
  while (tmp) {\n\
    next = tmp->next;\n\
    free (tmp->ptr);\n\
    free (tmp);\n\
    tmp = next;\n\
  }\n\
  free (heap->name);  \n\
  free (heap);\n\
}\n\
\n\
void * evergrowing_heap_reset\n\
(evergrowing_heap_t heap) {\n\
  evergrowing_heap_node_t tmp = heap->fst, next;\n\
  while (tmp) {\n\
    next = tmp->next;\n\
    free (tmp->ptr);\n\
    free (tmp);\n\
    tmp = next;\n\
  }\n\
  heap->next = 0;\n\
  heap->last = heap->fst = NULL;\n\
}\n\
\n\
void * evergrowing_heap_mem_alloc\n\
(evergrowing_heap_t heap,\n\
 mem_size_t         size) {\n\
  void * result;\n\
  evergrowing_heap_node_t new_node;\n\
  \n\
  if ((NULL == heap->fst) || (size + heap->next >= heap->last->size)) {\n\
    heap->next = 0;\n\
    MALLOC (new_node, evergrowing_heap_node_t,\n\
	    sizeof (struct_evergrowing_heap_node_t));\n\
    new_node->size = (heap->block_size >= size) ? heap->block_size : size;\n\
    new_node->next = NULL;\n\
    MALLOC (new_node->ptr, char *, new_node->size);\n\
    if (NULL == heap->fst) {\n\
      heap->fst = heap->last = new_node;\n\
    } else {\n\
      heap->last->next = new_node;\n\
      heap->last = new_node;\n\
    }\n\
  }\n\
  result = heap->last->ptr + heap->next;\n\
  heap->next += size;\n\
  return result;\n\
}\n\
\n\
void * evergrowing_heap_mem_free\n\
(evergrowing_heap_t heap,\n\
 void *             ptr) {\n\
}\n\
\n\
void * evergrowing_heap_get_position\n\
(evergrowing_heap_t heap) {\n\
  fatal_error (\"evergrowing_heap_get_position: impossible operation\");\n\
  return NULL;\n\
}\n\
\n\
void evergrowing_heap_set_position\n\
(evergrowing_heap_t heap,\n\
 void *             pos) {\n\
  fatal_error (\"evergrowing_heap_set_position: impossible operation\");\n\
}\n\
\n\
mem_size_t evergrowing_heap_space_left\n\
(evergrowing_heap_t heap) {\n\
  fatal_error (\"evergrowing_heap_space_left: impossible operation\");\n\
}\n\
\n\
bool_t evergrowing_heap_has_mem_free\n\
(evergrowing_heap_t heap) {\n\
  return FALSE;\n\
}\n\
\n\
\n\
\n\
\n\
\n\
/*\n\
 *  generic heap operations\n\
 */\n\
typedef void (* heap_free_func_t) (void *);\n\
heap_free_func_t heap_free_funcs[HEAP_TYPES];\n\
\n\
void heap_free\n\
(heap_t heap) {\n\
  if (heap) {\n\
    heap_free_funcs[((char *) heap)[0]] (heap);\n\
  }\n\
}\n\
\n\
typedef void (* heap_reset_func_t) (void *);\n\
heap_reset_func_t heap_reset_funcs[HEAP_TYPES];\n\
\n\
void heap_reset\n\
(heap_t heap) {\n\
  if (heap) {\n\
    heap_reset_funcs[((char *) heap)[0]] (heap);\n\
  }\n\
}\n\
\n\
typedef void * (* heap_mem_alloc_func_t) (void *, mem_size_t);\n\
heap_mem_alloc_func_t heap_mem_alloc_funcs[HEAP_TYPES];\n\
\n\
void * mem_alloc\n\
(heap_t     heap,\n\
 mem_size_t size) {\n\
  if (NULL == heap) {\n\
    return malloc (size);\n\
  }\n\
  else {\n\
    return heap_mem_alloc_funcs[((char *) heap)[0]] (heap, size);\n\
  }\n\
}\n\
\n\
typedef void (* heap_mem_free_func_t) (void *, void *);\n\
heap_mem_free_func_t heap_mem_free_funcs[HEAP_TYPES];\n\
\n\
void mem_free\n\
(heap_t heap,\n\
 void * ptr) {\n\
  if (NULL == heap) {\n\
    free (ptr);\n\
  }\n\
  else {\n\
    heap_mem_free_funcs[((char *) heap)[0]] (heap, ptr);\n\
  }\n\
}\n\
\n\
typedef void * (* heap_get_position_func_t) (void *);\n\
heap_get_position_func_t heap_get_position_funcs[HEAP_TYPES];\n\
\n\
void * heap_get_position\n\
(heap_t heap) {\n\
  if (heap) {\n\
    return heap_get_position_funcs[((char *) heap)[0]] (heap);\n\
  } else {\n\
    return NULL;\n\
  }\n\
}\n\
\n\
typedef void (* heap_set_position_func_t) (void *, void *);\n\
heap_set_position_func_t heap_set_position_funcs[HEAP_TYPES];\n\
\n\
void heap_set_position\n\
(heap_t heap,\n\
 void * pos) {\n\
  if (heap) {\n\
    heap_set_position_funcs[((char *) heap)[0]] (heap, pos);\n\
  }\n\
}\n\
\n\
typedef mem_size_t (* heap_space_left_func_t) (void *);\n\
heap_space_left_func_t heap_space_left_funcs[HEAP_TYPES];\n\
\n\
mem_size_t heap_space_left\n\
(heap_t heap) {\n\
  if (heap) {\n\
    return heap_space_left_funcs[((char *) heap)[0]](heap);\n\
  } else {\n\
    return INT_MAX;\n\
  }\n\
}\n\
\n\
typedef bool_t (* heap_has_mem_free_func_t) (void *);\n\
heap_has_mem_free_func_t heap_has_mem_free_funcs[HEAP_TYPES];\n\
\n\
bool_t heap_has_mem_free\n\
(heap_t heap) {\n\
  if (heap) {\n\
    return heap_has_mem_free_funcs[((char *) heap)[0]](heap);\n\
  } else {\n\
    return TRUE;\n\
  }\n\
}\n\
\n\
\n\
void init_heap () {\n\
  unsigned char t;\n\
\n\
  t = BOUNDED_HEAP;\n\
  heap_free_funcs[t] =\n\
    (heap_free_func_t) bounded_heap_free;\n\
  heap_reset_funcs[t] =\n\
    (heap_reset_func_t) bounded_heap_reset;\n\
  heap_mem_alloc_funcs[t] =\n\
    (heap_mem_alloc_func_t) bounded_heap_mem_alloc;\n\
  heap_mem_free_funcs[t] =\n\
    (heap_mem_free_func_t) bounded_heap_mem_free;\n\
  heap_get_position_funcs[t] =\n\
    (heap_get_position_func_t) bounded_heap_get_position;\n\
  heap_set_position_funcs[t] =\n\
    (heap_set_position_func_t) bounded_heap_set_position;\n\
  heap_space_left_funcs[t] =\n\
    (heap_space_left_func_t) bounded_heap_space_left;\n\
  heap_has_mem_free_funcs[t] =\n\
    (heap_has_mem_free_func_t) bounded_heap_has_mem_free;\n\
\n\
  t = EVERGROWING_HEAP;\n\
  heap_free_funcs[t] =\n\
    (heap_free_func_t) evergrowing_heap_free;\n\
  heap_reset_funcs[t] =\n\
    (heap_reset_func_t) evergrowing_heap_reset;\n\
  heap_mem_alloc_funcs[t] =\n\
    (heap_mem_alloc_func_t) evergrowing_heap_mem_alloc;\n\
  heap_mem_free_funcs[t] =\n\
    (heap_mem_free_func_t) evergrowing_heap_mem_free;\n\
  heap_get_position_funcs[t] =\n\
    (heap_get_position_func_t) evergrowing_heap_get_position;\n\
  heap_set_position_funcs[t] =\n\
    (heap_set_position_func_t) evergrowing_heap_set_position;\n\
  heap_space_left_funcs[t] =\n\
    (heap_space_left_func_t) evergrowing_heap_space_left;\n\
  heap_has_mem_free_funcs[t] =\n\
    (heap_has_mem_free_func_t) evergrowing_heap_has_mem_free;\n\
}\n\
\n\
void free_heap () {\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "graph.h", "w")
    f.write ("\
#ifndef LIB_GRAPH\n\
#define LIB_GRAPH\n\
\n\
#include \"heap.h\"\n\
\n\
#define GT_NODE 1\n\
#define GT_EDGE 2\n\
\n\
typedef uint8_t edge_num_t;\n\
typedef uint32_t node_t;\n\
\n\
typedef struct {\n\
  edge_num_t num;\n\
  node_t     dest;\n\
} edge_data_t;\n\
\n\
typedef struct {\n\
  uint8_t       no_succs;\n\
  edge_data_t * out;\n\
} node_data_t;\n\
\n\
typedef struct {\n\
  unsigned int  no_nodes;\n\
  unsigned int  no_edges;\n\
  node_data_t * data;\n\
  node_t        root;\n\
  heap_t        heap;\n\
} struct_graph_t;\n\
\n\
typedef struct_graph_t * graph_t;\n\
\n\
void graph_make_report\n\
(char * in_file,\n\
 char * out_file,\n\
 char * dot_file);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "graph.c", "w")
    f.write ("\
#include \"graph.h\"\n\
\n\
#ifdef MODEL_HAS_GRAPH_ROUTINES\n\
#include \"model.h\"\n\
#include \"model_graph.h\"\n\
#else\n\
typedef int model_graph_data_t;\n\
void model_graph_data_init (model_graph_data_t * mdata, uint32_t states) {}\n\
void model_graph_data_free (model_graph_data_t * mdata) {}\n\
void model_graph_data_output (model_graph_data_t mdata, FILE * out) {}\n\
void model_graph_dfs_start (model_graph_data_t mdata) {}\n\
void model_graph_dfs_stop (model_graph_data_t mdata) {}\n\
void model_graph_dfs_push (model_graph_data_t mdata, edge_num_t num,\n\
			   bool_t new_succ) {}\n\
void model_graph_dfs_pop (model_graph_data_t mdata) {}\n\
void model_graph_scc_dfs_start (model_graph_data_t mdata) {}\n\
void model_graph_scc_dfs_stop (model_graph_data_t mdata) {}\n\
void model_graph_scc_dfs_push (model_graph_data_t mdata, edge_num_t num) {}\n\
void model_graph_scc_dfs_pop (model_graph_data_t mdata) {}\n\
void model_graph_scc_enter (model_graph_data_t mdata, bool_t terminal) {}\n\
void model_graph_scc_exit (model_graph_data_t mdata) {}\n\
#endif\n\
\n\
void graph_free\n\
(graph_t graph) {\n\
  unsigned int i;\n\
  for (i = 0; i < graph->no_nodes; i ++) {\n\
    mem_free (graph->heap, graph->data[i].out);\n\
  }\n\
  mem_free (graph->heap, graph->data);\n\
  mem_free (graph->heap, graph);\n\
}\n\
\n\
graph_t graph_load_main\n\
(char *       in_file,\n\
 heap_t       heap,\n\
 unsigned int max) {\n\
  unsigned int i;\n\
  char t;\n\
  uint8_t no_succs;\n\
  node_t n, o;\n\
  FILE * f = fopen (in_file, \"r\");\n\
  graph_t result = NULL;\n\
  edge_data_t * out;\n\
  edge_num_t num;\n\
\n\
  if (f) {\n\
    result = mem_alloc (heap, sizeof (struct_graph_t));\n\
    result->heap = heap;\n\
    result->no_nodes = 0;\n\
    result->no_edges = 0;\n\
    result->root = 0;\n\
    result->data = mem_alloc (heap, sizeof (node_data_t) * max);\n\
    for (i = 0; i < max; i ++) {\n\
      result->data[i].no_succs = 0;\n\
      result->data[i].out = NULL;\n\
    }\n\
    while (fread (&t, 1, 1, f)) {\n\
      switch (t) {\n\
      case GT_NODE: {\n\
	fread (&n, sizeof (node_t), 1, f);\n\
	if (n >= max) {\n\
	  graph_free (result);\n\
	  fclose (f);\n\
	  return NULL;\n\
	}\n\
	fread (&no_succs, sizeof (uint8_t), 1, f);\n\
	if (!no_succs) {\n\
	  out = NULL;\n\
	} else {\n\
	  out = mem_alloc (heap, sizeof (node_t) * no_succs);\n\
	  for (i = 0; i < no_succs; i ++) {\n\
	    fread (&(out[i].num),  sizeof (edge_num_t), 1, f);\n\
	    fread (&(out[i].dest), sizeof (node_t), 1, f);\n\
	  }\n\
	}\n\
	result->data[n].out = out;\n\
	result->data[n].no_succs = no_succs;\n\
	result->no_nodes ++;\n\
	result->no_edges += no_succs;\n\
	break;\n\
      }\n\
      case GT_EDGE: {\n\
	fread (&n, sizeof (node_t), 1, f);\n\
        if (n >= max) {\n\
          graph_free (result);\n\
          fclose (f);\n\
          return NULL;\n\
        }\n\
	fread (&num, sizeof (edge_num_t), 1, f);\n\
	fread (&o, sizeof (node_t), 1, f);\n\
	out = mem_alloc (heap,\n\
			 sizeof (edge_data_t) * (result->data[n].no_succs + 1));\n\
	for (i = 0; i < result->data[n].no_succs; i ++) {\n\
          out[i] = result->data[n].out[i];\n\
        }\n\
	out[i].dest = o;\n\
	out[i].num = num;\n\
	if (result->data[n].out) {\n\
	  mem_free (heap, result->data[n].out);\n\
	}\n\
	result->data[n].out = out;\n\
	result->data[n].no_succs ++;\n\
	result->no_edges ++;\n\
	break;\n\
      }\n\
      default: {\n\
	printf (\"error: graph_load read an incorrect GT: %d\\n\", t);\n\
      }\n\
      }\n\
    }\n\
    fclose (f);\n\
  }\n\
  return result;\n\
}\n\
\n\
graph_t graph_load\n\
(char *  in_file,\n\
 heap_t  heap) {\n\
  unsigned int max = 4;\n\
  graph_t result = NULL;\n\
  while (NULL == result) {\n\
    result = graph_load_main (in_file, heap, max);\n\
    max = max * 2;\n\
  }\n\
  return result;\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  DFS exploration data\n\
 */\n\
typedef struct {\n\
  uint32_t scc_count;\n\
  uint32_t scc_trivial;\n\
  uint32_t scc_terminal;\n\
  uint32_t scc_largest;\n\
  uint32_t front_edges;\n\
  uint32_t cross_edges;\n\
  uint32_t back_edges;\n\
  uint32_t max_stack;\n\
  uint32_t shortest_cycle;\n\
  uint32_t samples;\n\
  uint32_t * stack_samples_id;\n\
  uint32_t * stack_samples_size;\n\
} dfs_data_t;\n\
\n\
/*\n\
 *  degree data\n\
 */\n\
typedef struct {\n\
  float avg;\n\
  uint32_t max_in;\n\
  uint32_t max_out;\n\
  uint32_t degs;\n\
  uint32_t * nodes_per_in;\n\
  uint32_t * nodes_per_out;\n\
} degree_data_t;\n\
\n\
/*\n\
 *  BFS exploration data\n\
 */\n\
typedef struct {\n\
  uint32_t   levels;\n\
  uint32_t   max_level;\n\
  uint32_t   ble;\n\
  uint32_t   max_ble;\n\
  float      avg_ble;\n\
  uint32_t * states;\n\
  uint32_t * edges;\n\
  uint32_t * ble_lengths;\n\
} bfs_data_t;\n\
\n\
\n\
\n\
/*\n\
 *  Function: graph_degree\n\
 */\n\
void graph_degree \n\
(graph_t            graph,\n\
 degree_data_t *    data,\n\
 model_graph_data_t mdata) {\n\
  node_data_t * N = graph->data;\n\
  node_t * in_deg;\n\
  int i, j;\n\
\n\
  in_deg = mem_alloc (SYSTEM_HEAP, sizeof (node_t) * graph->no_nodes);\n\
  for (i = 0; i < graph->no_nodes; i ++) {\n\
    in_deg[i] = 0;\n\
  }\n\
\n\
  data->avg = (float) graph->no_edges / (float) graph->no_nodes;\n\
  data->max_in = 0;\n\
  data->max_out = N[graph->root].no_succs;\n\
  for (i = 0; i < graph->no_nodes; i ++) {\n\
    if (data->max_out < N[i].no_succs) {\n\
      data->max_out = N[i].no_succs;\n\
    }\n\
    for (j = 0; j < N[i].no_succs; j ++) {\n\
      if ((++ in_deg[N[i].out[j].dest]) > data->max_in) {\n\
	data->max_in = in_deg[N[i].out[j].dest];\n\
      }\n\
    }\n\
  }\n\
  data->degs = data->max_in;\n\
  if (data->max_out > data->degs) {\n\
    data->degs = data->max_out;\n\
  }\n\
  data->nodes_per_in = mem_alloc (SYSTEM_HEAP,\n\
				  sizeof(uint32_t) * (data->degs + 1));\n\
  data->nodes_per_out = mem_alloc (SYSTEM_HEAP, \n\
				   sizeof(uint32_t) * (data->degs + 1));\n\
  for (i = 0; i <= data->degs; i ++) {\n\
    data->nodes_per_in[i] = 0;\n\
    data->nodes_per_out[i] = 0;\n\
  }\n\
  for (i = 0; i < graph->no_nodes; i ++) {\n\
    data->nodes_per_in[in_deg[i]] ++;\n\
    data->nodes_per_out[N[i].no_succs] ++;\n\
  }\n\
\n\
  mem_free (SYSTEM_HEAP, in_deg);\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  Function: graph_bfs\n\
 */\n\
void graph_bfs\n\
(graph_t            graph,\n\
 bfs_data_t *       data,\n\
 model_graph_data_t mdata) {\n\
  uint32_t fst = 0;\n\
  uint32_t last = 0;\n\
  uint32_t old = 1;\n\
  uint32_t current = 1;\n\
  uint32_t next = 0;\n\
  uint32_t edges = 0;\n\
  uint32_t lg;\n\
  uint32_t * depth;\n\
  large_unsigned_t ble_length_sum = 0;\n\
  int i;\n\
  node_t * queue;\n\
  bool_t * visited;\n\
  node_data_t * N = graph->data;\n\
  node_t now, succ;\n\
\n\
  data->levels = 0;\n\
  data->max_level = 1;\n\
  data->ble = 0;\n\
  data->max_ble = 0;\n\
  data->avg_ble = 0.0;\n\
  data->states = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * 65536);\n\
  data->edges = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * 65536);\n\
  data->ble_lengths = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * 65536);\n\
  for (i = 0; i < 65536; i ++) {\n\
    data->ble_lengths[i] = 0;\n\
  }\n\
\n\
  queue = mem_alloc (SYSTEM_HEAP, sizeof (node_t) * graph->no_nodes);\n\
  depth = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * graph->no_nodes);\n\
  visited = mem_alloc (SYSTEM_HEAP, sizeof (bool_t) * graph->no_nodes);\n\
\n\
  for (i = 0; i < graph->no_nodes; i ++) {\n\
    visited[i] = 0;\n\
  }\n\
  queue[0] = graph->root;\n\
  depth[graph->root] = 0;\n\
  visited[graph->root] = TRUE;\n\
\n\
  while (fst <= last) {\n\
    now = queue[fst];\n\
    for (i = 0; i < N[now].no_succs; i ++) {\n\
      edges ++;\n\
      succ = N[now].out[i].dest;\n\
      if (visited[succ]) {\n\
	if (depth[succ] != data->levels + 1) {\n\
	  data->ble ++;\n\
	  lg = data->levels - depth[succ];\n\
	  ble_length_sum += lg;\n\
	  data->ble_lengths[lg] ++;\n\
	  if (lg > data->max_ble) { data->max_ble = lg; }\n\
	}	\n\
      } else {\n\
	visited[succ] = TRUE;\n\
	depth[succ] = data->levels + 1;\n\
	queue[++ last] = succ;\n\
	next ++;\n\
      }\n\
    }\n\
    fst ++;\n\
    current --;\n\
    if (0 == current) {  /*  BFS level terminated  */\n\
      if (next > data->max_level) { data->max_level = next; }\n\
      data->states[data->levels] = old;\n\
      data->edges[data->levels] = edges;\n\
      data->levels ++;\n\
      old = next;\n\
      current = next;\n\
      next = 0;\n\
      edges = 0;\n\
    }\n\
  }\n\
  data->avg_ble = (float) ble_length_sum / (float) data->ble;\n\
\n\
  mem_free (SYSTEM_HEAP, depth);\n\
  mem_free (SYSTEM_HEAP, queue);\n\
  mem_free (SYSTEM_HEAP, visited);\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  Function: graph_dfs\n\
 */\n\
void graph_dfs\n\
(graph_t            graph,\n\
 dfs_data_t *       data,\n\
 model_graph_data_t mdata) {\n\
  uint8_t * scc;\n\
  uint8_t * visited;\n\
  uint8_t * next;\n\
  uint32_t * depth;\n\
  uint32_t * index;\n\
  uint32_t * low_link;\n\
  bool_t * scc_terminal;\n\
  uint32_t idx = 0;\n\
  uint32_t scc_size = 1;\n\
  int top = 0, scc_top = 0, i;\n\
  node_data_t * N = graph->data;\n\
  node_t * stack;\n\
  node_t * scc_stack;\n\
  node_t now, succ;\n\
  bool_t loop;\n\
  unsigned int sampling_period = graph->no_nodes / 1000;\n\
  \n\
  if (sampling_period == 0) {\n\
    sampling_period = 1;\n\
  }\n\
\n\
  data->scc_count = 0;\n\
  data->scc_trivial = 0;\n\
  data->scc_terminal = 0;\n\
  data->scc_largest = 0;\n\
  data->shortest_cycle = 0;\n\
  data->front_edges = 0;\n\
  data->cross_edges = 0;\n\
  data->back_edges = 0;\n\
  data->max_stack = 0;\n\
  data->samples = 0;\n\
  data->stack_samples_id =\n\
    mem_alloc (SYSTEM_HEAP,\n\
	       sizeof (uint32_t) * graph->no_nodes / sampling_period);\n\
  data->stack_samples_size =\n\
    mem_alloc (SYSTEM_HEAP,\n\
	       sizeof (uint32_t) * graph->no_nodes / sampling_period);\n\
\n\
  scc_terminal = mem_alloc (SYSTEM_HEAP, sizeof (bool_t) * graph->no_nodes);\n\
  visited = mem_alloc (SYSTEM_HEAP, sizeof (uint8_t) * graph->no_nodes);\n\
  next = mem_alloc (SYSTEM_HEAP, sizeof (uint8_t) * graph->no_nodes);\n\
  scc = mem_alloc (SYSTEM_HEAP, sizeof (uint8_t) * graph->no_nodes);\n\
  stack = mem_alloc (SYSTEM_HEAP, sizeof (node_t) * graph->no_nodes);\n\
  scc_stack = mem_alloc (SYSTEM_HEAP, sizeof (node_t) * graph->no_nodes);\n\
  depth = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * graph->no_nodes);\n\
  index = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * graph->no_nodes);\n\
  low_link = mem_alloc (SYSTEM_HEAP, sizeof (uint32_t) * graph->no_nodes);\n\
\n\
  data->front_edges = 0;\n\
  data->cross_edges = 0;\n\
  data->back_edges = 0;\n\
  data->max_stack = 0;\n\
\n\
  loop = TRUE;\n\
  for (top = 0; top < graph->no_nodes; top ++) {\n\
    visited[top] = 0;\n\
  }\n\
  top = 0;\n\
  scc_top = 0;\n\
  stack[0] = graph->root;\n\
  next[0] = 0;\n\
  scc_stack[0] = graph->root;\n\
  scc_terminal[0] = TRUE;\n\
  scc[graph->root] = TRUE;\n\
  depth[graph->root] = 0;\n\
  visited[graph->root] = 1;\n\
  index[graph->root] = idx;\n\
  low_link[graph->root] = idx;\n\
  idx ++;\n\
\n\
  /*\n\
   *  main DFS loop\n\
   */\n\
  model_graph_dfs_start (mdata);\n\
  while (loop) {\n\
    now = stack[top];\n\
    if (next[top] >= N[now].no_succs) {  /*  backtrack  */\n\
      visited[now] ++;\n\
      if (index[now] == low_link[now]) {  /*  pop the root of an SCC  */\n\
	scc_size = 0;\n\
	do {\n\
	  now = scc_stack[scc_top];\n\
	  scc[now] = FALSE;\n\
	  scc_top --;\n\
	  scc_size ++;\n\
	} while (scc_top >= 0 && now != stack[top]);\n\
	if (scc_terminal[now]) {\n\
	  data->scc_terminal ++;\n\
	  for (i = top - 1; i >= 0 && scc_terminal[stack[i]]; i --) {\n\
	    scc_terminal[stack[i]] = FALSE;\n\
	  }\n\
	}\n\
	data->scc_count ++;\n\
	if (scc_size == 1) { data->scc_trivial ++; }\n\
	if (scc_size > data->scc_largest) { data->scc_largest = scc_size; }\n\
      }\n\
      if (0 == top) {\n\
	loop = FALSE;\n\
      } else {\n\
	model_graph_dfs_pop (mdata);\n\
	top --;\n\
	if (low_link[stack[top]] > low_link[now]) {\n\
	  low_link[stack[top]] = low_link[now];\n\
	}\n\
      }\n\
    } else {  /*  visit a successor  */\n\
      succ = N[now].out[next[top]].dest;\n\
      next[top] ++;\n\
      model_graph_dfs_push (mdata, N[now].out[next[top] - 1].num,\n\
			    (0 == visited[succ]) ? TRUE : FALSE);\n\
      if (0 == visited[succ]) {  /*  successor is new  */\n\
	top ++;\n\
	scc_top ++;\n\
	next[top] = 0;\n\
	stack[top] = succ;\n\
	scc_stack[scc_top] = succ;\n\
	scc_terminal[succ] = TRUE;\n\
	scc[succ] = TRUE;\n\
	depth[succ] = top;\n\
	visited[succ] ++;\n\
	index[succ] = idx;\n\
	low_link[succ] = idx;\n\
	idx ++;\n\
	if (top + 1 > data->max_stack) { data->max_stack = top + 1; }\n\
	if (0 == idx % sampling_period) {\n\
	  data->stack_samples_id[data->samples] = idx;\n\
	  data->stack_samples_size[data->samples] = top + 1;\n\
	  data->samples ++;\n\
	}\n\
	data->front_edges ++;\n\
      } else {  /*  successor is not new  */\n\
	if (scc[succ]) {\n\
	  if (low_link[now] > index[succ]) {\n\
	    low_link[now] = index[succ];\n\
	  }\n\
	} else {\n\
	  for (i = top; i >= 0 && scc_terminal[stack[i]]; i --) {\n\
	    scc_terminal[stack[i]] = FALSE;\n\
	  }	  \n\
	}\n\
	if (1 == visited[succ]) {  /*  successor is on stack  */\n\
	  data->back_edges ++;\n\
	  if (data->shortest_cycle == 0 ||\n\
	      top - depth[succ] + 1 < data->shortest_cycle) {\n\
	    data->shortest_cycle = top - depth[succ] + 1;\n\
	  }\n\
	} else {  /*  successor has left stack  */\n\
	  data->cross_edges ++;\n\
	}\n\
      }\n\
    }\n\
  }\n\
  model_graph_dfs_stop (mdata);\n\
\n\
  /*\n\
   *  main SCC-DFS loop\n\
   */\n\
  loop = TRUE;\n\
  for (top = 0; top < graph->no_nodes; top ++) {\n\
    visited[top] = 0;\n\
  }\n\
  top = 0;\n\
  stack[0] = graph->root;\n\
  next[0] = 0;\n\
  visited[graph->root] = 1;\n\
  model_graph_scc_dfs_start (mdata);\n\
  while (loop) {\n\
    now = stack[top];\n\
    if (index[now] == low_link[now] && next[top] == 0) {\n\
      model_graph_scc_enter (mdata, scc_terminal[now]);\n\
    }\n\
    if (next[top] >= N[now].no_succs) {  /*  backtrack  */\n\
      if (index[now] == low_link[now]) {  /*  pop the root of an SCC  */\n\
	model_graph_scc_exit (mdata);\n\
      }\n\
      if (0 == top) {\n\
	loop = FALSE;\n\
      } else {\n\
	model_graph_scc_dfs_pop (mdata);\n\
	top --;\n\
      }\n\
    } else {  /*  visit a successor  */\n\
      succ = N[now].out[next[top]].dest;\n\
      next[top] ++;\n\
      model_graph_scc_dfs_push (mdata, N[now].out[next[top] - 1].num);\n\
      if (visited[succ]) {  /*  successor is not new  */\n\
	model_graph_scc_dfs_pop (mdata);\n\
      } else {\n\
	top ++;\n\
	next[top] = 0;\n\
	stack[top] = succ;\n\
	visited[succ] = 1;\n\
      }\n\
    }\n\
  }\n\
  model_graph_scc_dfs_stop (mdata);\n\
\n\
  mem_free (SYSTEM_HEAP, depth);\n\
  mem_free (SYSTEM_HEAP, next);\n\
  mem_free (SYSTEM_HEAP, visited);\n\
  mem_free (SYSTEM_HEAP, stack);\n\
  mem_free (SYSTEM_HEAP, index);\n\
  mem_free (SYSTEM_HEAP, low_link);\n\
  mem_free (SYSTEM_HEAP, scc);\n\
  mem_free (SYSTEM_HEAP, scc_stack);\n\
  mem_free (SYSTEM_HEAP, scc_terminal);\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  Function: graph_make_statistics\n\
 */\n\
void graph_make_statistics\n\
(graph_t graph,\n\
 char *  out_file) {\n\
\n\
  FILE * f = fopen (out_file, \"w\");\n\
  bfs_data_t B;\n\
  dfs_data_t D;\n\
  degree_data_t E;\n\
  int i;\n\
  model_graph_data_t mdata;\n\
\n\
  model_graph_data_init (&mdata, graph->no_nodes);\n\
\n\
  fprintf (f, \"<?xml version=\\\"1.0\\\" encoding=\\\"ISO-8859-1\\\"?>\\n\");\n\
  fprintf (f, \"<state-space-info>\\n\\n\");\n\
\n\
  fprintf (f, \"<model>%s</model>\\n\", model_name ());\n\
#ifdef LANGUAGE\n\
  fprintf (f, \"<language>%s</language>\\n\", LANGUAGE);\n\
#endif\n\
#ifdef DATE\n\
  fprintf (f, \"<date>%s</date>\\n\", DATE);\n\
#endif\n\
#ifdef FILE_PATH\n\
  fprintf (f, \"<filePath>%s</filePath>\\n\", FILE_PATH);\n\
#endif\n\
  model_xml_parameters (f);\n\
\n\
  fprintf (f, \"<states>%d</states>\\n\", graph->no_nodes);\n\
  fprintf (f, \"<edges>%d</edges>\\n\\n\", graph->no_edges);\n\
\n\
  /*\n\
   *  BFS statistics\n\
   */\n\
  graph_bfs (graph, &B, mdata);\n\
  fprintf (f, \"<bfs-info>\\n\");\n\
  fprintf (f, \"<levels>%d</levels>\\n\", B.levels);\n\
  fprintf (f, \"<max-level>%d</max-level>\\n\", B.max_level);\n\
  fprintf (f, \"<back-level-edges>%d</back-level-edges>\\n\", B.ble);\n\
  fprintf (f, \"<max-back-level-edge>%d</max-back-level-edge>\\n\", B.max_ble);\n\
  fprintf (f, \"<avg-back-level-edge>%.2f</avg-back-level-edge>\\n\", B.avg_ble);\n\
  fprintf (f, \"<bfs-levels>\\n\");\n\
  for (i = 0; i < B.levels; i ++) {\n\
    fprintf (f, \"<level id=\\\"%d\\\">\", i);\n\
    fprintf (f, \"<states>%d</states>\", B.states[i]);\n\
    fprintf (f, \"<edges>%d</edges>\", B.edges[i]);\n\
    fprintf (f, \"</level>\\n\");\n\
  }\n\
  fprintf (f, \"</bfs-levels>\\n\");\n\
  fprintf (f, \"<back-level-lengths>\\n\");\n\
  if (B.ble > 0) {\n\
    for (i = 0; i <= B.max_ble; i ++) {\n\
      fprintf (f, \"<length id=\\\"%d\\\">%.4f</length>\\n\", i,\n\
	       100.0 * (float) B.ble_lengths[i] / (float) B.ble);\n\
    }\n\
  }\n\
  fprintf (f, \"</back-level-lengths>\\n\");\n\
  fprintf (f, \"</bfs-info>\\n\\n\");\n\
  mem_free (SYSTEM_HEAP, B.states);\n\
  mem_free (SYSTEM_HEAP, B.edges);\n\
  mem_free (SYSTEM_HEAP, B.ble_lengths);\n\
\n\
  /*\n\
   *  degress statistics\n\
   */\n\
  graph_degree (graph, &E, mdata);\n\
  fprintf (f, \"<degrees>\\n\");\n\
  fprintf (f, \"<avg>%.4f</avg>\\n\", E.avg);\n\
  fprintf (f, \"<max-in>%d</max-in>\\n\", E.max_in);\n\
  fprintf (f, \"<max-out>%d</max-out>\\n\", E.max_out);\n\
  for (i = 0; i <= E.degs; i ++) {\n\
    fprintf (f, \"<degree id=\\\"%d\\\"><in>%d</in><out>%d</out></degree>\\n\",\n\
	     i, E.nodes_per_in[i], E.nodes_per_out[i]);\n\
  }\n\
  fprintf (f, \"</degrees>\\n\\n\");\n\
  mem_free (SYSTEM_HEAP, E.nodes_per_in);\n\
  mem_free (SYSTEM_HEAP, E.nodes_per_out);\n\
\n\
  /*\n\
   *  SCC statistics\n\
   */\n\
  graph_dfs (graph, &D, mdata);\n\
  fprintf (f, \"<scc-info>\\n\");\n\
  fprintf (f, \"<count>%d</count>\\n\", D.scc_count);\n\
  fprintf (f, \"<trivial>%d</trivial>\\n\", D.scc_trivial);\n\
  fprintf (f, \"<terminal>%d</terminal>\\n\", D.scc_terminal);\n\
  fprintf (f, \"<largest>%d</largest>\\n\", D.scc_largest);\n\
  fprintf (f, \"</scc-info>\\n\\n\");\n\
\n\
  /*\n\
   *  DFS statistics\n\
   */\n\
  fprintf (f, \"<dfs-info>\\n\");\n\
  for (i = 0; i < D.samples; i ++) {\n\
    fprintf (f, \"<stack-size id=\\\"%d\\\">%.4f</stack-size>\\n\",\n\
	     D.stack_samples_id[i],\n\
	     100.0 *\n\
	     (float) D.stack_samples_size[i] / (float) graph->no_nodes);\n\
\n\
  }\n\
  fprintf (f, \"<max-stack>%d</max-stack>\\n\", D.max_stack);\n\
  fprintf (f, \"<front-edges>%d</front-edges>\\n\", D.front_edges);\n\
  fprintf (f, \"<back-edges>%d</back-edges>\\n\", D.back_edges);\n\
  fprintf (f, \"<cross-edges>%d</cross-edges>\\n\", D.cross_edges);\n\
  fprintf (f, \"<shortest-cycle>%d</shortest-cycle>\\n\", D.shortest_cycle);\n\
  fprintf (f, \"</dfs-info>\\n\\n\");\n\
  mem_free (SYSTEM_HEAP, D.stack_samples_id);\n\
  mem_free (SYSTEM_HEAP, D.stack_samples_size);\n\
\n\
  /*\n\
   *  model specific data\n\
   */\n\
  model_graph_data_output (mdata, f);\n\
  model_graph_data_free (&mdata);\n\
  \n\
  fprintf (f, \"</state-space-info>\\n\");\n\
  fclose (f);\n\
}\n\
\n\
\n\
\n\
/*\n\
 *  Function: graph_dot_export\n\
 */\n\
void graph_dot_export\n\
(graph_t g,\n\
 char *  in_file,\n\
 char *  out_file) {\n\
  FILE * f = fopen (out_file, \"w\");\n\
\n\
  fprintf (f, \"digraph %s {\\n\", model_name ());\n\
  fprintf (f, \"}\\n\");\n\
  fclose (f);\n\
}\n\
\n\
\n\
\n\
void graph_make_report\n\
(char *  in_file,\n\
 char *  out_file,\n\
 char *  dot_file) {\n\
  graph_t g = graph_load (in_file, SYSTEM_HEAP);\n\
  graph_make_statistics (g, out_file);\n\
  if (dot_file) {\n\
    graph_dot_export (g, in_file, out_file);\n\
  }\n\
  graph_free (g);\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "includes.h", "w")
    f.write ("\
#ifndef LIB_INCLUDES\n\
#define LIB_INCLUDES\n\
\n\
/*  for pthread_barrier_t and stdio.h */\n\
#define _XOPEN_SOURCE 700\n\
\n\
#include \"stdio.h\"\n\
#include \"stdlib.h\"\n\
#include \"stdarg.h\"\n\
#include \"limits.h\"\n\
#include \"pthread.h\"\n\
#include \"semaphore.h\"\n\
#include \"assert.h\"\n\
#include \"malloc.h\"\n\
#include \"math.h\"\n\
#include \"string.h\"\n\
#include \"limits.h\"\n\
#include \"sys/times.h\"\n\
#include \"sys/time.h\"\n\
#include \"time.h\"\n\
#include \"unistd.h\"\n\
#include \"semaphore.h\"\n\
#include \"signal.h\"\n\
#include \"stdint.h\"\n\
\n\
#include \"config.h\"\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "main.c", "w")
    f.write ("\
#include \"report.h\"\n\
#include \"dfs.h\"\n\
#include \"bfs.h\"\n\
#include \"pd4.h\"\n\
#include \"simulator.h\"\n\
#include \"random_walk.h\"\n\
#include \"graph.h\"\n\
\n\
int main (int argc,\n\
	  char ** argv) {\n\
  int i;\n\
\n\
  /*\n\
   *  initialisation of all libraries\n\
   */\n\
  init_heap ();\n\
  init_vectors ();\n\
  init_common ();\n\
  init_storage ();\n\
  init_model ();\n\
\n\
  /*\n\
   *  simulation mode\n\
   */\n\
#if   defined(ACTION_SIMULATE)\n\
  \n\
  simulator ();\n\
\n\
#else\n\
\n\
  /*\n\
   *  normal mode\n\
   */\n\
  printf (\"Running...\\n\");\n\
\n\
  /*\n\
   *  catch SIGINT by changing the report state\n\
   */\n\
  signal (SIGINT, report_interruption_handler);\n\
\n\
  /*\n\
   *  initialisation of the report\n\
   */\n\
  glob_report = report_new (NO_WORKERS);\n\
  for (i = 1; i < argc; i += 2) {\n\
    if (0 == strcmp (argv[i], \"comp-time\")) {\n\
      float comp_time;\n\
      sscanf (argv[i + 1], \"%f\", &comp_time);\n\
      report_set_comp_time (glob_report, comp_time);\n\
    }\n\
  }\n\
\n\
  /*\n\
   *  launch the search and create the report\n\
   */\n\
#if   defined(ALGO_BFS) || defined(ALGO_FRONTIER)\n\
  bfs (glob_report);\n\
#elif defined(ALGO_DFS)\n\
  dfs (glob_report);\n\
#elif defined(ALGO_PD4)\n\
  pd4 (glob_report);\n\
#elif defined(ALGO_RWALK)\n\
  random_walk (glob_report);\n\
#endif\n\
  report_finalise (glob_report);\n\
\n\
  /*\n\
   *  termination of all libraries\n\
   */\n\
  free_heap ();\n\
  free_vectors ();\n\
  free_common ();\n\
  free_storage ();\n\
  free_model ();\n\
\n\
  report_free (glob_report);\n\
\n\
#ifdef ACTION_BUILD_RG\n\
  graph_make_report (GRAPH_FILE, RG_REPORT_FILE, NULL);\n\
#endif\n\
\n\
#endif\n\
\n\
  exit (EXIT_SUCCESS);\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "observer.h", "w")
    f.write ("\
#ifndef LIB_OBSERVER\n\
#define LIB_OBSERVER\n\
\n\
#include \"report.h\"\n\
#include \"storage.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void * observer_start (void * arg);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "observer.c", "w")
    f.write ("\
#include \"observer.h\"\n\
\n\
float mem_usage () {\n\
  float result = 0.0;\n\
  FILE * f;\n\
  char buf[30];\n\
  unsigned int size = 0;\n\
  snprintf (buf, 30, \"/proc/%u/statm\", (unsigned) getpid ());\n\
  f = fopen (buf, \"r\");\n\
  if (f) {\n\
    fscanf (f, \"%u\", &size);\n\
  }\n\
  fclose (f);\n\
  return (float) size / 1024.0;\n\
}\n\
\n\
void * observer_start\n\
(void * arg) {\n\
  report_t r = (report_t) arg;\n\
  float time = 0;\n\
  struct timeval now;\n\
  float mem;\n\
  int i;\n\
  large_unsigned_t visited;\n\
  large_unsigned_t stored;\n\
\n\
  while (r->keep_searching) {\n\
    sleep (1);\n\
    gettimeofday (&now, NULL);\n\
    stored = storage_size (r->storage);\n\
    mem = mem_usage ();\n\
    if (stored > r->states_max_stored) {\n\
      r->states_max_stored = stored;\n\
    }\n\
    if (mem > r->max_mem_used) {\n\
      r->max_mem_used = mem;\n\
    }\n\
    visited = 0;\n\
    for (i = 0; i < r->no_workers; i ++) {\n\
      visited += r->states_visited[i];\n\
    }\n\
    time = ((float) duration (r->start_time, now)) / 1000000.0;\n\
    printf (\"States:%10llu stored,\", stored);\n\
    printf (\"%10llu visited. \", visited);\n\
    printf (\"Mem.:%7.1f MB. \", mem);\n\
    printf (\"Time:%8.2f s.\\n\", time);\n\
    /*\n\
     *  check for limits\n\
     */\n\
#if defined (MEMORY_LIMITED) && defined (MAX_MEMORY)\n\
    if (mem > MAX_MEMORY) {\n\
      r->keep_searching = FALSE;\n\
      r->result = MEMORY_EXHAUSTED;\n\
    }\n\
#endif\n\
#if defined (TIME_LIMITED) && defined (MAX_TIME)\n\
    if (time > (float) MAX_TIME) {\n\
      r->keep_searching = FALSE;\n\
      r->result = TIME_ELAPSED;\n\
    }\n\
#endif\n\
#if defined (STATE_LIMITED) && defined (MAX_STATE)\n\
    if (visited > MAX_STATE) {\n\
      r->keep_searching = FALSE;\n\
      r->result = STATE_LIMIT_REACHED;\n\
    }\n\
#endif\n\
  }\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "pd4.h", "w")
    f.write ("\
#ifndef LIB_PD4\n\
#define LIB_PD4\n\
\n\
#include \"includes.h\"\n\
#include \"common.h\"\n\
#include \"state.h\"\n\
#include \"event.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void init_pd4_storage ();\n\
void free_pd4_storage ();\n\
\n\
typedef uint32_t pd4_storage_id_t;\n\
\n\
typedef struct {\n\
  pd4_storage_id_t fst_child;\n\
  pd4_storage_id_t next;\n\
  bool_t           father;\n\
  bool_t           dd;\n\
  bool_t           dd_visit;\n\
  bool_t           recons[2];\n\
  event_id_t       e;\n\
#ifdef ACTION_BUILD_RG\n\
  uint32_t         num;\n\
#endif\n\
} pd4_state_t;\n\
\n\
typedef struct {\n\
  unsigned char    content;\n\
  pd4_storage_id_t id;\n\
  pd4_storage_id_t pred;\n\
  event_id_t       e;\n\
  bit_vector_t     s;\n\
  hash_key_t       h;\n\
  uint16_t         width;\n\
} pd4_candidate_t;\n\
\n\
typedef struct {\n\
  pd4_storage_id_t root;\n\
  pd4_state_t      ST[HASH_SIZE];\n\
  int32_t          size[NO_WORKERS];\n\
  large_unsigned_t dd_time;\n\
  large_unsigned_t barrier_time[NO_WORKERS];\n\
} struct_pd4_storage_t;\n\
\n\
typedef struct_pd4_storage_t * pd4_storage_t;\n\
\n\
uint32_t pd4_storage_id_char_width;\n\
\n\
#include \"report.h\"\n\
\n\
void pd4\n\
(report_t r);\n\
\n\
pd4_storage_t pd4_storage_new\n\
();\n\
\n\
void pd4_storage_free\n\
(pd4_storage_t storage);\n\
\n\
large_unsigned_t pd4_storage_size\n\
(pd4_storage_t storage);\n\
\n\
void pd4_storage_output_stats\n\
(pd4_storage_t storage,\n\
 FILE *        out);\n\
\n\
void pd4_storage_id_serialise\n\
(pd4_storage_id_t id,\n\
 bit_vector_t     v);\n\
\n\
pd4_storage_id_t pd4_storage_id_unserialise\n\
(bit_vector_t v);\n\
\n\
void pd4_storage_insert\n\
(pd4_storage_t      storage,\n\
 state_t            s,\n\
 pd4_storage_id_t * pred,\n\
 event_id_t *       exec,\n\
 uint32_t           depth,\n\
 worker_id_t        w,\n\
 bool_t *           is_new,\n\
 pd4_storage_id_t * id);\n\
\n\
void pd4_storage_remove\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id);\n\
\n\
order_t pd4_storage_id_cmp\n\
(pd4_storage_id_t id1,\n\
 pd4_storage_id_t id2);\n\
\n\
state_t pd4_storage_get\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t ptr,\n\
 worker_id_t      w);\n\
\n\
state_t pd4_storage_get_mem\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t ptr,\n\
 worker_id_t      w,\n\
 heap_t           heap);\n\
\n\
void pd4_storage_set_in_unproc\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id,\n\
 bool_t           in_unproc);\n\
\n\
bool_t pd4_storage_get_in_unproc\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id);\n\
\n\
state_num_t pd4_storage_get_num\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id);\n\
\n\
void pd4_storage_update_refs\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id,\n\
 int              update);\n\
\n\
void pd4_storage_set_is_red\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "pd4.c", "w")
    f.write ("\
#include \"pd4.h\"\n\
#include \"prop.h\"\n\
#include \"graph.h\"\n\
\n\
static report_t R;\n\
static pd4_storage_t S;\n\
static uint32_t next_num;\n\
\n\
/*  mail boxes used during expansion  */\n\
static pd4_candidate_t * BOX[NO_WORKERS][NO_WORKERS];\n\
static uint32_t BOX_size[NO_WORKERS][NO_WORKERS];\n\
static uint32_t BOX_tot_size[NO_WORKERS];\n\
static uint32_t BOX_max_size;\n\
\n\
/*  candidate set (obtained from boxes after merging)  */\n\
static pd4_candidate_t * CS[NO_WORKERS];\n\
static uint32_t CS_size[NO_WORKERS];\n\
static uint32_t * NCS[NO_WORKERS];\n\
static uint32_t CS_max_size;\n\
\n\
/*  state table  */\n\
static pd4_state_t * ST;\n\
\n\
/*  heaps used to store candidates, to reconstruct states and\n\
 *  perform duplicate detection  */\n\
static heap_t candidates_heaps[NO_WORKERS];\n\
static heap_t expand_heaps[NO_WORKERS];\n\
static heap_t detect_heaps[NO_WORKERS];\n\
static heap_t expand_evts_heaps[NO_WORKERS];\n\
static heap_t detect_evts_heaps[NO_WORKERS];\n\
\n\
/*  random seeds  */\n\
static rseed_t seeds[NO_WORKERS];\n\
\n\
/*  synchronisation variables  */\n\
static bool_t level_terminated[NO_WORKERS];\n\
static pthread_barrier_t barrier;\n\
static uint32_t next_lvl;\n\
static uint32_t next_lvls[NO_WORKERS];\n\
static pthread_mutex_t report_mutex;\n\
static bool_t error_reported;\n\
\n\
/*  alternating bit to know which states to expand  */\n\
static uint8_t recons_id;\n\
\n\
#define EXPAND_HEAP_SIZE (1024 * 1024)\n\
#define DETECT_HEAP_SIZE (1024 * 1024)\n\
\n\
#define PD4_STATS\n\
\n\
#define PD4_CAND_NEW  1\n\
#define PD4_CAND_DEL  2\n\
#define PD4_CAND_NONE 3\n\
\n\
#define PD4_OWNER(h) (((h) & HASH_SIZE_M) % NO_WORKERS)\n\
\n\
#ifdef EVENT_UNDOABLE\n\
#define PD4_VISIT_PRE_HEAP_PROCESS() {		\\\n\
    if (heap_space_left (heap) <= 81920) {	\\\n\
      state_t copy = state_copy (s);		\\\n\
      heap_reset (heap);			\\\n\
      s = state_copy_mem (copy, heap);		\\\n\
      state_free (copy);			\\\n\
    }						\\\n\
    heap_pos = heap_get_position (heap_evts);	\\\n\
  }\n\
#define PD4_VISIT_POST_HEAP_PROCESS() {		\\\n\
    heap_set_position (heap_evts, heap_pos);	\\\n\
  }\n\
#define PD4_VISIT_HANDLE_EVENT(func) {				\\\n\
    e = state_enabled_event_mem (s, ST[curr].e, heap_evts);	\\\n\
    event_exec (e, s);						\\\n\
    s = func (w, curr, s, depth - 1);				\\\n\
    event_undo (e, s);						\\\n\
  }\n\
#else  /*  !defined(EVENT_UNDOABLE)  */\n\
#define PD4_VISIT_PRE_HEAP_PROCESS() {		\\\n\
    heap_pos = heap_get_position (heap);	\\\n\
  }\n\
#define PD4_VISIT_POST_HEAP_PROCESS() {		\\\n\
    heap_set_position (heap, heap_pos);		\\\n\
  }\n\
#define PD4_VISIT_HANDLE_EVENT(func) {				\\\n\
    e = state_enabled_event (s, ST[curr].e);			\\\n\
    t = state_succ_mem (s, e, heap);				\\\n\
    func (w, curr, t, depth - 1);				\\\n\
  }\n\
#endif\n\
\n\
#define PD4_PICK_RANDOM_NODE(w, now, start)	{		\\\n\
    unsigned int rnd;						\\\n\
    pd4_storage_id_t fst = ST[now].fst_child;			\\\n\
    start = fst;						\\\n\
    rnd = random_int (&seeds[w]) % (ST[now].father >> 1);	\\\n\
    while (rnd --) {						\\\n\
      if ((start = ST[start].next) == now) {			\\\n\
	start = fst;						\\\n\
      }								\\\n\
    }								\\\n\
  }\n\
\n\
void init_pd4_storage () {}\n\
void free_pd4_storage () {}\n\
\n\
void pd4_barrier_wait\n\
(worker_id_t w) {\n\
#ifdef PARALLEL\n\
\n\
#ifdef PD4_STATS\n\
  lna_timer_t t;\n\
  lna_timer_init (&t);\n\
  lna_timer_start (&t);\n\
#endif\n\
\n\
  pthread_barrier_wait (&barrier);\n\
\n\
#ifdef PD4_STATS\n\
  lna_timer_stop (&t);\n\
  S->barrier_time[w] += lna_timer_value (t);\n\
#endif\n\
\n\
#endif\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_storage_new\n\
 *\n\
 *****/\n\
pd4_storage_t pd4_storage_new\n\
() {\n\
  worker_id_t w, x;\n\
  unsigned int i, fst, last, s;\n\
  pd4_storage_t result;\n\
\n\
  result = mem_alloc (SYSTEM_HEAP, sizeof (struct_pd4_storage_t));\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    result->size[w] = 0;\n\
    result->barrier_time[w] = 0;\n\
  }\n\
\n\
  /*\n\
   *  initialisation of the state table\n\
   */\n\
  for (i = 0; i < HASH_SIZE; i ++) {\n\
    result->ST[i].fst_child = UINT_MAX;\n\
    result->ST[i].recons[0] = FALSE;\n\
    result->ST[i].recons[1] = FALSE;\n\
  }\n\
\n\
  result->dd_time = 0;\n\
  return result;\n\
}\n\
\n\
void pd4_storage_free\n\
(pd4_storage_t storage) {\n\
  worker_id_t w, x;\n\
  unsigned int i;\n\
  mem_free (SYSTEM_HEAP, storage);\n\
}\n\
\n\
large_unsigned_t pd4_storage_size\n\
(pd4_storage_t storage) {\n\
  large_unsigned_t result = 0;\n\
  worker_id_t w;\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    result += storage->size[w];\n\
  }\n\
  return result;\n\
}\n\
\n\
void pd4_storage_output_stats\n\
(pd4_storage_t storage,\n\
 FILE *        out) {\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_create_trace\n\
 *\n\
 *****/\n\
void pd4_create_trace\n\
(pd4_storage_id_t id) {\n\
  pd4_storage_id_t * trace;\n\
  pd4_storage_id_t pred, curr = id;\n\
  state_t s = state_initial ();\n\
  unsigned int i;\n\
  R->trace_len = 0;\n\
  while (curr != S->root) {\n\
    while (!(ST[curr].father & 1)) { curr = ST[curr].next; }\n\
    curr = ST[curr].next;\n\
    R->trace_len ++;\n\
  }\n\
  R->trace = mem_alloc (SYSTEM_HEAP, sizeof (event_t) * R->trace_len);\n\
  trace = mem_alloc (SYSTEM_HEAP,\n\
		     sizeof (pd4_storage_id_t) * (R->trace_len + 1));\n\
  i = R->trace_len;\n\
  curr = id;\n\
  trace[i --] = curr;\n\
  while (curr != S->root) {\n\
    while (!(ST[curr].father & 1)) { curr = ST[curr].next; }\n\
    curr = ST[curr].next;\n\
    trace[i --] = curr;\n\
  }\n\
  for (i = 1; i <= R->trace_len; i ++) {\n\
    R->trace[i - 1] = state_enabled_event (s, ST[trace[i]].e);\n\
    event_exec (R->trace[i - 1], s);\n\
  }\n\
  state_free (s);\n\
  free (trace);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_send_candidate\n\
 *\n\
 *****/\n\
bool_t pd4_send_candidate\n\
(worker_id_t      w,\n\
 pd4_storage_id_t pred,\n\
 event_id_t       e,\n\
 state_t          s) {\n\
  unsigned int i;\n\
  pd4_candidate_t c;\n\
  worker_id_t x;\n\
  c.content = PD4_CAND_NEW;\n\
  c.pred = pred;\n\
  c.e = e;\n\
  c.width = state_char_width (s);\n\
  c.s = mem_alloc (candidates_heaps[w], c.width);\n\
  for (i = 0; i < c.width; i ++) {\n\
    c.s[i] = 0;\n\
  }\n\
  state_serialise (s, c.s);\n\
  c.h = state_hash (s);\n\
  x = PD4_OWNER(c.h);\n\
  BOX[w][x][BOX_size[w][x]] = c;  \n\
  BOX_size[w][x] ++;\n\
  BOX_tot_size[w] ++;\n\
  return BOX_size[w][x] == BOX_max_size;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_merge_candidate_set\n\
 *\n\
 *  merge the mailboxes of workers into the candidate set before\n\
 *  performing duplicate detection\n\
 *\n\
 *****/\n\
bool_t pd4_cmp_vector\n\
(uint16_t     width,\n\
 bit_vector_t v,\n\
 bit_vector_t w) {\n\
  uint16_t i;\n\
  for (i = 0; i < width; i ++) {\n\
    if (v[i] != w[i]) {\n\
      return FALSE;\n\
    }\n\
  }\n\
  return TRUE;\n\
}\n\
\n\
bool_t pd4_merge_candidate_set\n\
(worker_id_t w) {\n\
  pd4_candidate_t * C = CS[w];\n\
  unsigned int i, pos, fst, slot;\n\
  pd4_storage_id_t id;\n\
  worker_id_t x;\n\
  bool_t loop;\n\
\n\
  CS_size[w] = 0;\n\
  for (x = 0; x < NO_WORKERS; x ++) {\n\
    for (i = 0; i < BOX_size[x][w]; i ++) {\n\
      pd4_candidate_t c = BOX[x][w][i];\n\
      fst = pos = c.h % CS_max_size;\n\
      loop = TRUE;\n\
      while (loop) {\n\
	switch (C[pos].content) {\n\
	case PD4_CAND_NONE :\n\
	  C[pos] = c;\n\
	  NCS[w][CS_size[w] ++] = pos;\n\
	  loop = FALSE;\n\
	  slot = C[pos].h & HASH_SIZE_M;\n\
\n\
	  /*  mark for reconstruction states in conflict with the candidate  */\n\
	  while (ST[slot].fst_child != UINT_MAX) {\n\
	    ST[slot].dd = TRUE;\n\
	    id = slot;\n\
	    while (id != S->root) {\n\
	      while (!(ST[id].father & 1)) {\n\
		id = ST[id].next;\n\
	      }\n\
	      id = ST[id].next;\n\
	      if (ST[id].dd_visit) {\n\
		break;\n\
	      } else {\n\
		ST[id].dd_visit = TRUE;\n\
	      }\n\
	    }\n\
	    slot = (slot + NO_WORKERS) & HASH_SIZE_M;\n\
	  }\n\
	  break;\n\
	case PD4_CAND_NEW :\n\
#ifdef ACTION_BUILD_RG\n\
	  pos = (pos + 1) % CS_max_size;\n\
	  assert (pos != fst);\n\
#else\n\
	  if (c.h == C[pos].h\n\
	      && c.width == C[pos].width\n\
	      && pd4_cmp_vector (c.width, c.s, C[pos].s)) {\n\
	    loop = FALSE;\n\
	  } else {\n\
	    pos = (pos + 1) % CS_max_size;\n\
	    assert (pos != fst);\n\
	  }\n\
#endif\n\
	  break;\n\
	case PD4_CAND_DEL :\n\
	  assert (FALSE);\n\
	}\n\
      }\n\
    }\n\
  }\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_duplicate_detection_dfs\n\
 *\n\
 *****/\n\
void pd4_storage_delete_candidate\n\
(worker_id_t      w,\n\
 state_t          s,\n\
 pd4_storage_id_t id) {\n\
  hash_key_t h = state_hash (s);\n\
  unsigned int fst, i = h % CS_max_size;\n\
  worker_id_t x = PD4_OWNER(h);\n\
  \n\
  fst = i;\n\
  do {\n\
    switch (CS[x][i].content) {\n\
    case PD4_CAND_NONE : return;\n\
    case PD4_CAND_NEW  :\n\
      if (state_cmp_vector (s, CS[x][i].s)) {\n\
	CS[x][i].content = PD4_CAND_DEL;\n\
#ifdef ACTION_BUILD_RG\n\
	CS[x][i].id = id;\n\
	break;\n\
#else\n\
	return;\n\
#endif\n\
      }\n\
    }\n\
    i = (i + 1) % CS_max_size;\n\
  } while (fst != i);\n\
}\n\
\n\
state_t pd4_duplicate_detection_dfs\n\
(worker_id_t      w,\n\
 pd4_storage_id_t now,\n\
 state_t          s,\n\
 unsigned int     depth) {\n\
  heap_t heap = detect_heaps[w];\n\
  heap_t heap_evts = detect_evts_heaps[w];\n\
  state_t t;\n\
  event_t e;\n\
  void * heap_pos;\n\
  pd4_storage_id_t start, curr;\n\
\n\
  PD4_VISIT_PRE_HEAP_PROCESS();\n\
\n\
  /*\n\
   *  remove state now from the candidate set\n\
   */\n\
  if (ST[now].dd) {\n\
    ST[now].dd = FALSE;\n\
    pd4_storage_delete_candidate (w, s, now);\n\
  }\n\
\n\
  /*\n\
   *  state now must be visited by the duplicate detection procedure\n\
   */\n\
  if (ST[now].dd_visit) {\n\
    \n\
    /*\n\
     *  we start expanding now from a randomly picked successor\n\
     */\n\
    PD4_PICK_RANDOM_NODE(w, now, start);\n\
    curr = start;\n\
    do {\n\
      if (ST[curr].dd || ST[curr].dd_visit) {\n\
	R->events_executed[w] ++;\n\
	R->events_executed_dd[w] ++;\n\
	PD4_VISIT_HANDLE_EVENT (pd4_duplicate_detection_dfs);\n\
      }\n\
      if (ST[curr].father & 1) {\n\
	curr = ST[ST[curr].next].fst_child;\n\
      } else {\n\
	curr = ST[curr].next;\n\
      }\n\
    } while (curr != start);\n\
  }\n\
  ST[now].dd = FALSE;\n\
  ST[now].dd_visit = FALSE;\n\
  PD4_VISIT_POST_HEAP_PROCESS();\n\
  return s;\n\
}\n\
\n\
\n\
#ifdef ACTION_BUILD_RG\n\
void pd4_remove_duplicates_around\n\
(pd4_candidate_t * C,\n\
 unsigned int      i) {\n\
  int j, k, m, moves[2] = { 1, -1};\n\
  for (k = 0; k < 2; k ++) {\n\
    j = i;\n\
    m = moves[k];\n\
    while (TRUE) {\n\
      j += m;\n\
      if (j == -1) { j = CS_max_size - 1; }\n\
      if (j == CS_max_size) { j = 0; }\n\
      if (C[j].content == PD4_CAND_NONE) { break; }\n\
      if (C[j].width == C[i].width\n\
	  && pd4_cmp_vector (C[j].width, C[j].s, C[i].s)) {\n\
	C[j].content = PD4_CAND_DEL;\n\
	C[j].id = C[i].id;\n\
      }\n\
    }\n\
  }\n\
}\n\
\n\
void pd4_write_nodes_graph\n\
(worker_id_t w) {\n\
  pd4_candidate_t * C = CS[w];\n\
  unsigned int i = 0;\n\
  uint8_t t, succs = 0;\n\
  for (i = 0; i < CS_max_size; i ++) {\n\
    if (PD4_CAND_NEW == C[i].content) {\n\
      t = GT_NODE;\n\
      fwrite (&t, sizeof (uint8_t), 1, R->graph_file);\n\
      fwrite (&ST[C[i].id].num, sizeof (node_t), 1, R->graph_file);\n\
      fwrite (&succs, sizeof (uint8_t), 1, R->graph_file);\n\
    }\n\
  }\n\
  for (i = 0; i < CS_max_size; i ++) {\n\
    if (PD4_CAND_NONE != C[i].content) {\n\
      t = GT_EDGE;\n\
      fwrite (&t, sizeof (uint8_t), 1, R->graph_file);\n\
      fwrite (&ST[C[i].pred].num, sizeof (node_t), 1, R->graph_file);\n\
      fwrite (&C[i].e, sizeof (edge_num_t), 1, R->graph_file);\n\
      fwrite (&ST[C[i].id].num, sizeof (node_t), 1, R->graph_file);\n\
    }\n\
  }\n\
}\n\
#endif\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_insert_new_states\n\
 *\n\
 *  insert in the state tree states that are still in the candidate\n\
 *  set after duplicate detection\n\
 *\n\
 *****/\n\
pd4_storage_id_t pd4_insert_new_state\n\
(worker_id_t      w,\n\
 hash_key_t       h,\n\
 pd4_state_t      s,\n\
 pd4_storage_id_t pred) {\n\
  uint8_t r = (recons_id + 1) & 1;\n\
  unsigned int id, fst = h & HASH_SIZE_M, slot = fst;\n\
  while (ST[slot].fst_child != UINT_MAX) {\n\
    assert ((slot = (slot + NO_WORKERS) & HASH_SIZE_M) != fst);\n\
  }\n\
  s.next = s.fst_child = slot;\n\
#ifdef ACTION_BUILD_RG\n\
  s.num = next_num ++;\n\
#endif\n\
  ST[slot] = s;\n\
\n\
  /*  mark the state for the next expansion step  */\n\
  do {\n\
    ST[pred].recons[r] = TRUE;\n\
    while (!(ST[pred].father & 1)) {\n\
      pred = ST[pred].next;\n\
    }\n\
    pred = ST[pred].next;\n\
  } while (pred != S->root && !ST[pred].recons[r]);\n\
  return slot;\n\
}\n\
\n\
void pd4_insert_new_states\n\
(worker_id_t w) {\n\
  worker_id_t x;\n\
  unsigned int i = 0;\n\
  pd4_candidate_t c, * C = CS[w];\n\
  pd4_state_t ns;\n\
  unsigned int no_new = 0;\n\
\n\
  ns.dd = ns.dd_visit = ns.recons[recons_id] = FALSE;\n\
  ns.recons[(recons_id + 1) & 1] = TRUE;\n\
  for (i = 0; i < CS_size[w]; i ++) {\n\
    c = C[NCS[w][i]];\n\
    if (PD4_CAND_NEW == c.content) {\n\
      no_new ++;\n\
      ns.e = c.e;\n\
      ns.father = 0;\n\
      C[NCS[w][i]].id = pd4_insert_new_state (w, c.h, ns, c.pred);\n\
#ifdef ACTION_BUILD_RG\n\
      pd4_remove_duplicates_around (C, NCS[w][i]);\n\
#endif\n\
    }\n\
  }\n\
  S->size[w] += no_new;\n\
  next_lvls[w] += no_new;\n\
#ifdef ACTION_BUILD_RG\n\
  pd4_write_nodes_graph (w);\n\
#endif\n\
\n\
  pd4_barrier_wait (w);\n\
\n\
  if (0 == w) {\n\
    for (x = 0; x < NO_WORKERS; x ++) {\n\
      for (i = 0; i < CS_size[x]; i ++) {\n\
	c = CS[x][NCS[x][i]];\n\
	if (PD4_CAND_NEW == c.content) {\n\
	  if (ST[c.pred].fst_child == c.pred) {\n\
	    ST[c.id].next = c.pred;\n\
	    ST[c.id].father += 1;\n\
	  } else {\n\
	    ST[c.id].next = ST[c.pred].fst_child;\n\
	  }\n\
	  ST[c.pred].fst_child = c.id;\n\
	  ST[c.pred].father += 2;\n\
	}\n\
	CS[x][NCS[x][i]].content = PD4_CAND_NONE;\n\
      }\n\
    }\n\
  }\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_duplicate_detection\n\
 *\n\
 *****/\n\
bool_t pd4_duplicate_detection\n\
(worker_id_t w) {\n\
  state_t s;\n\
  worker_id_t x;\n\
  bool_t all_terminated = TRUE;\n\
  lna_timer_t t;\n\
\n\
  if (0 == w) {\n\
    lna_timer_init (&t);\n\
    lna_timer_start (&t);\n\
  }\n\
\n\
  /*\n\
   *  initialize heaps for duplicate detection\n\
   */\n\
#ifdef EVENT_UNDOABLE\n\
  heap_reset (detect_evts_heaps[w]);\n\
#endif\n\
  heap_reset (detect_heaps[w]);\n\
  s = state_initial_mem (detect_heaps[w]);\n\
\n\
  /*\n\
   *  merge the candidate set and mark states to reconstruct\n\
   */\n\
  pd4_barrier_wait (w);\n\
  if (pd4_storage_size (S) >= 0.9 * HASH_SIZE) {\n\
    pthread_mutex_lock (&report_mutex);\n\
    raise_error (\"state table too small (increase --hash-size and rerun)\");\n\
    pthread_mutex_unlock (&report_mutex);\n\
  }\n\
  if (!R->keep_searching) {\n\
    pthread_exit (NULL);\n\
  }\n\
  pd4_merge_candidate_set (w);\n\
\n\
  /*\n\
   *  reconstruct states and perform duplicate detection\n\
   */\n\
  pd4_barrier_wait (w);\n\
  pd4_duplicate_detection_dfs (w, S->root, s, 0);\n\
\n\
  /*\n\
   *  insert these new states in the tree\n\
   */\n\
  pd4_barrier_wait (w);\n\
  pd4_insert_new_states (w);\n\
\n\
  /*\n\
   *  reinitialise my mail boxes and candidate heaps\n\
   */\n\
  heap_reset (candidates_heaps[w]);\n\
  BOX_tot_size[w] = 0;\n\
  for (x = 0; x < NO_WORKERS; x ++) {\n\
    BOX_size[w][x] = 0;\n\
    all_terminated = all_terminated && level_terminated[x];\n\
  }\n\
  if (0 == w) {\n\
    lna_timer_stop (&t);\n\
    S->dd_time += lna_timer_value (t);\n\
  }\n\
  return all_terminated ? FALSE : TRUE;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_expand_dfs\n\
 *\n\
 *  recursive function called by pd4_expand to explore state now\n\
 *\n\
 *****/\n\
state_t pd4_expand_dfs\n\
(worker_id_t      w,\n\
 pd4_storage_id_t now,\n\
 state_t          s,\n\
 unsigned int     depth) {\n\
  heap_t heap = expand_heaps[w];\n\
  heap_t heap_evts = expand_evts_heaps[w];\n\
  void * heap_pos;\n\
  pd4_storage_id_t start, curr;\n\
  state_t t;\n\
  event_t e;\n\
  event_id_t e_id;\n\
  event_set_t en;\n\
  unsigned int en_size, i;\n\
  worker_id_t x, y;\n\
  uint32_t size;\n\
\n\
  PD4_VISIT_PRE_HEAP_PROCESS();\n\
\n\
  if (0 == depth) {\n\
    \n\
    /*\n\
     *  we have reached a leaf => we expand it\n\
     */\n\
    en = state_enabled_events_mem (s, heap);\n\
#ifdef ACTION_CHECK_SAFETY\n\
    if (state_check_property (s, en)) {\n\
      pthread_mutex_lock (&report_mutex);\n\
      if (!error_reported) {\n\
	error_reported = TRUE;\n\
	report_faulty_state (R, s);\n\
	pd4_create_trace (now);\n\
      }\n\
      pthread_mutex_unlock (&report_mutex);\n\
    }\n\
#endif\n\
    en_size = event_set_size (en);\n\
    if (0 == en_size) {\n\
      R->states_dead[w] ++;\n\
    }\n\
    for (i = 0; i < en_size; i ++) {\n\
      R->arcs[w] ++;\n\
      R->events_executed[w] ++;\n\
      e = event_set_nth (en, i);\n\
      e_id = event_set_nth_id (en, i);\n\
      t = state_succ_mem (s, e, heap);\n\
      if (pd4_send_candidate (w, now, e_id, t)) {\n\
	assert (0);\n\
	pd4_duplicate_detection (w);\n\
      }\n\
    }\n\
    R->states_visited[w] ++;\n\
\n\
    /*\n\
     *  perform duplicate detection if the candidate set is full\n\
     */\n\
    size = 0;\n\
    for (x = 0; x < NO_WORKERS; x ++) {\n\
      size += BOX_tot_size[x];\n\
    }\n\
    if (size >= PD4_CAND_SET_SIZE) {\n\
      pd4_duplicate_detection (w);\n\
    }\n\
  } else {\n\
\n\
    /*\n\
     *  we start expanding now from a randomly picked successor\n\
     */\n\
    PD4_PICK_RANDOM_NODE(w, now, start);\n\
    curr = start;\n\
    do {\n\
      if (ST[curr].recons[recons_id]) {\n\
	R->events_executed[w] ++;\n\
	PD4_VISIT_HANDLE_EVENT (pd4_expand_dfs);\n\
      }\n\
      if (ST[curr].father & 1) {\n\
	curr = ST[ST[curr].next].fst_child;\n\
      } else {\n\
	curr = ST[curr].next;\n\
      }\n\
    } while (curr != start);\n\
  }\n\
\n\
  ST[now].recons[recons_id] = FALSE;\n\
  PD4_VISIT_POST_HEAP_PROCESS();\n\
  return s;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_expand\n\
 *\n\
 *****/\n\
void pd4_expand\n\
(worker_id_t w,\n\
 unsigned int depth) {\n\
  state_t s;\n\
\n\
#ifdef EVENT_UNDOABLE\n\
  heap_reset (expand_evts_heaps[w]);\n\
#endif\n\
  heap_reset (expand_heaps[w]);\n\
  s = state_initial_mem (expand_heaps[w]);\n\
  pd4_expand_dfs (w, S->root, s, depth);\n\
  level_terminated[w] = TRUE;\n\
  while (pd4_duplicate_detection (w));\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4_worker\n\
 *\n\
 *****/\n\
void * pd4_worker\n\
(void * arg) {\n\
  worker_id_t x, w = (worker_id_t) (unsigned long int) arg;\n\
  unsigned int depth = 0;\n\
\n\
  if (0 == w) {\n\
    pd4_state_t ns;\n\
    state_t s = state_initial ();\n\
    hash_key_t h = state_hash (s);\n\
    pd4_storage_id_t slot = h & HASH_SIZE_M;\n\
    uint8_t t = GT_NODE, succs = 0;\n\
    ns.dd = ns.dd_visit = ns.recons[0] = FALSE;\n\
    ns.recons[1] = ns.father = 1;\n\
    ns.next = ns.fst_child = slot;\n\
#ifdef ACTION_BUILD_RG\n\
    ns.num = next_num ++;\n\
    fwrite (&t, sizeof (uint8_t), 1, R->graph_file);\n\
    fwrite (&ns.num, sizeof (node_t), 1, R->graph_file);\n\
    fwrite (&succs, sizeof (uint8_t), 1, R->graph_file);\n\
#endif\n\
    ST[slot] = ns;\n\
    S->root = slot;\n\
    S->size[0] = 1;\n\
    state_free (s);\n\
    recons_id = 0;\n\
    next_lvl = 1;\n\
    report_update_max_unproc_size (R, 1);\n\
  }\n\
  pd4_barrier_wait (w);\n\
  while (next_lvl != 0) {\n\
\n\
    /*\n\
     *  initialise some data for the next level\n\
     */\n\
    pd4_barrier_wait (w);\n\
    level_terminated[w] = FALSE;\n\
    next_lvls[w] = 0;\n\
    if (0 == w) {\n\
      next_lvl = 0;\n\
      recons_id = (recons_id + 1) & 1;\n\
    }\n\
\n\
    /*\n\
     *  all workers expand the current level\n\
     */\n\
    pd4_barrier_wait (w);\n\
    pd4_expand (w, depth);\n\
    depth ++;\n\
    if (0 == w) {\n\
      for (x = 0; x < NO_WORKERS; x ++) {\n\
	next_lvl += next_lvls[x];\n\
      }\n\
      report_update_max_unproc_size (R, next_lvl);\n\
      report_update_bfs_levels (R, depth);\n\
    }\n\
    pd4_barrier_wait (w);\n\
  }\n\
  return NULL;\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: pd4\n\
 *\n\
 *****/\n\
void pd4\n\
(report_t r) {  \n\
  worker_id_t w, x;\n\
  void * dummy;\n\
  unsigned int i, s;\n\
\n\
  R = r;\n\
  S = (pd4_storage_t) r->storage;\n\
  ST = S->ST;\n\
  pthread_barrier_init (&barrier, NULL, NO_WORKERS);\n\
  pthread_mutex_init (&report_mutex, NULL);\n\
  error_reported = FALSE;\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    seeds[w] = random_seed (w);\n\
  }\n\
  next_num = 0;\n\
  R->graph_file = open_graph_file ();\n\
\n\
  /*\n\
   *  initialisation of the heaps\n\
   */\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    expand_heaps[w] =\n\
      bounded_heap_new (\"reconstruction\", EXPAND_HEAP_SIZE);\n\
    detect_heaps[w] =\n\
      bounded_heap_new (\"duplicate detection\", DETECT_HEAP_SIZE);\n\
    candidates_heaps[w] =\n\
      evergrowing_heap_new (\"candidate set\", 1024 * 1024);\n\
#ifdef EVENT_UNDOABLE\n\
    expand_evts_heaps[w] =\n\
      bounded_heap_new (\"reconstruction events\", EXPAND_HEAP_SIZE);\n\
    detect_evts_heaps[w] =\n\
      bounded_heap_new (\"duplicate detection events\", DETECT_HEAP_SIZE);\n\
#endif\n\
  }\n\
\n\
  /*\n\
   *  initialisation of the mailboxes of workers\n\
   */\n\
  BOX_max_size = (PD4_CAND_SET_SIZE / (NO_WORKERS * NO_WORKERS)) << 1;\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    for (x = 0; x < NO_WORKERS; x ++) {\n\
      s = BOX_max_size * sizeof (pd4_candidate_t);\n\
      BOX[w][x] = mem_alloc (SYSTEM_HEAP, s);\n\
      for (i = 0; i < BOX_max_size; i ++) {\n\
	BOX[w][x][i].content = PD4_CAND_NONE;\n\
	BOX[w][x][i].h = 0;\n\
	BOX_size[w][x] = 0;\n\
      }\n\
    }\n\
    BOX_tot_size[w] = 0;\n\
  }\n\
\n\
  /*\n\
   *  initialisation of the candidate set\n\
   */\n\
  CS_max_size = (PD4_CAND_SET_SIZE / NO_WORKERS) << 1;\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    CS[w] = mem_alloc (SYSTEM_HEAP, CS_max_size * sizeof (pd4_candidate_t));\n\
    NCS[w] = mem_alloc (SYSTEM_HEAP, CS_max_size * sizeof (uint32_t));\n\
    for (i = 0; i < CS_max_size; i ++) {\n\
      CS[w][i].content = PD4_CAND_NONE;\n\
    }\n\
    CS_size[w] = 0;\n\
  }\n\
  \n\
  /*\n\
   *  start the threads and wait for their termination\n\
   */\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_create (&(r->workers[w]), NULL, &pd4_worker, (void *) (long) w);\n\
  }\n\
  for (w = 0; w < r->no_workers; w ++) {\n\
    pthread_join (r->workers[w], &dummy);\n\
  }\n\
\n\
  /*\n\
   *  free heaps and mailboxes\n\
   */\n\
  for (w = 0; w < NO_WORKERS; w ++) {\n\
    for (x = 0; x < NO_WORKERS; x ++) {\n\
      mem_free (SYSTEM_HEAP, BOX[w][x]);\n\
    }\n\
    heap_free (candidates_heaps[w]);\n\
    heap_free (expand_heaps[w]);\n\
    heap_free (detect_heaps[w]);\n\
#ifdef EVENT_UNDOABLE\n\
    heap_free (expand_evts_heaps[w]);\n\
    heap_free (detect_evts_heaps[w]);\n\
#endif\n\
  }\n\
  if (R->graph_file) {\n\
    fclose (R->graph_file);\n\
    R->graph_file = NULL;\n\
  }\n\
}\n\
\n\
\n\
/*****\n\
 *\n\
 *  Unimplemented functions that should not be called anyway\n\
 *\n\
 *****/\n\
void pd4_storage_id_serialise\n\
(pd4_storage_id_t id,\n\
 bit_vector_t     v) {\n\
  fatal_error (\"pd4_storage_id_serialise: not implemented\");\n\
}\n\
\n\
pd4_storage_id_t pd4_storage_id_unserialise\n\
(bit_vector_t v) {\n\
  fatal_error (\"pd4_storage_id_unserialise: not implemented\");\n\
}\n\
\n\
order_t pd4_storage_id_cmp\n\
(pd4_storage_id_t id1,\n\
 pd4_storage_id_t id2) {\n\
  fatal_error (\"pd4_storage_id_cmp: not implemented\");\n\
}\n\
\n\
void pd4_storage_insert\n\
(pd4_storage_t      storage,\n\
 state_t            s,\n\
 pd4_storage_id_t * pred,\n\
 event_id_t *       exec,\n\
 uint32_t           depth,\n\
 worker_id_t        w,\n\
 bool_t *           is_new,\n\
 pd4_storage_id_t * id) {\n\
  fatal_error (\"pd4_storage_insert: not implemented\");\n\
}\n\
\n\
void pd4_storage_remove\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id) {\n\
  fatal_error (\"pd4_storage_remove: not implemented\");\n\
}\n\
\n\
state_t pd4_storage_get\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t ptr,\n\
 worker_id_t      w) {\n\
  fatal_error (\"pd4_storage_get: not implemented\");\n\
}\n\
\n\
state_t pd4_storage_get_mem\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t ptr,\n\
 worker_id_t      w,\n\
 heap_t           heap) {\n\
  fatal_error (\"pd4_storage_get_mem: not implemented\");\n\
}\n\
\n\
void pd4_storage_set_in_unproc\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id,\n\
 bool_t           in_unproc) {\n\
  fatal_error (\"pd4_storage_set_in_unproc: not implemented\");\n\
}\n\
\n\
bool_t pd4_storage_get_in_unproc\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id) {\n\
  fatal_error (\"pd4_storage_get_in_unproc: not implemented\");\n\
}\n\
\n\
state_num_t pd4_storage_get_num\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id) {\n\
  fatal_error (\"pd4_storage_get_num: not implemented\");\n\
}\n\
\n\
void pd4_storage_update_refs\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id,\n\
 int              update) {\n\
  fatal_error (\"pd4_storage_update_refs: not implemented\");\n\
}\n\
\n\
void pd4_storage_set_is_red\n\
(pd4_storage_t    storage,\n\
 pd4_storage_id_t id) {\n\
  fatal_error (\"pd4_storage_set_is_red: not implemented\");\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "random_walk.h", "w")
    f.write ("\
#ifndef LIB_RANDOM_WALK\n\
#define LIB_RANDOM_WALK\n\
\n\
#include \"includes.h\"\n\
#include \"report.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void random_walk\n\
(report_t r);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "random_walk.c", "w")
    f.write ("\
#include \"random_walk.h\"\n\
#include \"prop.h\"\n\
\n\
#define RW_MAX_DEPTH 10000\n\
#define RW_HEAP_SIZE (RW_MAX_DEPTH * 1024)\n\
\n\
static report_t R;\n\
\n\
void * random_walk_worker\n\
(void * arg) {\n\
  worker_id_t w = (worker_id_t) (long) arg;\n\
  state_t s;\n\
  event_set_t en;\n\
  event_t e;\n\
  int i, j;\n\
  unsigned int seed = random_seed (w);\n\
  unsigned int en_size;\n\
  unsigned int stack_size;\n\
  char heap_name [100];\n\
  event_t stack[RW_MAX_DEPTH];\n\
  heap_t heap;\n\
  event_t * tr;\n\
\n\
  sprintf (heap_name, \"random walk heap of worker %d\", w);\n\
  heap = bounded_heap_new (heap_name, RW_HEAP_SIZE);\n\
\n\
  while (R->keep_searching) {\n\
    heap_reset (heap);\n\
    stack_size = 0;\n\
    s = state_initial_mem (heap);\n\
    for (i = 0; i < RW_MAX_DEPTH && R->keep_searching; i ++) {\n\
      en = state_enabled_events_mem (s, heap);\n\
      en_size = event_set_size (en);\n\
#ifdef ACTION_CHECK_SAFETY\n\
      if (state_check_property (s, en)) {\n\
	report_faulty_state (R, s);\n\
	tr = mem_alloc (SYSTEM_HEAP, sizeof (event_t) * stack_size);\n\
	for (j = 0; j < stack_size; j ++) {\n\
	  tr[j] = event_copy (stack[j]);\n\
	}\n\
	R->trace = tr;\n\
	R->trace_len = stack_size;\n\
	break;\n\
      }\n\
#endif\n\
      if (0 != en_size) {\n\
	e = event_set_nth (en, random_int (&seed) % en_size);\n\
	event_exec (e, s);\n\
	stack[stack_size ++] = e;\n\
      }\n\
      R->events_executed[w] ++;\n\
      R->states_visited[w] ++;\n\
      R->arcs[w] += en_size;\n\
      event_set_free (en);\n\
      if (0 == en_size) {\n\
	R->states_dead[w] ++;\n\
	break;\n\
      }\n\
    }\n\
    state_free (s);\n\
  }\n\
  heap_free (heap);\n\
}\n\
\n\
void random_walk\n\
(report_t r) {\n\
  worker_id_t w;\n\
  void * dummy;\n\
\n\
  R = r;\n\
\n\
  /*\n\
   *  launch threads and wait for their termination\n\
   */\n\
  for (w = 0; w < r->no_workers; w ++)\n\
    pthread_create (&(r->workers[w]), NULL,\n\
		    &random_walk_worker, (void *) (long) w);\n\
  for (w = 0; w < r->no_workers; w ++)\n\
    pthread_join (r->workers[w], &dummy);\n\
}\n\
\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "report.h", "w")
    f.write ("\
#ifndef LIB_REPORT\n\
#define LIB_REPORT\n\
\n\
#include \"includes.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
struct struct_report_t;\n\
\n\
typedef struct struct_report_t struct_report_t;\n\
\n\
typedef struct_report_t * report_t;\n\
\n\
#include \"model.h\"\n\
#include \"storage.h\"\n\
\n\
void init_report ();\n\
void free_report ();\n\
\n\
struct struct_report_t {\n\
  unsigned int no_workers;\n\
  char * error_msg;\n\
  unsigned int errors;\n\
  termination_state_t result;\n\
  FILE * graph_file;\n\
  storage_t storage;\n\
  bool_t keep_searching;\n\
  struct timeval start_time;\n\
  struct timeval end_time;\n\
\n\
  /*\n\
   *  for the trace report\n\
   */\n\
  bool_t faulty_state_found;\n\
  state_t faulty_state;\n\
  event_t * trace;\n\
  unsigned int trace_len;\n\
\n\
  /*\n\
   *  statistics field\n\
   */\n\
  large_unsigned_t * states_accepting;\n\
  large_unsigned_t * states_visited;\n\
  large_unsigned_t * states_dead;\n\
  large_unsigned_t * arcs;\n\
  large_unsigned_t * events_executed;\n\
  large_unsigned_t * events_executed_dd;\n\
  large_unsigned_t * state_cmps;\n\
  large_unsigned_t exec_time;\n\
  large_unsigned_t max_unproc_size;\n\
  large_unsigned_t states_max_stored;\n\
  unsigned int bfs_levels;\n\
  bool_t bfs_levels_ok;\n\
  float max_mem_used;\n\
  float comp_time;\n\
\n\
  /*\n\
   *  threads\n\
   */\n\
  pthread_t observer;\n\
  pthread_t * workers;\n\
};\n\
\n\
report_t glob_report;\n\
\n\
report_t report_new\n\
(unsigned int no_workers);\n\
\n\
void report_free\n\
();\n\
\n\
void report_finalise\n\
(report_t r);\n\
\n\
bool_t report_error\n\
(char * msg);\n\
\n\
void report_interruption_handler\n\
(int signal);\n\
\n\
void report_stop_search\n\
();\n\
\n\
void report_set_comp_time\n\
(report_t r,\n\
 float    comp_time);\n\
\n\
void report_update_bfs_levels\n\
(report_t     r,\n\
 unsigned int bfs_levels);\n\
\n\
void report_update_max_unproc_size\n\
(report_t         r,\n\
 large_unsigned_t max_unproc_size);\n\
\n\
void report_faulty_state\n\
(report_t r,\n\
 state_t  s);\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "report.c", "w")
    f.write ("\
#include \"report.h\"\n\
#include \"observer.h\"\n\
\n\
report_t report_new\n\
(unsigned int no_workers) {\n\
  report_t result;\n\
  unsigned int i;\n\
\n\
  result = mem_alloc (SYSTEM_HEAP, sizeof (struct_report_t));\n\
\n\
  /*\n\
   *  initialisation of statistic related fields\n\
   */\n\
  result->states_visited =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->states_dead =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->states_accepting =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->arcs =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->events_executed =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->events_executed_dd =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  result->state_cmps =\n\
    mem_alloc (SYSTEM_HEAP, no_workers * sizeof (large_unsigned_t));\n\
  for (i = 0; i < no_workers; i ++) {\n\
    result->states_visited[i] = 0;\n\
    result->states_accepting[i] = 0;\n\
    result->states_dead[i] = 0;\n\
    result->arcs[i] = 0;\n\
    result->events_executed[i] = 0;\n\
    result->events_executed_dd[i] = 0;\n\
    result->state_cmps[i] = 0;\n\
  }\n\
  result->max_unproc_size = 0;\n\
  result->bfs_levels = 0;\n\
  result->bfs_levels_ok = FALSE;\n\
  result->max_mem_used = 0.0;\n\
  result->states_max_stored = 0;\n\
  result->comp_time = 0.0;\n\
\n\
  result->no_workers = no_workers;\n\
  result->storage = storage_new ();\n\
  result->faulty_state_found = FALSE;\n\
  result->trace = NULL;\n\
  result->trace_len = 0;\n\
  result->error_msg = NULL;\n\
  result->errors = 0;\n\
  result->keep_searching = TRUE;\n\
  gettimeofday (&result->start_time, NULL);\n\
  result->graph_file = NULL;\n\
#ifdef PROPERTY\n\
#ifdef STORAGE_HASH_COMPACTION\n\
  result->result = NO_ERROR;\n\
#else\n\
  result->result = SUCCESS;\n\
#endif\n\
#else\n\
  result->result = SEARCH_TERMINATED;\n\
#endif\n\
\n\
  /*\n\
   *  launch the observer thread\n\
   */\n\
#ifdef WITH_OBSERVER\n\
  pthread_create (&result->observer, NULL, &observer_start,\n\
		  (void *) result);\n\
#else\n\
  result->observer = NULL;\n\
#endif\n\
  \n\
  result->workers =\n\
    mem_alloc (SYSTEM_HEAP, sizeof (pthread_t) * result->no_workers);\n\
  return result;\n\
}\n\
\n\
void report_free\n\
(report_t report) {\n\
  unsigned int i;\n\
  free (report->states_visited);\n\
  free (report->states_dead);\n\
  free (report->states_accepting);\n\
  free (report->arcs);\n\
  free (report->events_executed);\n\
  free (report->events_executed_dd);\n\
  free (report->state_cmps);\n\
  storage_free (report->storage);\n\
  if (report->error_msg) {\n\
    free (report->error_msg);\n\
  }\n\
  free (report->workers);\n\
  if (report->trace) {\n\
    free (report->trace);\n\
  }\n\
  if (report->faulty_state_found) {\n\
    state_free (report->faulty_state);\n\
  }\n\
  free (report);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: report_output_trace\n\
 *\n\
 *****/\n\
void report_output_trace\n\
(report_t r,\n\
 FILE * out) {\n\
  unsigned int i = 0;\n\
  state_t s = state_initial ();\n\
  \n\
  state_to_xml (s, out);\n\
  for (i = 0; i < r->trace_len; i ++) {\n\
    if (!event_is_dummy (r->trace[i])) {\n\
      event_to_xml (r->trace[i], out);\n\
      event_exec (r->trace[i], s);\n\
#ifdef TRACE_FULL\n\
      state_to_xml (s, out);\n\
#endif\n\
    }\n\
  }\n\
#ifdef TRACE_EVENTS\n\
  if (r->trace_len > 0) {\n\
    state_to_xml (s, out);\n\
  }\n\
#endif\n\
  state_free (s);\n\
}\n\
\n\
\n\
\n\
/*****\n\
 *\n\
 *  Function: report_finalise\n\
 *\n\
 *****/\n\
void report_finalise\n\
(report_t r) {\n\
  FILE * out;\n\
  void * dummy;\n\
  large_unsigned_t ssize;\n\
  large_unsigned_t visited;\n\
  \n\
  if (NULL != r->graph_file) {\n\
    fclose (r->graph_file);\n\
  }\n\
  r->keep_searching = FALSE;\n\
  gettimeofday (&r->end_time, NULL);\n\
  r->exec_time = duration (r->start_time, r->end_time);\n\
#ifdef WITH_OBSERVER\n\
  pthread_join (r->observer, &dummy);\n\
#endif\n\
  out = fopen (REPORT_FILE, \"w\");\n\
  fprintf (out, \"<helenaReport>\\n\");\n\
\n\
  /***\n\
   *  info report\n\
   ***/\n\
  fprintf (out, \"<infoReport>\\n\");\n\
  fprintf (out, \"<model>%s</model>\\n\", model_name ());\n\
  model_xml_parameters (out);\n\
#ifdef LANGUAGE\n\
  fprintf (out, \"<language>%s</language>\\n\", LANGUAGE);\n\
#endif\n\
#ifdef DATE\n\
  fprintf (out, \"<date>%s</date>\\n\", DATE);\n\
#endif\n\
#ifdef FILE_PATH\n\
  fprintf (out, \"<filePath>%s</filePath>\\n\", FILE_PATH);\n\
#endif\n\
#ifdef HOST\n\
  fprintf (out, \"<host>%s</host>\\n\", HOST);\n\
#endif\n\
  fprintf (out, \"</infoReport>\\n\");\n\
\n\
  /***\n\
   *  search report\n\
   ***/\n\
  fprintf (out, \"<searchReport>\\n\");\n\
#ifdef PROPERTY\n\
  fprintf (out, \"<property>%s</property>\\n\", PROPERTY);\n\
#endif\n\
  switch(r->result) {\n\
  case STATE_LIMIT_REACHED:\n\
    fprintf (out, \"<stateLimitReached/>\\n\"); break;\n\
  case MEMORY_EXHAUSTED:\n\
    fprintf (out, \"<memoryExhausted/>\\n\"); break;\n\
  case TIME_ELAPSED:\n\
    fprintf (out, \"<timeElapsed/>\\n\"); break;\n\
  case INTERRUPTION:\n\
    fprintf (out, \"<interruption/>\\n\"); break;\n\
  case SEARCH_TERMINATED:\n\
    fprintf (out, \"<searchTerminated/>\\n\"); break;\n\
  case NO_ERROR:\n\
    fprintf (out, \"<noCounterExample/>\\n\"); break;\n\
  case SUCCESS:\n\
    fprintf (out, \"<propertyHolds/>\\n\"); break;\n\
  case FAILURE:\n\
    fprintf (out, \"<propertyViolated/>\\n\"); break;\n\
  case ERROR:\n\
    fprintf (out, \"<error/>\\n\");\n\
    fprintf (out, \"<errorMessage>%s</errorMessage>\\n\", r->error_msg);\n\
    break;\n\
  }\n\
#if   defined(ALGO_DFS)\n\
  fprintf (out, \"<depthSearch/>\\n\");\n\
#elif defined(ALGO_BFS)\n\
  fprintf (out, \"<breadthSearch/>\\n\");\n\
#elif defined(ALGO_FRONTIER)\n\
  fprintf (out, \"<frontierSearch/>\\n\");\n\
#elif defined(ALGO_RWALK)\n\
  fprintf (out, \"<randomWalk/>\\n\");\n\
#elif defined(ALGO_PD4)\n\
  fprintf (out, \"<parallelDDDD/>\\n\");\n\
#endif\n\
#if defined(NO_WORKERS)\n\
  fprintf (out, \"<workers>%d</workers>\\n\", NO_WORKERS);\n\
#endif\n\
  fprintf (out, \"<searchOptions>\\n\");\n\
#if defined (HASH_STORAGE) || defined (PD4_STORAGE)\n\
  fprintf (out, \"<hashTableSlots>%d</hashTableSlots>\\n\", HASH_SIZE);\n\
#endif\n\
#ifdef STORAGE_DELTA\n\
  fprintf (out, \"<deltaCompression>%d</deltaCompression>\\n\",\n\
	   STORAGE_DELTA_K);\n\
#endif\n\
#ifdef STATE_CACHING\n\
  fprintf (out, \"<stateCaching>%d</stateCaching>\\n\",\n\
	   STATE_CACHING_CACHE_SIZE);\n\
#endif\n\
#ifdef STORAGE_HASH_COMPACTION\n\
  fprintf (out, \"<hashCompact/>\\n\");\n\
#endif\n\
#ifdef POR\n\
  fprintf (out, \"<partialOrder/>\\n\");\n\
#endif\n\
#if defined(ALGO_PD4)\n\
  fprintf (out, \"<candidateSetSize>%d</candidateSetSize>\\n\",\n\
	   PD4_CAND_SET_SIZE);\n\
#endif\n\
  fprintf (out, \"</searchOptions>\\n\");\n\
  fprintf (out, \"</searchReport>\\n\");\n\
\n\
  /***\n\
   *  statistics report\n\
   ***/\n\
  fprintf (out, \"<statisticsReport>\\n\");\n\
  /*  time  */\n\
  fprintf (out, \"<timeStatistics>\\n\");\n\
  if (r->comp_time > 0) {\n\
    fprintf (out, \"<compilationTime>%.2f</compilationTime>\\n\", r->comp_time);\n\
  }\n\
  fprintf (out, \"<searchTime>%.2f</searchTime>\\n\", r->exec_time / 1000000.0);\n\
#if defined(ALGO_PD4)\n\
  fprintf (out, \"<duplicateDetectionTime>%.2f</duplicateDetectionTime>\\n\",\n\
	   r->storage->dd_time / 1000000.0);\n\
  fprintf (out, \"<barrierTime>%.2f</barrierTime>\\n\",\n\
	   do_large_sum (r->storage->barrier_time, r->no_workers) / 1000000.0);\n\
#endif\n\
  fprintf (out, \"</timeStatistics>\\n\");\n\
  /*  model */\n\
  model_xml_statistics (out);\n\
  /*  reachability graph  */\n\
  fprintf (out, \"<graphStatistics>\\n\");\n\
  ssize = storage_size (r->storage);\n\
  fprintf (out, \"<statesStored>%llu</statesStored>\\n\", ssize);\n\
  fprintf (out, \"<statesMaxStored>%llu</statesMaxStored>\\n\",\n\
	   (ssize > r->states_max_stored) ? ssize : r->states_max_stored);\n\
  visited = do_large_sum (r->states_visited, r->no_workers);\n\
  fprintf (out, \"<statesExpanded>%llu</statesExpanded>\\n\", visited);\n\
#ifdef ACTION_CHECK_LTL\n\
  fprintf (out, \"<statesAccepting>%llu</statesAccepting>\\n\",\n\
	   do_large_sum (r->states_accepting, r->no_workers));\n\
#endif\n\
  fprintf (out, \"<statesTerminal>%llu</statesTerminal>\\n\",\n\
	   do_large_sum (r->states_dead, r->no_workers));\n\
  fprintf (out, \"<arcs>%llu</arcs>\\n\",\n\
	   do_large_sum (r->arcs, r->no_workers));\n\
  if (r->bfs_levels_ok) {\n\
    fprintf (out, \"<bfsLevels>%u</bfsLevels>\\n\", r->bfs_levels);\n\
  }\n\
  fprintf (out, \"</graphStatistics>\\n\");\n\
  /*  storage statistics  */\n\
#if defined (HASH_STORAGE) || defined (PD4_STORAGE)\n\
  storage_output_stats (r->storage, out);\n\
#endif\n\
  /*  others  */\n\
  fprintf (out, \"<otherStatistics>\\n\");\n\
#if defined(ALGO_DFS)\n\
  fprintf (out, \"<maxDfsStack>%llu</maxDfsStack>\\n\",\n\
	   r->max_unproc_size);\n\
#elif defined(ALGO_BFS) || defined(ALGO_FRONTIER) || defined(ALGO_PD4)\n\
  fprintf (out, \"<maxBfsQueue>%llu</maxBfsQueue>\\n\",\n\
	   r->max_unproc_size);\n\
#endif\n\
  fprintf (out, \"<maxMemoryUsed>%.1f</maxMemoryUsed>\\n\",\n\
	   r->max_mem_used);\n\
  fprintf (out, \"<eventsExecuted>%llu</eventsExecuted>\\n\",\n\
	   do_large_sum (r->events_executed, r->no_workers));\n\
#ifdef ALGO_PD4\n\
  fprintf (out, \"<eventsExecutedDDD>%llu</eventsExecutedDDD>\\n\",\n\
	   do_large_sum (r->events_executed_dd, r->no_workers));\n\
  fprintf (out, \"<eventsExecutedExpansion>%llu</eventsExecutedExpansion>\\n\",\n\
	   do_large_sum (r->events_executed, r->no_workers) -\n\
	   do_large_sum (r->events_executed_dd, r->no_workers));\n\
#endif\n\
#ifdef ALGO_RWALK\n\
  fprintf (out, \"<eventExecPerSecond>%d</eventExecPerSecond>\\n\",\n\
	   (unsigned int) (1.0 * visited / (r->exec_time / 1000000.0)));\n\
#endif\n\
  fprintf (out, \"</otherStatistics>\\n\");\n\
  fprintf (out, \"</statisticsReport>\\n\");\n\
\n\
  /***\n\
   *  trace report\n\
   ***/\n\
  if (r->result == FAILURE) {\n\
    fprintf (out, \"<traceReport>\\n\");\n\
#if    defined(TRACE_STATE)\n\
    fprintf (out, \"<traceState>\\n\");\n\
    state_to_xml (r->faulty_state, out);\n\
    fprintf (out, \"</traceState>\\n\");\n\
#elif defined(TRACE_FULL)\n\
    fprintf (out, \"<traceFull>\\n\");\n\
    report_output_trace (r, out);\n\
    fprintf (out, \"</traceFull>\\n\");\n\
#elif defined(TRACE_EVENTS)\n\
    fprintf (out, \"<traceEvents>\\n\");\n\
    report_output_trace (r, out);\n\
    fprintf (out, \"</traceEvents>\\n\");\n\
#endif\n\
    fprintf (out, \"</traceReport>\\n\");  \n\
  }\n\
  fprintf (out, \"</helenaReport>\\n\");\n\
  fclose (out);\n\
}\n\
\n\
void report_interruption_handler\n\
(int signal) {\n\
  glob_report->result = INTERRUPTION;\n\
  report_stop_search ();\n\
}\n\
\n\
bool_t report_error\n\
(char * msg) {\n\
  if (glob_report->result != ERROR) {\n\
    glob_report->result = ERROR;\n\
    if(!glob_report->error_msg) {\n\
      glob_report->error_msg =\n\
	mem_alloc (SYSTEM_HEAP, sizeof(char) * strlen(msg) + 1);\n\
      strcpy (glob_report->error_msg, msg);\n\
    }\n\
    glob_report->errors = 1;\n\
    glob_report->keep_searching = FALSE;\n\
  }\n\
  glob_report->keep_searching = FALSE;\n\
  return TRUE;\n\
}\n\
\n\
void report_stop_search\n\
() {\n\
  glob_report->keep_searching = FALSE;\n\
}\n\
\n\
void report_set_comp_time\n\
(report_t r,\n\
 float    comp_time) {\n\
  r->comp_time = comp_time;\n\
}\n\
\n\
void report_update_bfs_levels\n\
(report_t     r,\n\
 unsigned int bfs_levels) {\n\
  r->bfs_levels_ok = TRUE;\n\
  if (bfs_levels > r->bfs_levels) {\n\
    r->bfs_levels = bfs_levels;\n\
  }\n\
}\n\
\n\
void report_update_max_unproc_size\n\
(report_t         r,\n\
 large_unsigned_t max_unproc_size) {\n\
  if (max_unproc_size > r->max_unproc_size) \n\
    r->max_unproc_size = max_unproc_size;\n\
}\n\
\n\
void report_faulty_state\n\
(report_t r,\n\
 state_t  s) {\n\
  r->faulty_state = state_copy (s);\n\
  r->keep_searching = FALSE;\n\
  r->result = FAILURE;\n\
  r->faulty_state_found = TRUE;\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "simulator.h", "w")
    f.write ("\
#ifndef LIB_SIMULATOR\n\
#define LIB_SIMULATOR\n\
\n\
#include \"includes.h\"\n\
#include \"common.h\"\n\
#include \"model.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
void simulator\n\
();\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "simulator.c", "w")
    f.write ("\
#include \"simulator.h\"\n\
\n\
bool_t check_error () {\n\
  if (!glob_error_msg) {\n\
    return TRUE;\n\
  } else {\n\
    printf (\"model error: %s\\n\", glob_error_msg);\n\
    flush_error ();\n\
    return FALSE;\n\
  }\n\
}\n\
\n\
void simulator () {\n\
  unsigned int i;\n\
  bool_t loop = TRUE;\n\
  char * cmd = NULL;\n\
  int top = 0;\n\
  mevent_set_t en;\n\
  mstate_t stack[65536], succ;\n\
  unsigned int stack_evt[65536];\n\
  mevent_t e;\n\
  size_t n;\n\
  char prop[65536];\n\
  \n\
  stack[0] = mstate_initial ();\n\
  while (loop) {\n\
    printf (\"# \");\n\
    fflush (stdout);\n\
    n = getline (&cmd, &n, stdin);\n\
    if (n == -1) {\n\
      printf (\"\\n\");\n\
      continue;\n\
    }\n\
    cmd[n - 1] = '\\0';\n\
    if (!strcmp (cmd, \"show\")) {\n\
      mstate_print (stack[top], stdout);\n\
    } else if (!strcmp (cmd, \"stack\")) {\n\
      mstate_t now = mstate_initial ();\n\
      for (i = 0; i < top; i ++) {\n\
	en = mstate_enabled_events (now);\n\
	e = mevent_set_nth (en, stack_evt[i] - 1);\n\
	mevent_print (e, stdout);\n\
	mevent_exec (e, now);\n\
	mevent_set_free (en);\n\
      }\n\
      mstate_free (now);\n\
    } else if (!strncmp (cmd, \"eval \", 5)) {\n\
      sscanf (cmd, \"eval %s\", &prop[0]);\n\
      if (!model_is_state_proposition(prop)) {\n\
	printf (\"error: %s is not a proposition of the model\\n\", prop);\n\
      } else {\n\
	printf (\"evaluation of proposition %s: \", prop);\n\
	if (model_check_state_proposition (prop, stack[top])) {\n\
	  printf (\"true\\n\");\n\
	} else {\n\
	  printf (\"false\\n\");\n\
	}\n\
      }\n\
    } else if (!strncmp (cmd, \"push \", 5)) {\n\
      sscanf (cmd, \"push %d\", &i);\n\
      en = mstate_enabled_events (stack[top]);\n\
      if (check_error ()) {\n\
	if (i < 1 || i > mevent_set_size (en)) {\n\
	  printf (\"error: state has %d enabled event(s)\\n\",\n\
		  mevent_set_size (en));\n\
	} else {\n\
	  e = mevent_set_nth (en, i - 1);\n\
	  succ = mstate_succ (stack[top], e);\n\
	  if (check_error ()) {\n\
	    stack_evt[top] = i;\n\
	    top ++;\n\
	    stack[top] = succ;\n\
	  } else {\n\
	    mstate_free (succ);\n\
	  }\n\
	}\n\
      }\n\
      mevent_set_free (en);\n\
    } else if (!strcmp (cmd, \"pop\")) {\n\
      if (0 == top) {\n\
	printf (\"error: stack is empty\\n\");\n\
      } else {\n\
	mstate_free (stack[top]);\n\
	top --;\n\
      }\n\
    } else if (!strcmp (cmd, \"enabled\")) {\n\
      en = mstate_enabled_events (stack[top]);\n\
      if (check_error ()) {\n\
	for (i = 0; i < mevent_set_size (en); i ++) {\n\
	  printf (\"%3d: \", i + 1);\n\
	  mevent_print (mevent_set_nth (en, i), stdout);\n\
	}\n\
      }\n\
      mevent_set_free (en);\n\
    } else if (!strcmp (cmd, \"help\")) {\n\
      printf (\"\\\n\
show    -> show the current state (the one on top of the stack)\\n\\\n\
stack   -> show the stack of executed events\\n\\\n\
enabled -> show enabled events of the current state\\n\\\n\
pop     -> pop the state on top of the stack\\n\\\n\
push N  -> push the Nth successor of the current state on the stack\\n\\\n\
eval P  -> evaluate proposition on the current state\\n\\\n\
help\\n\\\n\
quit\\n\");\n\
    } else if (!strcmp (cmd, \"quit\")) {\n\
      loop = FALSE;\n\
    } else if (cmd[0] != '\\0') {\n\
      printf (\"error: unrecognized command: %s\\n\", cmd);\n\
    }\n\
    free (cmd);\n\
    cmd = NULL;\n\
  }\n\
  for (; top >= 0; top --) {\n\
    mstate_free (stack[top]);\n\
  }\n\
}\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "state.h", "w")
    f.write ("\
#ifndef LIB_STATE\n\
#define LIB_STATE\n\
\n\
#include \"model.h\"\n\
#include \"heap.h\"\n\
#include \"prop.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
#ifdef ACTION_CHECK_LTL\n\
\n\
\n\
\n\
/*\n\
 *  state definition when doing LTL model checking\n\
 */\n\
\n\
#include \"buchi.h\"\n\
\n\
typedef struct {\n\
  mstate_t m;  /*  state of the model  */\n\
  bstate_t b;  /*  state of the buchi automaton  */\n\
  heap_t heap;\n\
} struct_state_t;\n\
typedef struct_state_t * state_t;\n\
\n\
bool_t state_equal\n\
(state_t s,\n\
 state_t t);\n\
\n\
bool_t state_accepting\n\
(state_t s);\n\
\n\
state_t state_initial\n\
();\n\
\n\
void state_free\n\
(state_t s);\n\
\n\
hash_key_t state_hash\n\
(state_t s);\n\
\n\
state_t state_copy\n\
(state_t s);\n\
\n\
void state_print\n\
(state_t s,\n\
 FILE *  out);\n\
\n\
void state_to_xml\n\
(state_t s,\n\
 FILE *  out);\n\
\n\
void state_serialise\n\
(state_t s,\n\
 bit_vector_t v);\n\
\n\
state_t state_unserialise\n\
(bit_vector_t v);\n\
\n\
bool_t state_cmp_vector\n\
(state_t s,\n\
 bit_vector_t v);\n\
\n\
unsigned int state_char_width\n\
(state_t s);\n\
\n\
state_t state_initial_mem\n\
(heap_t heap);\n\
\n\
state_t state_copy_mem\n\
(state_t s,\n\
 heap_t heap);\n\
\n\
state_t state_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap);\n\
\n\
#else\n\
\n\
\n\
\n\
/*\n\
 *  state definition when not doing LTL model checking\n\
 */\n\
\n\
typedef mstate_t state_t;\n\
#define state_initial mstate_initial\n\
#define state_equal mstate_equal\n\
#define state_free mstate_free\n\
#define state_hash mstate_hash\n\
#define state_copy mstate_copy\n\
#define state_print mstate_print\n\
#define state_to_xml mstate_to_xml\n\
#define state_serialise mstate_serialise\n\
#define state_unserialise mstate_unserialise\n\
#define state_char_width mstate_char_width\n\
#define state_cmp_vector mstate_cmp_vector\n\
\n\
#ifdef USE_HELENA_HEAPS\n\
#define state_initial_mem mstate_initial_mem\n\
#define state_copy_mem mstate_copy_mem\n\
#define state_unserialise_mem mstate_unserialise_mem\n\
#else\n\
#define state_initial_mem(heap) mstate_initial ()\n\
#define state_copy_mem(s, heap) mstate_copy (s)\n\
#define state_unserialise_mem(v, heap) mstate_unserialise(v)\n\
#endif\n\
\n\
#endif\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "state.c", "w")
    f.write ("\
#include \"state.h\"\n\
\n\
#ifdef ACTION_CHECK_LTL\n\
\n\
state_t state_initial_mem\n\
(heap_t heap) {\n\
  state_t result;\n\
  result = mem_alloc (heap, sizeof (struct_state_t));\n\
  result->m = mstate_initial_mem (heap);\n\
  result->b = bstate_initial ();\n\
  result->heap = heap;\n\
  return result;\n\
}\n\
\n\
state_t state_initial\n\
() {\n\
  return state_initial_mem (SYSTEM_HEAP);\n\
}\n\
\n\
bool_t state_equal\n\
(state_t s,\n\
 state_t t) {\n\
  return mstate_equal (s->m, t->m) && (s->b == t->b);\n\
}\n\
\n\
bool_t state_accepting\n\
(state_t s) {\n\
  return bstate_accepting (s->b);\n\
}\n\
\n\
void state_free\n\
(state_t s) {\n\
  mstate_free (s->m);\n\
  mem_free (s->heap, s);\n\
}\n\
\n\
hash_key_t state_hash\n\
(state_t s) {\n\
  return mstate_hash (s->m) + s->b;\n\
}\n\
\n\
state_t state_copy_mem\n\
(state_t s,\n\
 heap_t heap) {\n\
  state_t result;\n\
  result = mem_alloc (heap, sizeof (struct_state_t));\n\
  result->m = mstate_copy_mem (s->m, heap);\n\
  result->b = s->b;\n\
  result->heap = heap;\n\
  return result;\n\
}\n\
\n\
state_t state_copy\n\
(state_t s) {\n\
  return state_copy_mem (s, SYSTEM_HEAP);\n\
}\n\
\n\
void state_print\n\
(state_t s,\n\
 FILE *  out) {\n\
  mstate_print (s->m, out);\n\
}\n\
\n\
void state_to_xml\n\
(state_t s,\n\
 FILE *  out) {\n\
  mstate_to_xml (s->m, out);\n\
}\n\
\n\
void state_serialise\n\
(state_t s,\n\
 bit_vector_t v) {\n\
  unsigned int bsize = bstate_char_width ();\n\
  memcpy (v, &(s->b), bsize);\n\
  mstate_serialise (s->m, v + bsize);\n\
}\n\
\n\
state_t state_unserialise_mem\n\
(bit_vector_t v,\n\
 heap_t heap) {\n\
  unsigned int bsize = bstate_char_width ();\n\
  state_t result = mem_alloc (heap, sizeof (struct_state_t)); \n\
  result->b = 0;\n\
  memcpy (&(result->b), v, bsize);\n\
  result->m = mstate_unserialise (v + bsize);\n\
  result->heap = heap;\n\
  return result;\n\
}\n\
\n\
state_t state_unserialise\n\
(bit_vector_t v) {\n\
  return state_unserialise_mem (v, SYSTEM_HEAP);\n\
}\n\
\n\
bool_t state_cmp_vector\n\
(state_t s,\n\
 bit_vector_t v) {\n\
  bstate_t b = 0;\n\
  unsigned int bsize = bstate_char_width ();\n\
  memcpy (&b, v, bsize);\n\
  if (s->b != b) {\n\
    return FALSE;\n\
  }\n\
  return mstate_cmp_vector (s->m, v + bsize);\n\
}\n\
\n\
unsigned int state_char_width\n\
(state_t s) {\n\
  return bstate_char_width () + mstate_char_width (s->m);\n\
}\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "storage.h", "w")
    f.write ("\
#ifndef LIB_STORAGE\n\
#define LIB_STORAGE\n\
\n\
#include \"hash_storage.h\"\n\
#include \"pd4.h\"\n\
\n\
#ifndef MODEL_CONFIG\n\
#error Model configuration missing!\n\
#endif\n\
\n\
\n\
/*****\n\
 *  storage used by delta-ddd algorithm\n\
 *****/\n\
#if defined (PD4_STORAGE)\n\
\n\
typedef pd4_storage_t storage_t;\n\
typedef pd4_storage_id_t storage_id_t;\n\
typedef void * storage_state_attr_t;\n\
\n\
#define init_storage           init_pd4_storage\n\
#define free_storage           free_pd4_storage\n\
#define storage_id_serialise   pd4_storage_id_serialise\n\
#define storage_id_unserialise pd4_storage_id_unserialise\n\
#define storage_id_char_width  pd4_storage_id_char_width\n\
#define storage_new            pd4_storage_new\n\
#define storage_free           pd4_storage_free\n\
#define storage_size           pd4_storage_size\n\
#define storage_insert         pd4_storage_insert\n\
#define storage_remove         pd4_storage_remove\n\
#define storage_id_cmp         pd4_storage_id_cmp\n\
#define storage_get            pd4_storage_get\n\
#define storage_get_mem        pd4_storage_get_mem\n\
#define storage_set_in_unproc  pd4_storage_set_in_unproc\n\
#define storage_get_in_unproc  pd4_storage_get_in_unproc\n\
#define storage_get_num        pd4_storage_get_num\n\
#define storage_set_is_red     pd4_storage_set_is_red\n\
#define storage_update_refs    pd4_storage_update_refs\n\
#define storage_get_attr       pd4_storage_get_attr\n\
#define storage_output_stats   pd4_storage_output_stats\n\
\n\
\n\
/*****\n\
 *  hash table storage is the default storage\n\
 *****/\n\
#else\n\
\n\
typedef hash_storage_t storage_t;\n\
typedef hash_storage_id_t storage_id_t;\n\
typedef hash_storage_state_attr_t storage_state_attr_t;\n\
\n\
#define init_storage           init_hash_storage\n\
#define free_storage           free_hash_storage\n\
#define storage_id_serialise   hash_storage_id_serialise\n\
#define storage_id_unserialise hash_storage_id_unserialise\n\
#define storage_id_char_width  hash_storage_id_char_width\n\
#define storage_new            hash_storage_default_new\n\
#define storage_free           hash_storage_free\n\
#define storage_size           hash_storage_size\n\
#define storage_insert         hash_storage_insert\n\
#define storage_remove         hash_storage_remove\n\
#define storage_id_cmp         hash_storage_id_cmp\n\
#define storage_get            hash_storage_get\n\
#define storage_get_mem        hash_storage_get_mem\n\
#define storage_set_in_unproc  hash_storage_set_in_unproc\n\
#define storage_get_in_unproc  hash_storage_get_in_unproc\n\
#define storage_get_num        hash_storage_get_num\n\
#define storage_set_is_red     hash_storage_set_is_red\n\
#define storage_update_refs    hash_storage_update_refs\n\
#define storage_get_attr       hash_storage_get_attr\n\
#define storage_output_stats   hash_storage_output_stats\n\
\n\
#endif\n\
\n\
#endif\n\
"    )
    f.close ()
    ############################################################
    f = open (dir + "/" + "storage.c", "w")
    f.write ("\
"    )
    f.close ()



if (len (sys.argv) != 2):
    print ("usage: helena-generate-checker directory")
    exit (1)
else:
    genFiles (sys.argv[1])
    exit (0)
