int aut_start(void) { char myname[] = "aut_start"; int max; if (__all_callback_fn == NULL) { printf("%s: please call aut_register first\n", myname); return (-1); } /* 取得所有有效配置行的总和 */ max = aut_size(); if (max <= 0) { aut_log_error("%s(%d): configure's size is null", myname, __LINE__); return (-1); } return (__fn_callback(0, max, NULL)); }
int main( int argc, char **argv ) { char *result; FILE *fp; char filename[STRING_MAXLEN]; char instr[STRING_MAXLEN]; anode_t *head, *node, *out_node; vartype state[2], next_state[2]; strcpy( filename, "temp_automaton_io_dumpXXXXXX" ); result = mktemp( filename ); if (result == NULL) { perror( "test_automaton_io, mktemp" ); abort(); } fp = fopen( filename, "w+" ); if (fp == NULL) { perror( "test_automaton_io, fopen" ); abort(); } fprintf( fp, REF_GR1CAUT_TRIVIAL ); if (fseek( fp, 0, SEEK_SET )) { perror( "test_automaton_io, fseek" ); abort(); } /* Load in "gr1c automaton" format */ head = aut_aut_load( 2, fp ); if (head == NULL) { ERRPRINT( "Failed to read 3-node automaton in \"gr1c automaton\" format." ); abort(); } /* Check number of nodes, labels, and outgoing edges */ if (aut_size( head ) != 3) { ERRPRINT1( "size 3 automaton detected as having size %d.", aut_size( head ) ); abort(); } state[0] = 1; state[1] = 0; node = find_anode( head, 0, state, 2 ); if (node == NULL) { ERRPRINT2( "could not find expected node with state [%d %d].", state[0], state[1] ); abort(); } if (node->rgrad != 2) { ERRPRINT1( "node should have reach annotation value of 2 but actually has %d", node->rgrad ); abort(); } state[0] = 0; state[1] = 0; out_node = find_anode( head, 0, state, 2 ); if (out_node == NULL) { ERRPRINT2( "could not find expected node with state [%d %d].", state[0], state[1] ); abort(); } if (out_node->rgrad != 1) { ERRPRINT1( "node should have reach annotation value of 1 but actually has %d", out_node->rgrad ); abort(); } if (node->trans_len != 2) { ERRPRINT1( "node should have 2 outgoing transitions but actually has %d.", node->trans_len ); abort(); } if (*(node->trans) != out_node && *(node->trans+1) != out_node) { ERRPRINT( "an edge is missing." ); abort(); } /* Modify the automaton and dump the result */ *(node->trans+1) = node; state[0] = 0; state[1] = 1; head = insert_anode( head, 0, -1, False, state, 2 ); if (head == NULL) { ERRPRINT( "failed to insert new node into automaton." ); abort(); } next_state[0] = 1; next_state[1] = 0; head = append_anode_trans( head, 0, state, 2, 0, next_state ); if (head == NULL) { ERRPRINT( "failed to append transition to new node." ); abort(); } fclose( fp ); fp = fopen( filename, "w+" ); if (fp == NULL) { perror( "test_automaton_io, fopen" ); abort(); } aut_aut_dump( head, 2, fp ); if (fseek( fp, 0, SEEK_SET )) { perror( "test_automaton_io, fseek" ); abort(); } /* NB, assumed width may cause problems if we start using Unicode. */ if (fread( instr, sizeof(char), strlen(REF_GR1CAUT_TRIVIAL_MOD), fp ) < strlen(REF_GR1CAUT_TRIVIAL_MOD)) { ERRPRINT( "output of aut_aut_dump is too short." ); abort(); } if (!strncmp( instr, REF_GR1CAUT_TRIVIAL_MOD, strlen(REF_GR1CAUT_TRIVIAL_MOD) )) { ERRPRINT( "output of aut_aut_dump does not match expectation." ); abort(); } fclose( fp ); if (remove( filename )) { perror( "test_automaton_io, remove" ); abort(); } return 0; }
int main( int argc, char **argv ) { FILE *fp; FILE *stdin_backup = NULL; bool help_flag = False; bool ptdump_flag = False; bool logging_flag = False; unsigned char verbose = 0; int input_index = -1; int output_file_index = -1; /* For command-line flag "-o". */ char dumpfilename[64]; int i, j, var_index; ptree_t *tmppt; /* General purpose temporary ptree pointer */ int horizon = -1; DdNode *W, *etrans, *strans, **sgoals, **egoals; DdManager *manager; DdNode *T = NULL; anode_t *strategy = NULL; int num_env, num_sys; int original_num_env, original_num_sys; int max_sim_it; /* Number of simulation iterations */ anode_t *play; vartype *init_state; int *init_state_ints = NULL; char *all_vars = NULL, *metric_vars = NULL; int *offw, num_vars; int init_state_acc; /* Accumulate components of initial state before expanding into a (bool) bitvector. */ /* Look for flags in command-line arguments. */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { if (argv[i][1] == 'h') { help_flag = True; } else if (argv[i][1] == 'V') { printf( "grjit (experiment-related program, distributed with" " gr1c v" GR1C_VERSION ")\n\n" GR1C_COPYRIGHT "\n" ); return 0; } else if (argv[i][1] == 'v') { verbose = 1; j = 2; /* Only support up to "level 2" of verbosity */ while (argv[i][j] == 'v' && j <= 2) { verbose++; j++; } } else if (argv[i][1] == 'l') { logging_flag = True; } else if (argv[i][1] == 'p') { ptdump_flag = True; } else if (argv[i][1] == 'm') { if (i == argc-1) { fprintf( stderr, "Invalid flag given. Try \"-h\".\n" ); return 1; } all_vars = strtok( argv[i+1], "," ); max_sim_it = strtol( all_vars, NULL, 10 ); all_vars = strtok( NULL, "," ); if (all_vars == NULL) { fprintf( stderr, "Invalid use of -m flag.\n" ); return 1; } metric_vars = strdup( all_vars ); if (max_sim_it >= 0) { all_vars = strtok( NULL, "," ); if (all_vars == NULL) { fprintf( stderr, "Invalid use of -m flag.\n" ); return 1; } init_state_acc = read_state_str( all_vars, &init_state_ints, -1 ); all_vars = strtok( NULL, "," ); if (all_vars == NULL) { horizon = -1; /* The horizon was not given. */ } else { horizon = strtol( all_vars, NULL, 10 ); if (horizon < 1) { fprintf( stderr, "Invalid use of -m flag. Horizon must" " be positive.\n" ); return 1; } } } all_vars = NULL; i++; } else if (argv[i][1] == 'o') { if (i == argc-1) { fprintf( stderr, "Invalid flag given. Try \"-h\".\n" ); return 1; } output_file_index = i+1; i++; } else { fprintf( stderr, "Invalid flag given. Try \"-h\".\n" ); return 1; } } else if (input_index < 0) { /* Use first non-flag argument as filename whence to read specification. */ input_index = i; } } if (help_flag) { /* Split among printf() calls to conform with ISO C90 string length */ printf( "Usage: %s [-hVvlp] [-m ARG1,ARG2,...] [-o FILE] [FILE]\n\n" " -h this help message\n" " -V print version and exit\n" " -v be verbose; use -vv to be more verbose\n" " -l enable logging\n" " -p dump parse trees to DOT files, and echo formulas to screen\n" " -o FILE output results to FILE, rather than stdout (default)\n", argv[0] ); printf( " -m ARG1,... run simulation using comma-separated list of arguments:\n" " ARG1 is the max simulation duration; -1 to only compute horizon;\n" " ARG2 is a space-separated list of metric variables;\n" " ARG3 is a space-separated list of initial values;\n" " ARG3 is ignored and may be omitted if ARG1 equals -1.\n" " ARG4 is the horizon, if provided; otherwise compute it.\n" ); return 1; } if (logging_flag) { openlogfile( NULL ); /* Use default filename prefix */ /* Only change verbosity level if user did not specify it */ if (verbose == 0) verbose = 1; } else { setlogstream( stdout ); setlogopt( LOGOPT_NOTIME ); } if (verbose > 0) logprint( "Running with verbosity level %d.", verbose ); /* If filename for specification given at command-line, then use it. Else, read from stdin. */ if (input_index > 0) { fp = fopen( argv[input_index], "r" ); if (fp == NULL) { perror( "grjit, fopen" ); return -1; } stdin_backup = stdin; stdin = fp; } /* Parse the specification. */ if (verbose) logprint( "Parsing input..." ); SPC_INIT( spc ); if (yyparse()) return -1; if (verbose) logprint( "Done." ); if (stdin_backup != NULL) { stdin = stdin_backup; } /* Close input file, if opened. */ if (input_index > 0) fclose( fp ); /* Treat deterministic problem in which ETRANS or EINIT is omitted. */ if (spc.evar_list == NULL) { if (spc.et_array_len == 0) { spc.et_array_len = 1; spc.env_trans_array = malloc( sizeof(ptree_t *) ); if (spc.env_trans_array == NULL) { perror( "gr1c, malloc" ); return -1; } *spc.env_trans_array = init_ptree( PT_CONSTANT, NULL, 1 ); } if (spc.env_init == NULL) spc.env_init = init_ptree( PT_CONSTANT, NULL, 1 ); } /* Number of variables, before expansion of those that are nonboolean */ original_num_env = tree_size( spc.evar_list ); original_num_sys = tree_size( spc.svar_list ); /* Build list of variable names if needed for simulation, storing the result as a string in all_vars */ if (max_sim_it >= 0) { /* At this point, init_state_acc should contain the number of integers read by read_state_str() during command-line argument parsing. */ if (init_state_acc != original_num_env+original_num_sys) { fprintf( stderr, "Number of initial values given does not match number" " of problem variables.\n" ); return 1; } num_vars = 0; tmppt = spc.evar_list; while (tmppt) { num_vars += strlen( tmppt->name )+1; tmppt = tmppt->left; } tmppt = spc.svar_list; while (tmppt) { num_vars += strlen( tmppt->name )+1; tmppt = tmppt->left; } all_vars = malloc( num_vars*sizeof(char) ); if (all_vars == NULL) { perror( "main, malloc" ); return -1; } i = 0; tmppt = spc.evar_list; while (tmppt) { strncpy( all_vars+i, tmppt->name, num_vars-i ); i += strlen( tmppt->name )+1; *(all_vars+i-1) = ' '; tmppt = tmppt->left; } tmppt = spc.svar_list; while (tmppt) { strncpy( all_vars+i, tmppt->name, num_vars-i ); i += strlen( tmppt->name )+1; *(all_vars+i-1) = ' '; tmppt = tmppt->left; } *(all_vars+i-1) = '\0'; if (verbose) logprint( "String of all variables found to be \"%s\"", all_vars ); } if (ptdump_flag) { tree_dot_dump( spc.env_init, "env_init_ptree.dot" ); tree_dot_dump( spc.sys_init, "sys_init_ptree.dot" ); for (i = 0; i < spc.et_array_len; i++) { snprintf( dumpfilename, sizeof(dumpfilename), "env_trans%05d_ptree.dot", i ); tree_dot_dump( *(spc.env_trans_array+i), dumpfilename ); } for (i = 0; i < spc.st_array_len; i++) { snprintf( dumpfilename, sizeof(dumpfilename), "sys_trans%05d_ptree.dot", i ); tree_dot_dump( *(spc.sys_trans_array+i), dumpfilename ); } if (spc.num_egoals > 0) { for (i = 0; i < spc.num_egoals; i++) { snprintf( dumpfilename, sizeof(dumpfilename), "env_goal%05d_ptree.dot", i ); tree_dot_dump( *(spc.env_goals+i), dumpfilename ); } } if (spc.num_sgoals > 0) { for (i = 0; i < spc.num_sgoals; i++) { snprintf( dumpfilename, sizeof(dumpfilename), "sys_goal%05d_ptree.dot", i ); tree_dot_dump( *(spc.sys_goals+i), dumpfilename ); } } var_index = 0; printf( "Environment variables (indices; domains): " ); if (spc.evar_list == NULL) { printf( "(none)" ); } else { tmppt = spc.evar_list; while (tmppt) { if (tmppt->value == 0) { /* Boolean */ if (tmppt->left == NULL) { printf( "%s (%d; bool)", tmppt->name, var_index ); } else { printf( "%s (%d; bool), ", tmppt->name, var_index); } } else { if (tmppt->left == NULL) { printf( "%s (%d; {0..%d})", tmppt->name, var_index, tmppt->value ); } else { printf( "%s (%d; {0..%d}), ", tmppt->name, var_index, tmppt->value ); } } tmppt = tmppt->left; var_index++; } } printf( "\n\n" ); printf( "System variables (indices; domains): " ); if (spc.svar_list == NULL) { printf( "(none)" ); } else { tmppt = spc.svar_list; while (tmppt) { if (tmppt->value == 0) { /* Boolean */ if (tmppt->left == NULL) { printf( "%s (%d; bool)", tmppt->name, var_index ); } else { printf( "%s (%d; bool), ", tmppt->name, var_index ); } } else { if (tmppt->left == NULL) { printf( "%s (%d; {0..%d})", tmppt->name, var_index, tmppt->value ); } else { printf( "%s (%d; {0..%d}), ", tmppt->name, var_index, tmppt->value ); } } tmppt = tmppt->left; var_index++; } } printf( "\n\n" ); print_GR1_spec( spc.evar_list, spc.svar_list, spc.env_init, spc.sys_init, spc.env_trans_array, spc.et_array_len, spc.sys_trans_array, spc.st_array_len, spc.env_goals, spc.num_egoals, spc.sys_goals, spc.num_sgoals, stdout ); } if (expand_nonbool_GR1( spc.evar_list, spc.svar_list, &spc.env_init, &spc.sys_init, &spc.env_trans_array, &spc.et_array_len, &spc.sys_trans_array, &spc.st_array_len, &spc.env_goals, spc.num_egoals, &spc.sys_goals, spc.num_sgoals, verbose ) < 0) return -1; spc.nonbool_var_list = expand_nonbool_variables( &spc.evar_list, &spc.svar_list, verbose ); if (spc.et_array_len > 1) { spc.env_trans = merge_ptrees( spc.env_trans_array, spc.et_array_len, PT_AND ); } else if (spc.et_array_len == 1) { spc.env_trans = *spc.env_trans_array; } else { fprintf( stderr, "Syntax error: GR(1) specification is missing environment" " transition rules.\n" ); return -1; } if (spc.st_array_len > 1) { spc.sys_trans = merge_ptrees( spc.sys_trans_array, spc.st_array_len, PT_AND ); } else if (spc.st_array_len == 1) { spc.sys_trans = *spc.sys_trans_array; } else { fprintf( stderr, "Syntax error: GR(1) specification is missing system" " transition rules.\n" ); return -1; } if (verbose > 1) /* Dump the spec to show results of conversion (if any). */ print_GR1_spec( spc.evar_list, spc.svar_list, spc.env_init, spc.sys_init, spc.env_trans_array, spc.et_array_len, spc.sys_trans_array, spc.st_array_len, spc.env_goals, spc.num_egoals, spc.sys_goals, spc.num_sgoals, NULL ); num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); manager = Cudd_Init( 2*(num_env+num_sys), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_SetMaxCacheHard( manager, (unsigned int)-1 ); Cudd_AutodynEnable( manager, CUDD_REORDER_SAME ); T = check_realizable( manager, EXIST_SYS_INIT, verbose ); if (verbose) { if (T != NULL) { logprint( "Realizable." ); } else { logprint( "Not realizable." ); } } if (T != NULL) { /* Print measure data and simulate. */ if (horizon < 0) { if (verbose) logprint( "Computing horizon with metric variables: %s", metric_vars ); horizon = compute_horizon( manager, &W, &etrans, &strans, &sgoals, metric_vars, verbose ); logprint( "horizon: %d", horizon ); if (getlogstream() != stdout) printf( "horizon: %d\n", horizon ); } else { W = compute_winning_set_saveBDDs( manager, &etrans, &strans, &egoals, &sgoals, verbose ); if (verbose) logprint( "Using given horizon: %d", horizon ); } if (max_sim_it >= 0 && horizon > -1) { /* Compute variable offsets and use it to get the initial state as a bitvector */ offw = get_offsets( all_vars, &num_vars ); if (num_vars != original_num_env+original_num_sys) { fprintf( stderr, "Error while computing bitwise variable offsets.\n" ); return -1; } free( all_vars ); init_state_acc = 0; if (verbose) { logprint_startline(); logprint_raw( "initial state for simulation:" ); } for (i = 0; i < original_num_env+original_num_sys; i++) { if (verbose) logprint_raw( " %d", *(init_state_ints+i) ); init_state_acc += *(init_state_ints+i) << *(offw + 2*i); } if (verbose) logprint_endline(); free( offw ); init_state = int_to_bitvec( init_state_acc, num_env+num_sys ); if (init_state == NULL) return -1; play = sim_rhc( manager, W, etrans, strans, sgoals, metric_vars, horizon, init_state, max_sim_it, verbose ); if (play == NULL) { fprintf( stderr, "Error while attempting receding horizon" " simulation.\n" ); return -1; } free( init_state ); logprint( "play length: %d", aut_size( play ) ); tmppt = spc.nonbool_var_list; while (tmppt) { aut_compact_nonbool( play, spc.evar_list, spc.svar_list, tmppt->name, tmppt->value ); tmppt = tmppt->left; } num_env = tree_size( spc.evar_list ); num_sys = tree_size( spc.svar_list ); /* Open output file if specified; else point to stdout. */ if (output_file_index >= 0) { fp = fopen( argv[output_file_index], "w" ); if (fp == NULL) { perror( "grjit, fopen" ); return -1; } } else { fp = stdout; } /* Print simulation trace */ dump_simtrace( play, spc.evar_list, spc.svar_list, fp ); if (fp != stdout) fclose( fp ); } Cudd_RecursiveDeref( manager, W ); Cudd_RecursiveDeref( manager, etrans ); Cudd_RecursiveDeref( manager, strans ); } /* Clean-up */ free( metric_vars ); delete_tree( spc.evar_list ); delete_tree( spc.svar_list ); delete_tree( spc.env_init ); delete_tree( spc.sys_init ); delete_tree( spc.env_trans ); delete_tree( spc.sys_trans ); for (i = 0; i < spc.num_egoals; i++) delete_tree( *(spc.env_goals+i) ); if (spc.num_egoals > 0) free( spc.env_goals ); for (i = 0; i < spc.num_sgoals; i++) delete_tree( *(spc.sys_goals+i) ); if (spc.num_sgoals > 0) free( spc.sys_goals ); if (T != NULL) Cudd_RecursiveDeref( manager, T ); if (strategy) delete_aut( strategy ); if (verbose > 1) logprint( "Cudd_CheckZeroRef -> %d", Cudd_CheckZeroRef( manager ) ); Cudd_Quit(manager); if (logging_flag) closelogfile(); /* Return 0 if realizable, -1 if not realizable. */ if (T != NULL) { return 0; } else { return -1; } return 0; }