static int lump_hashcode(lts_t lts,int *map,int i){ long j; uint32_t temp[2]; uint32_t contrib[3]; int last=lts->begin[i+1]-1; int hc=map[i]; //int sigptr=0, *sig=alloca(2*(last-lts->begin[i])); //Warning(1,"signature for %d %x %x",i,sig,map); for(j=lts->begin[i];j<=last;j++){ int block=map[lts->dest[j]]; contrib[2]=block; TreeUnfold(lts->edge_idx,lts->label[j],(int*)contrib); //Warning(1,"collecting"); while(j<last && block==map[lts->dest[j+1]]){ j++; TreeUnfold(lts->edge_idx,lts->label[j],(int*)temp); uint64_t teller=((uint64_t)contrib[0])*((uint64_t)temp[1]); teller+=((uint64_t)temp[0])*((uint64_t)contrib[1]); uint64_t noemer=((uint64_t)contrib[1])*((uint64_t)temp[1]); uint64_t gcd=gcd64(teller,noemer); contrib[0]=teller/gcd; contrib[1]=noemer/gcd; } hc=SuperFastHash(contrib,12,hc); } return hc; }
static void lts_merge_hyperedges(lts_t lts){ if (lts->transitions==0) return; lts_set_type(lts,LTS_LIST); int group_pos=lts_type_find_edge_label(lts->ltstype,"group"); int param_pos=lts_type_find_edge_label(lts->ltstype,"numerator"); uint32_t e=1; uint32_t t=0; uint32_t label[6]; TreeUnfold(lts->edge_idx,lts->label[0],(int*)label); for(uint32_t i=1;i<lts->transitions;i++){ uint32_t next[6]; TreeUnfold(lts->edge_idx,lts->label[i],(int*)next); int k=0; if (lts->src[t]==lts->src[i]){ for(;k<=group_pos;k++){ if (label[k]!=next[k]) break; } } if (k<=group_pos){ e++; } if (lts->dest[t]!=lts->dest[i]){ k=0; } if (k==group_pos && label[param_pos]==1 && label[param_pos+1]==1 && next[param_pos]==1 && next[param_pos+1]==1){ // identical non-hyperedge: skip; e--; } else if (k<=group_pos) { // difference: ship out. lts->label[t]=TreeFold(lts->edge_idx,(int*)label); t++; lts->src[t]=lts->src[i]; lts->dest[t]=lts->dest[i]; TreeUnfold(lts->edge_idx,lts->label[i],(int*)label); } else { // same: add; fprintf(stderr,"merge %u/%u + %u/%u = ",label[param_pos],label[param_pos+1],next[param_pos],next[param_pos+1]); uint64_t teller=((uint64_t)label[param_pos])*((uint64_t)next[param_pos+1]); teller+=((uint64_t)next[param_pos])*((uint64_t)label[param_pos+1]); uint64_t noemer=((uint64_t)next[param_pos+1])*((uint64_t)label[param_pos+1]); uint64_t gcd=gcd64(teller,noemer); label[param_pos]=teller/gcd; label[param_pos+1]=noemer/gcd; fprintf(stderr,"%u/%u\n",label[param_pos],label[param_pos+1]); } } lts->label[t]=TreeFold(lts->edge_idx,(int*)label); t++; fprintf(stderr,"result has %u real edges\n",e); lts_set_size(lts,lts->root_count,lts->states,t); }
static int same_lump_sig(lts_t lts,uint32_t* map,uint32_t s1,uint32_t s2){ uint32_t t1,t2,m1,m2,t,block,rate1[2],rate2[2],temp[2]; if (map[s1]!=map[s2]) { //Warning(1,"source maps different"); return 0; } t1=lts->begin[s1]; t2=lts->begin[s2]; m1=lts->begin[s1+1]; m2=lts->begin[s2+1]; for(;;){ if(t1==m1 && t2==m2) return 1; if(t1==m1 || t2==m2) { //Warning(1,"different lengths"); return 0; } block=map[lts->dest[t1]]; if(block!=map[lts->dest[t2]]) return 0; t=t1+1; TreeUnfold(lts->edge_idx,lts->label[t1],(int*)rate1); while(t<m1 && map[lts->dest[t]]==block){ TreeUnfold(lts->edge_idx,lts->label[t],(int*)temp); uint64_t teller=((uint64_t)rate1[0])*((uint64_t)temp[1]); teller+=((uint64_t)temp[0])*((uint64_t)rate1[1]); uint64_t noemer=((uint64_t)rate1[1])*((uint64_t)temp[1]); uint64_t gcd=gcd64(teller,noemer); rate1[0]=teller/gcd; rate1[1]=noemer/gcd; t++; } t1=t; t=t2+1; TreeUnfold(lts->edge_idx,lts->label[t2],(int*)rate2); while(t<m2 && map[lts->dest[t]]==block){ TreeUnfold(lts->edge_idx,lts->label[t],(int*)temp); uint64_t teller=((uint64_t)rate2[0])*((uint64_t)temp[1]); teller+=((uint64_t)temp[0])*((uint64_t)rate2[1]); uint64_t noemer=((uint64_t)rate2[1])*((uint64_t)temp[1]); uint64_t gcd=gcd64(teller,noemer); rate2[0]=teller/gcd; rate2[1]=noemer/gcd; t++; } t2=t; if (rate1[0]!=rate2[0] || rate1[1]!= rate2[1]) return 0; } return 0; }
static int read_state(lts_file_t file,int *seg,void* state,void*labels){ if (file->state_count<file->lts->states){ *seg=file->state_count%file->segments; if (file->lts->prop_idx) { TreeUnfold(file->lts->prop_idx,file->lts->properties[file->state_count],labels); } else if (file->lts->properties) { *((uint32_t*)labels)=file->lts->properties[file->state_count]; } if (file->lts->state_db) { TreeUnfold(file->lts->state_db,file->state_count,state); } else { // TODO: decide if reading state number is allowed/required. *((uint32_t*)state)=file->state_count; } file->state_count++; return 1; } else { return 0; } }
static void lts_lump(lts_t lts){ int found; uint32_t i, k, j, count, oldbegin; lts_set_type(lts,LTS_BLOCK); count=0; uint32_t rate[2]; uint32_t temp[2]; for(i=0;i<lts->states;i++){ oldbegin=lts->begin[i]; lts->begin[i]=count; for(j=oldbegin;j<lts->begin[i+1];j++){ found=0; for(k=lts->begin[i];k<count;k++){ if(lts->dest[j]==lts->dest[k]){ TreeUnfold(lts->edge_idx,lts->label[k],(int*)rate); TreeUnfold(lts->edge_idx,lts->label[j],(int*)temp); uint64_t teller=((uint64_t)rate[0])*((uint64_t)temp[1]); teller+=((uint64_t)temp[0])*((uint64_t)rate[1]); uint64_t noemer=((uint64_t)rate[1])*((uint64_t)temp[1]); uint64_t gcd=gcd64(teller,noemer); rate[0]=teller/gcd; rate[1]=noemer/gcd; lts->label[k]=TreeFold(lts->edge_idx,(int*)rate); found=1; break; } } if (!found){ lts->label[count]=lts->label[j]; lts->dest[count]=lts->dest[j]; count++; } } } lts->begin[lts->states]=count; lts_set_size(lts,lts->root_count,lts->states,count); }
static int torx_handle_request(torx_struct_t *context, char *req) { while(isspace((int)*req)) req++; switch(req[0]) { case 'r': { /* reset */ fprintf(stdout, "R 0\t1\n"); fflush(stdout); break; } case 'e': { /*explore */ int n, res; req++; while(isspace((int)*req)) req++; if ((res = sscanf(req, "%u", &n)) != 1) { int l = strlen(req); if (req[l - 1] == '\n') req[l - 1] = '\0'; fprintf(stdout, "E0 Missing event number (%s; sscanf found #%d)\n", req, res); } else if (n >= TreeCount(dbs)) { fprintf(stdout, "E0 Unknown event number\n"); fflush(stdout); } else { int src[N], c; TreeUnfold(dbs,n,src); fprintf(stdout, "EB\n"); c=GBgetTransitionsAll(context->model,src,torx_transition,context); fprintf(stdout, "EE\n"); fflush(stdout); } break; } case 'q': { fprintf(stdout, "Q\n"); fflush(stdout); return 1; break; } default: /* unknown command */ fprintf(stdout, "A_ERROR UnknownCommand: %s\n", req); fflush(stdout); } return 0; }
static int read_edge(lts_file_t file,int *src_seg,void* src_state, int *dst_seg,void*dst_state,void* labels ){ if (file->edge_count<file->lts->transitions) { *((uint32_t*)src_seg)=file->lts->src[file->edge_count]%file->segments; *((uint32_t*)src_state)=file->lts->src[file->edge_count]/file->segments; *((uint32_t*)dst_seg)=file->lts->dest[file->edge_count]%file->segments; *((uint32_t*)dst_state)=file->lts->dest[file->edge_count]/file->segments; if (file->lts->edge_idx) { TreeUnfold(file->lts->edge_idx,file->lts->label[file->edge_count],labels); } else if (file->lts->label) { *((uint32_t*)labels)=file->lts->label[file->edge_count]; } file->edge_count++; return 1; } else { return 0; } }
int main(int argc, char *argv[]){ char *files[2]; RTinitPopt(&argc,&argv,options,1,2,files,NULL,"<model> [<lts>]", "Perform an enumerative reachability analysis of <model>\n" "Run the TorX remote procedure call protocol on <model> (--torx).\n\n" "Options"); if (files[1]) { Warning(info,"Writing output to %s",files[1]); write_lts=1; } else { Warning(info,"No output, just counting the number of states"); write_lts=0; } if (application==RunTorX && write_lts) Fatal(1,error,"A TorX server does not write to a file"); Warning(info,"loading model from %s",files[0]); model_t model=GBcreateBase(); GBsetChunkMethods(model,new_string_index,NULL, (int2chunk_t)SIgetC,(chunk2int_t)SIputC,(get_count_t)SIgetCount); GBloadFile(model,files[0],&model); if (RTverbosity >=2) { fprintf(stderr,"Dependency Matrix:\n"); GBprintDependencyMatrix(stderr,model); } if (matrix) { GBprintDependencyMatrix(stdout,model); exit(0); } lts_type_t ltstype=GBgetLTStype(model); N=lts_type_get_state_length(ltstype); edge_info_t e_info=GBgetEdgeInfo(model); K=e_info->groups; Warning(info,"length is %d, there are %d groups",N,K); state_labels=lts_type_get_state_label_count(ltstype); edge_labels=lts_type_get_edge_label_count(ltstype); Warning(info,"There are %d state labels and %d edge labels",state_labels,edge_labels); if (state_labels&&write_lts&&!write_state) { Fatal(1,error,"Writing state labels, but not state vectors unsupported. " "Writing of state vector is enabled with the option --write-state"); } int src[N]; GBgetInitialState(model,src); Warning(info,"got initial state"); int level=0; switch(application){ case ReachVset: domain=vdom_create_default(N); visited_set=vset_create(domain,0,NULL); next_set=vset_create(domain,0,NULL); if (write_lts){ output=lts_output_open(files[1],model,1,0,1,"viv",NULL); lts_output_set_root_vec(output,(uint32_t*)src); lts_output_set_root_idx(output,0,0); output_handle=lts_output_begin(output,0,0,0); } vset_add(visited_set,src); vset_add(next_set,src); vset_t current_set=vset_create(domain,0,NULL); while (!vset_is_empty(next_set)){ if (RTverbosity >= 1) Warning(info,"level %d has %d states, explored %d states %d trans", level,(visited-explored),explored,trans); level++; vset_copy(current_set,next_set); vset_clear(next_set); vset_enum(current_set,explore_state_vector,model); } long long size; long nodes; vset_count(visited_set,&nodes,&size); Warning(info,"%lld reachable states represented symbolically with %ld nodes",size,nodes); break; case ReachTreeDBS: dbs=TreeDBScreate(N); if(TreeFold(dbs,src)!=0){ Fatal(1,error,"expected 0"); } if (write_lts){ output=lts_output_open(files[1],model,1,0,1,write_state?"vsi":"-ii",NULL); if (write_state) lts_output_set_root_vec(output,(uint32_t*)src); lts_output_set_root_idx(output,0,0); output_handle=lts_output_begin(output,0,0,0); } int limit=visited; while(explored<visited){ if (limit==explored){ if (RTverbosity >= 1) Warning(info,"level %d has %d states, explored %d states %d trans", level,(visited-explored),explored,trans); limit=visited; level++; } TreeUnfold(dbs,explored,src); explore_state_index(model,explored,src); } break; case RunTorX: { torx_struct_t context = { model, ltstype }; torx_ui(&context); return 0; } } if (write_lts){ lts_output_end(output,output_handle); Warning(info,"finishing the writing"); lts_output_close(&output); Warning(info,"state space has %d levels %d states %d transitions",level,visited,trans); } else { printf("state space has %d levels %d states %d transitions\n",level,visited,trans); } return 0; }
void lts_write_pg (const char*name, lts_t lts) { Print(infoShort,"writing %s",name); FILE* f=fopen(name,"w"); if (f == NULL) { AbortCall("Could not open %s for writing",name); } lts_set_type(lts,LTS_BLOCK); //int N=lts_type_get_state_length(lts->ltstype); int L=lts_type_get_state_label_count(lts->ltstype); //int K=lts_type_get_edge_label_count(lts->ltstype); if (L != 2){ Abort("Number of state labels is %d, needs to be 2 for parity games.",L); } Warning(info,"Number of states: %d", lts->states); Warning(info,"First pass..."); // compute max priority // determine if there are nodes without successors int max_priority = 0; int labels[L]; bool first_edge = true; bool write_true = false; bool write_false = false; for(uint32_t src_idx=0; src_idx<lts->states; src_idx++){ TreeUnfold(lts->prop_idx, lts->properties[src_idx], labels); int priority = labels[PG_PRIORITY]; if (priority > max_priority) { max_priority = priority; } int player = labels[PG_PLAYER]; if (lts->begin[src_idx] >= lts->begin[src_idx+1]){ // no edges if (player==PG_AND) { write_true = true; } else if (player==PG_OR) { write_false = true; } //Warning(info, "State %d has no successors.",src_idx); } } if (max_priority%2!=0) { // when converting from min to max-priority game, // the maximum priority should be even. max_priority++; } Warning(info,"Second pass..."); bool min_game = false; int max_id = lts->states; int offset = 0; int true_idx = 0; int false_idx = 0; if (write_true) { true_idx = max_id; max_id++; } if (write_false) { false_idx = max_id; max_id++; } // write header. fprintf(f,"parity %d;\n",max_id-1); // write states and edges for(uint32_t src_idx=0; src_idx<lts->states; src_idx++){ if (src_idx > 0){ fprintf(f,";\n"); } TreeUnfold(lts->prop_idx, lts->properties[src_idx], labels); int priority = min_game ? labels[PG_PRIORITY] : max_priority-labels[PG_PRIORITY]; int player = labels[1]; fprintf(f, "%d %d %d ", src_idx+offset, priority /* priority */, player /* player */); first_edge = true; for(uint32_t edge_idx=lts->begin[src_idx]; edge_idx<lts->begin[src_idx+1]; edge_idx++){ if (!first_edge){ fprintf(f, ","); } fprintf(f,"%d",lts->dest[edge_idx]+offset); first_edge = false; } if (first_edge) { //Warning(info,"State %d has no successors.",src_idx); // add transition to true/false node fprintf(f,"%d",((player==PG_AND) ? true_idx : false_idx)); } } fprintf(f,";\n"); // write true and false if (write_true) { fprintf(f, "%d %d %d ", true_idx, min_game ? 0 : max_priority /* priority */, PG_AND /* player */); fprintf(f,"%d;\n",true_idx); } if (write_false) { fprintf(f, "%d %d %d ", false_idx, min_game ? 1 : max_priority-1 /* priority */, PG_OR /* player */); fprintf(f,"%d;\n",false_idx); } fclose(f); }
static void dbs_unfold(void*context,int seg,int ofs,int*vec){ struct dbs_ctx *ctx=(struct dbs_ctx *)context; TreeUnfold(ctx->dbs,ctx->begin[seg]+ofs,vec); }