Exemplo n.º 1
0
CAESAR_TYPE_STRING CAESAR_GATE_LABEL(CAESAR_TYPE_LABEL l) {
	static char *s = NULL;  /* start of string */
	static char *b = NULL; /*beyond*/
	char *p = NULL;  /* current insertion point */
	int u, n; /* used, needed */
	unsigned int i; /*unsigned to avoid warning in comparsison to c.len*/
	chunk c;
	
	if (edge_labels==1) {
		c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,0),l->label[0]);
		i = 0;
		while(i < c.len && strchr(" \t(),.:!?;[]{}",c.data[i])==0)
			i++;
		p = s;
		n = i;
		if (b-p < n) { 
			u = p-s;
			s = RTrealloc(s, u+n);
			p = s+u;
			b = s + u+n;
		}
		strncpy(s, c.data, i);
		if (i > 0) s[i-1] = '\0'; else s[0] = '\0';
		return s;
	} else
		return "gate";
}
Exemplo n.º 2
0
lts_file_t aut_file_create(const char* name,lts_type_t ltstype,int segments,lts_file_t settings){
    if (lts_type_get_state_length(ltstype)) {
        //Abort("cannot write state to AUT file");
        Print(infoShort,"Ignoring state vector");
    }
    if (lts_type_get_state_label_count(ltstype)) {
        Abort("cannot write state labels to AUT file");
    }
    if (lts_type_get_edge_label_count(ltstype)!=1) {
        Abort("AUT files contain precisely one edge label");
    }
    if (segments!=1) Abort("AUT files contain precisely 1 segment");
    lts_file_t file=lts_file_bare(name,ltstype,1,settings,sizeof(struct lts_file_s));
    file->f=fopen(name,"w");
    if(file->f==NULL){
        AbortCall("while opening %s",name);
    }
    file->root--; // set to -1 denoting undefined.
    file->states++; // set to 1, denoting one state.
    file->type_no=lts_type_get_edge_label_typeno(ltstype,0);
    lts_file_set_write_init(file,aut_write_init);
    lts_file_set_write_state(file,write_state);
    lts_file_set_write_edge(file,aut_write_edge);
    lts_file_set_close(file,aut_write_close);
    fprintf(file->f,"des(?,?,?)                                                     \n");
    lts_file_complete(file);
    return file;
}
Exemplo n.º 3
0
void lts_type_serialize(lts_type_t t,stream_t ds){
	DSwriteS(ds,"lts signature 1.1");
	uint32_t N=lts_type_get_state_length(t);
	Warning(debug,"state length is %d",N);
	DSwriteU32(ds,N);
	for(uint32_t i=0;i<N;i++){
		char*x=lts_type_get_state_name(t,i);
		if (x) DSwriteS(ds,x); else DSwriteS(ds,"");
		DSwriteU32(ds,lts_type_get_state_typeno(t,i));
	}
	N=lts_type_get_state_label_count(t);
	Warning(debug,"%d state labels",N);
	DSwriteU32(ds,N);
	for(uint32_t i=0;i<N;i++){
		char*x=lts_type_get_state_label_name(t,i);
		if (x) DSwriteS(ds,x); else DSwriteS(ds,"");
		DSwriteU32(ds,lts_type_get_state_label_typeno(t,i));
	}
	N=lts_type_get_edge_label_count(t);
	Warning(debug,"%d edge labels",N);
	DSwriteU32(ds,N);
	for(uint32_t i=0;i<N;i++){
		char*x=lts_type_get_edge_label_name(t,i);
		if (x) DSwriteS(ds,x); else DSwriteS(ds,"");
		DSwriteU32(ds,lts_type_get_edge_label_typeno(t,i));
		Warning(debug,"edge label %d is %s : %s",i,x,lts_type_get_edge_label_type(t,i));
	}
	N=lts_type_get_type_count(t);
	Warning(debug,"%d types",N);
	DSwriteU32(ds,N);
	for(uint32_t i=0;i<N;i++){
		DSwriteS(ds,lts_type_get_type(t,i));
		DSwriteS(ds,(char*)data_format_string(t,i));
	}
}
Exemplo n.º 4
0
CAESAR_TYPE_BOOLEAN CAESAR_VISIBLE_LABEL(CAESAR_TYPE_LABEL x) {
	CAESAR_TYPE_BOOLEAN vis = CAESAR_TRUE;
	if (edge_labels==1) {
		chunk c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,0),x->label[0]);
		if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0)
			vis =CAESAR_FALSE;
	}
	return vis;
}
Exemplo n.º 5
0
static char *
str_group (check_ctx_t *ctx, int group)
{
    model_t         model = ctx->parent;
    lts_type_t      ltstype = GBgetLTStype (model);
    int             label = lts_type_find_edge_label (ltstype, LTSMIN_EDGE_TYPE_STATEMENT);
    if (label) return "NULL";
    int             type = lts_type_get_edge_label_typeno (ltstype, label);
    int             count = pins_chunk_count  (model, type);
    if (count < ctx->K) return "NULL";
    chunk           c = pins_chunk_get (model, type, group);
    return c.data;
}
Exemplo n.º 6
0
static void torx_transition(void*arg,int*lbl,int*dst){

	torx_struct_t *context=(torx_struct_t*)arg;

	int tmp=TreeFold(dbs,dst);
	chunk c=GBchunkGet(context->model,lts_type_get_edge_label_typeno(context->ltstype,0),lbl[0]);
	
	int vis = 1;
	if (c.len==3 && strncmp(c.data, "tau", c.len)==0)
		vis =0;

	/* tab-separated fields: edge vis sat lbl pred vars state */
	fprintf(stdout, "Ee\t\t%d\t1\t%*s\t\t\t%d\n", vis, c.len, c.data, tmp);
}
Exemplo n.º 7
0
lts_file_t aut_file_open(const char* name){
    lts_type_t ltstype=single_action_type();
    lts_file_t file=lts_file_bare(name,ltstype,1,NULL,sizeof(struct lts_file_s));
    file->type_no=lts_type_get_edge_label_typeno(ltstype,0);
    lts_file_set_read_init(file,aut_read_init);
    lts_file_set_read_edge(file,aut_read_edge);
    lts_file_set_close(file,aut_read_close);
    lts_file_complete(file);
    file->f=fopen(name,"r");
    if(file->f==NULL){
        AbortCall("while opening %s",name);
    }
    int matches;
    matches = fscanf(file->f,"des%*[^(]s");
    if (matches != 0) Abort("while parsing %s",name);
    matches = fscanf(file->f,"(%llu,%llu,%llu)\n",&file->root,&file->trans,&file->states);
    if (matches != 3) Abort("while parsing %s",name);
    Print(infoLong,"file %s contains %llu states and %llu transitions",
         name,file->states,file->trans);
    return file;
}
Exemplo n.º 8
0
static inline void
print_ti (check_ctx_t *ctx, transition_info_t *ti)
{
    if (ti == NULL || ti->labels == NULL) return;
    model_t         model = ctx->parent;
    lts_type_t      ltstype = GBgetLTStype (model);
    int             Max = 4096;
    char           *tmp = RTmalloc (Max);
    int             l;
    for (int i = 0; i < ctx->L; i++) {
        char           *name = lts_type_get_edge_label_name (ltstype, i);
        char           *type = lts_type_get_edge_label_type (ltstype, i);
        int             typeno = lts_type_get_edge_label_typeno (ltstype, i);

        char           *res = tmp;
        l  = snprintf (res, Max, " --> %s : %s = ", name, type);
        l += print_chunk (model, res+l, Max-l, typeno, ti->labels[i]);
        Printf (lerror, "%s\n", res);
    }
    RTfree (tmp);
}
Exemplo n.º 9
0
static void lts_write_dir(archive_t archive,string_map_t map,lts_t lts,int segments){
    if (map) arch_set_write_policy(archive,map);
    dir_info_t info=DIRinfoCreate(segments);
    int i,j;
    uint32_t k;
    char filename[1024];
    stream_t output;
    stream_t *src_out;
    stream_t *lbl_out;
    stream_t *dst_out;

    if (lts->root_count !=1) Abort("LTS has %u initial states DIR requires 1",lts->root_count);
    lts_set_type(lts,LTS_BLOCK);
    info->label_tau=lts->tau;
    int type_no=lts_type_get_edge_label_typeno(lts->ltstype,0);
    switch(lts_type_get_format(lts->ltstype,type_no)){
        case LTStypeChunk:
        case LTStypeEnum:
            break;
        default:
            Abort("DIR is limited to Chunk/Enum edge labels.");
    }
    info->label_count=VTgetCount(lts->values[type_no]);
    info->initial_seg=lts->root_list[0]%segments;
    info->initial_ofs=lts->root_list[0]/segments;
    output=arch_write(archive,"TermDB");
    int last_idx = 0;
    table_iterator_t it = VTiterator (lts->values[type_no]);
    while (IThasNext(it)) {
        chunk label_c = ITnext (it);
        int idx = VTputChunk (lts->values[type_no], label_c);
        while (last_idx < idx) { // fill non-dense indices
            write_chunk (output, (chunk){0, ""});
            last_idx++;
        }
        write_chunk (output, label_c);
    }
    DSclose(&output);
    src_out=(stream_t*)RTmalloc(segments*sizeof(stream_t));
    lbl_out=(stream_t*)RTmalloc(segments*sizeof(stream_t));
    dst_out=(stream_t*)RTmalloc(segments*sizeof(stream_t));
    for(i=0;i<segments;i++) {
        for(j=0;j<segments;j++) {
            sprintf(filename,"src-%d-%d",i,j);
            src_out[j]=arch_write(archive,filename);
            sprintf(filename,"label-%d-%d",i,j);
            lbl_out[j]=arch_write(archive,filename);
            sprintf(filename,"dest-%d-%d",i,j);
            dst_out[j]=arch_write(archive,filename);
        }
        for(j=i;j<(int)lts->states;j+=segments){
            for(k=lts->begin[j];k<lts->begin[j+1];k++){
                int dseg=(lts->dest[k])%segments;
                info->transition_count[i][dseg]++;
                DSwriteU32(src_out[dseg],info->state_count[i]);
                DSwriteU32(lbl_out[dseg],lts->label[k]);
                DSwriteU32(dst_out[dseg],(lts->dest[k])/segments);
            }
            info->state_count[i]++;
        }
        for(j=0;j<segments;j++) {
            DSclose(&src_out[j]);
            DSclose(&lbl_out[j]);
            DSclose(&dst_out[j]);
        }
    }
    info->info="bsim2 output";
    output=arch_write(archive,"info");
    DIRinfoWrite(output,info);
    DSclose(&output);
    info->info=NULL;
    DIRinfoDestroy(info);
}
Exemplo n.º 10
0
static void lts_read_dir(archive_t archive,lts_t lts){
    Print(infoShort,"opening info");
    stream_t input=arch_read(archive,"info");
    dir_info_t info=DIRinfoRead(input,1);
    DSclose(&input);
    int segments=info->segment_count;
    Print(infoShort,"got info for %d segments",segments);
    int offset[segments];
    offset[0]=0;
    for(int i=1;i<segments;i++){
        offset[i]=info->state_count[i-1]+offset[i-1];
    }
    int s_count=0;
    int t_count=0;
    for(int i=0;i<segments;i++){
        s_count+=info->state_count[i];
        for(int j=0;j<segments;j++){
            t_count+=info->transition_count[i][j];
        }
    }
    Print(infoShort,"counted %u states and %u transitions",s_count,t_count);
    lts_set_sig(lts,single_action_type());
    lts_set_type(lts,LTS_LIST);
    lts_set_size(lts,1,s_count,t_count);
    lts->root_list[0]=offset[info->initial_seg]+info->initial_ofs;
    lts->tau=info->label_tau;
    Print(infoShort,"getting %d labels from TermDB",info->label_count);
    input=arch_read(archive,"TermDB");
    int type_no=lts_type_get_edge_label_typeno(lts->ltstype,0);
    for(int i=0;i<info->label_count;i++){
        char *line=DSreadLN(input);
        int len=strlen(line);
        char data[len];
        chunk tmp_chunk=chunk_ld(len,data);
        string2chunk(line,&tmp_chunk);
        VTputAtChunk(lts->values[type_no], tmp_chunk, i);
    }
    DSclose(&input);
    Print(infoShort,"got labels");
    int t_offset=0;
    char filename[1024];
    for(int i=0;i<segments;i++){
        for(int j=0;j<segments;j++){
            sprintf(filename,"src-%d-%d",i,j);
            stream_t src=arch_read(archive,filename);
            sprintf(filename,"label-%d-%d",i,j);
            stream_t lbl=arch_read(archive,filename);
            sprintf(filename,"dest-%d-%d",i,j);
            stream_t dst=arch_read(archive,filename);
            for(int k=0;k<info->transition_count[i][j];k++){
                lts->src[t_offset]=offset[i]+DSreadU32(src);
                lts->label[t_offset]=DSreadU32(lbl);
                lts->dest[t_offset]=offset[j]+DSreadU32(dst);
                t_offset++;
            }
            DSclose(&src);
            DSclose(&lbl);
            DSclose(&dst);
        }
    }
    DIRinfoDestroy(info);
}
Exemplo n.º 11
0
CAESAR_TYPE_STRING CAESAR_STRING_LABEL(CAESAR_TYPE_LABEL l) {
	static char *s = NULL;  /* start of string */
	static char *b = NULL; /*beyond*/
	static char *tau = "i";
	char *p = NULL;  /* current insertion point */
	int u, n; /* used, needed */
	int i;
	chunk c;
	size_t clen;
	
	p = s;
	n = 5;
	if (b-p < n) { 
		u = p-s;
		s = RTrealloc(s, u+n);/* TODO: check s!=0 */
		p = s+u;
		b = s + u+n;
	}
    if (edge_labels > 0 && l->label[0]<0){
        n = 6;
        if (b-p < n) { 
            u = p-s;
            s = RTrealloc(s, u+n); /* TODO: check s!=0 */
            p = s+u;
            b = s + u+n;
        }
        sprintf(p, "delta");
        p+=strlen(p);
    } else {
        if (edge_labels > 1 || edge_encode) {
                sprintf(p, "|");
                p += strlen(p);
        }
        for(i=0; i < edge_labels; i++) {
            char *name=lts_type_get_edge_label_name(ltstype,i);
            c=GBchunkGet(model,lts_type_get_edge_label_typeno(ltstype,i),l->label[i]);
            if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0)
                clen=strlen(tau);
            else
                clen=c.len*2+6;
            n = strlen(name)+ 1 + clen+1+1+1; /* for name , '=' , c, ';',  '>', '\0' */
            if (b-p < n) { 
                u = p-s;
                s = RTrealloc(s, u+n); /* TODO: check s!=0 */
                p = s+u;
                b = s + u+n;
            }
            if (i>0) {
                sprintf(p, "|");
                p += strlen(p);
            }
            if (edge_labels > 1 || edge_encode ) {
                sprintf(p, "%s=",name);
                p += strlen(p);
            }
            if (c.len==3 && strncmp(c.data, LTSMIN_EDGE_VALUE_TAU, c.len)==0)
                sprintf(p, "%s", tau);
            else
                chunk2string(c,b-p,p);
            p += strlen(p);
        }
    }
    if (edge_labels > 1 || edge_encode ) {
        sprintf(p, "|");
        p += strlen(p);
    }
    if (edge_encode){
        int ofs=edge_labels;
        /*
        for(i=0;i<N;i++){
            char*name=lts_type_get_state_name(ltstype,i);
            c=GBchunkGet(model,lts_type_get_state_typeno(ltstype,i),l->label[ofs+i]);
            n=strlen(name)+c.len*2+7;
            if (b-p < n) { 
                u = p-s;
                s = realloc(s, u+n); // TODO: check s!=0
                p = s+u;
                b = s + u+n;
            }
            sprintf(p, "%s=",name);
            p+=strlen(p);
            chunk2string(c,b-p,p);
            p+=strlen(p);
            sprintf(p, "|");
            p +=strlen(p);
        }
        */
        ofs+=N;
        for(i=0;i<state_labels;i++){
            char*name=lts_type_get_state_label_name(ltstype,i);
            c=GBchunkGet(model,lts_type_get_state_label_typeno(ltstype,i),l->label[ofs+i]);
            n=strlen(name)+c.len*2+7;
            if (b-p < n) { 
                u = p-s;
                s = RTrealloc(s, u+n); /* TODO: check s!=0 */
                p = s+u;
                b = s + u+n;
            }
            sprintf(p, "%s=",name);
            p+=strlen(p);
            chunk2string(c,b-p,p);
            p+=strlen(p);
            sprintf(p, "|");
            p +=strlen(p);
       }
    }
    return s;
}
Exemplo n.º 12
0
static void write_close(lts_file_t file){
    //if (file->init_count!=1) Abort("missing initial state"); in some cases no initial states makes sense!
    uint32_t pre_sum=0;
    for(int i=0;i<file->segments;i++) pre_sum+=file->state_perseg[i];
    uint32_t tmp;
    for (int i=0;i<file->segments;i++){
        tmp=lts_get_max_src_p1(file,i);
        if (tmp>file->state_perseg[i]) file->state_perseg[i]=tmp;
        tmp=lts_get_max_dst_p1(file,i);
        if (tmp>file->state_perseg[i]) file->state_perseg[i]=tmp;
    }
    file->state_count=0;
    for(int i=0;i<file->segments;i++) file->state_count+=file->state_perseg[i];
    if (pre_sum && pre_sum!=file->state_count) {
        Abort("edges use unwritten states");
    }
    uint32_t offset[file->segments];
    offset[0]=0;
    for(int i=1;i<file->segments;i++) offset[i]=offset[i-1]+file->state_perseg[i-1];
    uint32_t seg,ofs;
    for(uint32_t i=0;i<file->lts->root_count;i++){
        seg=file->lts->root_list[i]%file->segments;
        ofs=file->lts->root_list[i]/file->segments;
        file->lts->root_list[i]=offset[seg]+ofs;
    }
    for(uint32_t i=0;i<file->edge_count;i++){
        seg=file->lts->src[i]%file->segments;
        ofs=file->lts->src[i]/file->segments;
        file->lts->src[i]=offset[seg]+ofs;
        seg=file->lts->dest[i]%file->segments;
        ofs=file->lts->dest[i]/file->segments;
        file->lts->dest[i]=offset[seg]+ofs;
    }
    if (file->lts->properties){
        uint32_t* temp=file->lts->properties;
        file->lts->properties=(uint32_t*)RTmalloc(file->state_count*sizeof(uint32_t));
        for(int i=0;i<file->segments;i++){
            for(uint32_t j=0;j<file->state_perseg[i];j++){
                file->lts->properties[offset[i]+j]=temp[j*file->segments+i];
            }
        }
        RTfree(temp);
    }
    lts_set_size(file->lts,file->init_count,file->state_count,file->edge_count);
    file->lts->tau=-1;
    if (lts_type_get_edge_label_count(file->lts->ltstype)==1 &&
        strncmp(lts_type_get_edge_label_name(file->lts->ltstype,0),LTSMIN_EDGE_TYPE_ACTION_PREFIX,6)==0)
    {
        Print(infoShort,"action labeled, detecting silent step");
        int tableno=lts_type_get_edge_label_typeno(file->lts->ltstype,0);
        value_table_t vt=file->lts->values[tableno];
        int N=VTgetCount(vt);
        for(int i=0;i<N;i++){
            chunk c=VTgetChunk(vt,i);
            if ( (c.len==strlen(LTSMIN_EDGE_VALUE_TAU) && strcmp(c.data,LTSMIN_EDGE_VALUE_TAU)==0)
              || (c.len==1 && strcmp(c.data,"i")==0)
               )
            {
                Print(infoShort,"invisible label is %s",c.data);
                if (file->lts->tau>=0) Abort("two silent labels");
                file->lts->tau=i;
            }
        }
        if (file->lts->tau<0) {
            Print(infoShort,"no silent label");
        }
    }
}
Exemplo n.º 13
0
static void actual_main(void *arg)
#endif
{
    int argc = ((struct args_t*)arg)->argc;
    char **argv = ((struct args_t*)arg)->argv;

    /* initialize HRE */
    HREinitBegin(argv[0]);
    HREaddOptions(options,"Perform a symbolic reachability analysis of <model>\n"
                  "The optional output of this analysis is an ETF "
                      "representation of the input\n\nOptions");
    lts_lib_setup(); // add options for LTS library
    HREinitStart(&argc,&argv,1,2,files,"<model> [<etf>]");

    /* initialize HRE on other workers */
    init_hre(HREglobal());

    /* check for unsupported options */
    if (PINS_POR != PINS_POR_NONE) Abort("Partial-order reduction and symbolic model checking are not compatible.");
    if (inhibit_matrix != NULL && sat_strategy != NO_SAT) Abort("Maximal progress is incompatibale with saturation.");
    if (files[1] != NULL) {
        char *ext = strrchr(files[1], '.');
        if (ext == NULL || ext == files[1]) {
            Abort("Output filename has no extension!");
        }
        if (strcasecmp(ext, ".etf") != 0) {
            // not ETF
            if (!(vset_default_domain == VSET_Sylvan && strcasecmp(ext, ".bdd") == 0) &&
                !(vset_default_domain == VSET_LDDmc  && strcasecmp(ext, ".ldd") == 0)) {
                Abort("Only supported output formats are ETF, BDD (with --vset=sylvan) and LDD (with --vset=lddmc)");
            }
            if (PINS_USE_GUARDS) {
                Abort("Exporting symbolic state space not comptabile with "
                        "guard-splitting");
            }
        }
    }

#ifdef HAVE_SYLVAN
    if (!USE_PARALLELISM) {
        if (strategy == PAR_P) {
            strategy = BFS_P;
            Print(info, "Front-end not thread-safe; using --order=bfs-prev instead of --order=par-prev.");
        } else if (strategy == PAR) {
            strategy = BFS;
            Print(info, "Front-end not thread-safe; using --order=bfs instead of --order=par.");
        }
    }
#endif

    /* turn off Lace for now to speed up while not using parallelism */
    lace_suspend();

    /* initialize the model and PINS wrappers */
    init_model(files[0]);

    /* initialize action detection */
    act_label = lts_type_find_edge_label_prefix (ltstype, LTSMIN_EDGE_TYPE_ACTION_PREFIX);
    if (act_label != -1) action_typeno = lts_type_get_edge_label_typeno(ltstype, act_label);
    if (act_detect != NULL) init_action_detection();

    bitvector_create(&state_label_used, sLbls);
    if (inv_detect != NULL) init_invariant_detection();
    else if (PINS_USE_GUARDS) {
        for (int i = 0; i < nGuards; i++) {
            bitvector_set(&state_label_used, i);
        }
    }

    init_maxsum(ltstype);

    /* turn on Lace again (for Sylvan) */
    if (vset_default_domain==VSET_Sylvan || vset_default_domain==VSET_LDDmc) {
        lace_resume();
    }

    if (next_union) vset_next_fn = vset_next_union_src;

    init_domain(VSET_IMPL_AUTOSELECT);

    vset_t initial = vset_create(domain, -1, NULL);
    int *src = RTmalloc (sizeof(int[N]));
    GBgetInitialState(model, src);
    vset_add(initial, src);

    Print(infoShort, "got initial state");

    /* if writing .dot files, open directory first */
    if (dot_dir != NULL) {
        DIR* dir = opendir(dot_dir);
        if (dir) {
            closedir(dir);
        } else if (ENOENT == errno) {
            Abort("Option 'dot-dir': directory '%s' does not exist", dot_dir);
        } else {
            Abort("Option 'dot-dir': failed opening directory '%s'", dot_dir);
        }
    }

    if (vset_dir != NULL) {
        DIR *dir = opendir(vset_dir);
        if (dir) {
            closedir(dir);
        } else if (errno == ENOENT) {
            Abort("Option 'save-levels': directory '%s' does not exist", vset_dir);
        } else {
            Abort("Option 'save-levels': failed opening directory '%s'", vset_dir);
        }
    }

    init_mu_calculus();

    /* determine if we need to generate a symbolic parity game */
#ifdef LTSMIN_PBES
    bool spg = true;
#else
    bool spg = GBhaveMucalc() ? true : false;
#endif

    /* if spg, then initialize labeling stuff before reachability */
    if (spg) {
        Print(infoShort, "Generating a Symbolic Parity Game (SPG).");
        init_spg(model);
    }

    /* create timer */
    reach_timer = RTcreateTimer();

    /* fix level 0 */
    visited = vset_create(domain, -1, NULL);
    vset_copy(visited, initial);

    /* check the invariants at level 0 */
    check_invariants(visited, 0);

    /* run reachability */
    run_reachability(visited, files[1]);

    /* report states */
    final_stat_reporting(visited);

    /* save LTS */
    if (files[1] != NULL) {
        char *ext = strrchr(files[1], '.');
        if (strcasecmp(ext, ".etf") == 0) {
            do_output(files[1], visited);
        } else {
            // if not .etf, then the filename ends with .bdd or .ldd, symbolic LTS
            do_dd_output (initial, visited, files[1]);
        }
    }

    compute_maxsum(visited, domain);

    CHECK_MU(visited, src);

    if (max_mu_count > 0) {
        Print(info, "Mu-calculus peak nodes: %ld", max_mu_count);
    }

    /* optionally print counts of all group_next and group_explored sets */
    final_final_stats_reporting ();

    if (spg) { // converting the LTS to a symbolic parity game, save and solve.
        lts_to_pg_solve (visited, src);
    }

#ifdef HAVE_SYLVAN
    /* in case other Lace threads were still suspended... */
    if (vset_default_domain!=VSET_Sylvan && vset_default_domain!=VSET_LDDmc) {
        lace_resume();
    } else if (SYLVAN_STATS) {
        sylvan_stats_report(stderr);
    }
#endif

    RTfree (src);
    GBExit(model);
}