Hi Seth,

thanks for the additional info, that clears things up. Please find
below some pointers to places in the NuSMV interface that might help
you. Let us know if you need further information.



Please note that the following are based on the latest release, NuSMV
2.5.0. However, in 2.4.3 the interface mentioned below is comparable.



First we are not sure whether you are trying to follow an approach
where you do most work within NuSMV or where you just feed an smv file
such as the one attached to NuSMV.

In the first case (which is probably more clean) you would simply
remember the variables making up Q in some set structure and then
build the superset relation.

In the second case (which is a bit hack-ish) you would need to obtain
the list of state variables ("state variable" here in the NuSMV sense,
not in the sense of your attached .smv file) and somehow filter out
the ones making up Q. Note that you can probably declare the "input"
variable in your attached .smv file as an IVAR.



For obtaining the set of state variables there are two main ways:

- use BddEnc.h interface:
 - get set of state variables as BDD:
   - BddEnc_get_state_vars_cube
 - convert a BDD to an expression:
   - BddEnc_bdd_to_expr
 - convert expression to BDD:
   - BddEnc_expr_to_bdd

or

- use SymbTable.h interface:
 - get set of state variables as an expression:
   - SymbTable_get_state_vars
 - convert expression to BDD:
   - BddEnc_expr_to_bdd



For renaming variables when computing supersets_in_reachable, you can
probably abuse next state variables. Then you can use the following
two functions for renaming back and forth:


BddEnc_state_var_to_next_state_var

BddEnc_next_state_var_to_state_var



The following code snippets show two ways of building the superset
relation. Note that they are just sketches written w/o
compiling/testing or even checking function signatures.

Note also that the snippets assume that each state of the original DFA
is represented by a single state Boolean variable (declared as VAR)
and that all the labels of the property are seen as input
(i.e. declared as IVAR). Notice, that this code is not correct if a
logarithmic encoding of the states of the automaton is performed
(i.e. scalar variables are used).

Here is the code to generate it as an expr.
--- Seth: This is clearly better. Nothing to free, no BDD's to manage, just convert it in one lump

NodeList_ptr sv = SymbTable_get_state_vars(st);
ListIter_ptr iter;
Expr_ptr ssr_expr = Expr_true();
Expr_ptr tmp = Expr_false();
NODE_LIST_FOREACH(sv, iter) {
 node_ptr var = NodeList_get_element_at(sv, iter);

 ssr_expr = Expr_and(ssr_expr, Expr_implies(var, Expr_next(var)));
 tmp = Expr_or(tmp, Expr_and(Expr_not(var), Expr_next(var)));
}
ssr_expr = Expr_and(ssr_expr, tmp);
-- Seth added lines below
assert TypeChecker_is_expression_wellformed(self->enc->type_checker, ssr_expr, Nil);
strict_superset_relation = BddEnc_expr_to_bdd(self->dd, ssr_expr, Nil);

-- Seth's idea of what to add  to bdd_fsm_compute_reachable_states

//--- code
bdd_ptr tmp = bdd_and_abstract(self->dd, reachable_states, strict_superset_relation,BddEnc_get_state_vars_cube);
//probably have to somehow do renaming here.
supersets_in_reachable = BddEnc_next_state_var_to_state_var(self->enc,tmp);
//not quite positive on the abstraction usage yet
bdd_ptr not_supersets_in_reachable = bdd_not(self->dd, supersets_in_reachable);
bdd_and_accumulate(self->dd,  reachable_states, not_supersets_in_reachable);


This expression can then be converted as a BDD.


Alternatively, as a BDD operation (there are probably a couple of
bdd_free missing - please check the signatures of the respective
functions):

bdd_ptr cube = BddEnc_get_state_vars_cube(bdd_enc);
bdd_ptr ssr_bdd = bdd_one(dd);
bdd_ptr tmp = bdd_zero(dd);
bdd_ptr iter = bdd_dup(cube);

while(bdd_is_not_one(iter)) {
 bdd_ptr c1, c2, next_var;
 var = bdd_new_var_with_index(dd, bdd_index(dd, iter));
 iter = bdd_then(iter);

 next_var = BddEnc_shift_current_to_next(bdd_enc, var);
 c1 = bdd_implies(dd, var, next_var);
 bdd_and_accumulate(dd, &ssr_bdd, c1);
 bdd_free(dd, c1);

 c1 = bdd_not(dd, var);
 c2 = bdd_and(dd, c1, next_var);
 bdd_free(dd, c1);
 bdd_or_accumulate(dd, &tmp, c2);
 bdd_free(dd, next_var);
}
bdd_and_accumulate(dd, &ssr_bdd, tmp);
bdd_free(dd, tmp);
bdd_free(dd, cube);



Probably you just didn't write it here, so just in case: you could do
early termination for the universality check, i.e., move lines 9/10 in
algo 1 inside the while loop and do line 12 unconditionally after the
while loop.
