Esempio n. 1
0
    def eval_lambda(f, d, is_formula=True):
        """
        Evaluates lambda function f

        Examples:

        sage: assert InvMPP.eval_lambda('lambda x,y: max(x - 13,-3) >= y', {'x':11,'y':100}) == False

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 5', {'x':2,'y':3,'d':7})

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 6', {'x':2,'y':3,'d':7}) == False


        sage: assert InvMPP.eval_lambda('lambda x,y: x+y', {'x':2,'y':3,'d':7}, is_formula=False) == 5
        


        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 10 or x + y == 5', {'x':2,'y':3,'d':7})

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 1 or x + y == 2', {'x':2,'y':3,'d':7}) == False

        """
        if __debug__:
            assert is_str(f) and 'lambda' in f, f
            assert is_dict(d), d
            assert all(is_str(k) for k in d), d.keys()

        f = sage_eval(f)
        vs = f.func_code.co_varnames
        assert set(vs) <= set(d.keys()), (vs, d.keys())

        #if d has more keys than variables in f then remove those extra keys
        d = dict([(k, d[k]) for k in vs])
        rs = f(**d)
        return bool(rs) if is_formula else rs
Esempio n. 2
0
    def slice_defs(prop, defs, assumes_state, assumes_trans):
        """
        Return a new (potentially empty) def dictionary from the old one
        consisting of only necessary variable definitions to prove property
        """
        if __debug__:
            assert is_dict(defs), defs
            assert is_list(assumes_state), assumes_state
            assert is_list(assumes_trans), assumes_trans

        fs = [prop] + assumes_state + assumes_trans
        fs = [f for f in fs if is_expr(f)]

        vs = [get_vars(f) for f in fs]
        vs = [cur(v_) if is_pre(v_) else v_ for v_ in vflatten(vs)]
        vs = vset(vs, fhash)

        vs_ = [Prog.get_influence_vs(v, defs, []) for v in vs]
        vs = vset(vflatten(vs + vs_), fhash)

        a_defs = OrderedDict()
        for v in vs:
            k = fhash(v)
            if k in defs:
                a_defs[k] = defs[k]

        return a_defs
Esempio n. 3
0
    def eval_lambda(f, d, is_formula=True):
        """
        Evaluates lambda function f

        Examples:

        sage: assert InvMPP.eval_lambda('lambda x,y: max(x - 13,-3) >= y', {'x':11,'y':100}) == False

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 5', {'x':2,'y':3,'d':7})

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 6', {'x':2,'y':3,'d':7}) == False


        sage: assert InvMPP.eval_lambda('lambda x,y: x+y', {'x':2,'y':3,'d':7}, is_formula=False) == 5
        


        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 10 or x + y == 5', {'x':2,'y':3,'d':7})

        sage: assert InvMPP.eval_lambda('lambda x,y: x+y == 1 or x + y == 2', {'x':2,'y':3,'d':7}) == False

        """
        if __debug__:
            assert is_str(f) and 'lambda' in f, f
            assert is_dict(d), d
            assert all(is_str(k) for k in d), d.keys()

        f = sage_eval(f)
        vs = f.func_code.co_varnames
        assert set(vs) <= set(d.keys()), (vs,d.keys())

        #if d has more keys than variables in f then remove those extra keys
        d=dict([(k,d[k]) for k in vs])
        rs = f(**d)
        return bool(rs) if is_formula else rs
Esempio n. 4
0
    def __init__(self, init_conds, defs, input_vars, assumes):
        """
        This class models a program using
        1. initial condition
        2. transition (definitions of updated variables)
        3. assumptions

        Input variables:
        - init_cond: list of initial conditions
        e.g. [Block == Off,Reset == On,WaterPres == wp_init_val,
        Overridden == False,SafetyInjection == On,Pressure == TooLow]

        - defs: a dictionary consisting variables being updated by
        the transition

        - input_vars: variables that are INDEPDENT.
        SCR programs don't have these, because input (monitored) vars
        are dependent due to OIA

        - assumes: list of assumptions
        Two types of assumptions:
        (1) state assumes: those for each *state*
        e.g.
        And(0 <= WaterPres,WaterPres < 2000): WaterPres is in range 0,2000
        at any state

        (2) trans assumes: those for each *transition*
        e.g.
        One Input Assumption asserts only 1 var can changed at a time
        or
        And(pre(WaterPres) - 10 <= WaterPres,
        WaterPres <= pre(WaterPres) + 10)
        """

        if __debug__:
            assert is_list(init_conds) and \
                all(is_state(c) for c in init_conds), init_conds

            assert is_dict(defs) and \
                all(is_expr(v) for v in defs.values()), defs

            assert is_list(input_vars) and \
                all(is_expr_var(v) for v in input_vars), input_vars

            assert is_list(assumes) and \
                all(is_expr(a) for a in assumes), assumes

        self.defs = defs
        self.init_conds = init_conds
        self.input_vars = input_vars

        self.assumes_state = []
        self.assumes_trans = []

        for a in assumes:
            Prog.append_f(a, self.assumes_state, self.assumes_trans)

        #Known invariants (lemmas). Use add_inv() to add an inv as lemma
        self.invs_state = []
        self.invs_trans = []
Esempio n. 5
0
    def __init__(self, p):
        """
        Ex:
        ('lambda A, B, A0: (A[A0]) + (-7*B[2*A0]) + (-3*A0) == 0', 
        [{'A0': 2}, {'A0': 0}, {'A0': 1}])
        """

        if __debug__:
            assert (is_tuple(p) and len(p) == 2 and is_str(p[0])
                    and all(s in p[0] for s in ['lambda', '[', ']'])
                    and is_list(p[1]) and all(is_dict(v) for v in p[1])), p

        super(InvFlatArray, self).__init__(p[0].strip())
        self.idx_info = p[1]
Esempio n. 6
0
    def __init__(self, p): 
        """
        Ex:
        ('lambda A, B, A0: (A[A0]) + (-7*B[2*A0]) + (-3*A0) == 0', 
        [{'A0': 2}, {'A0': 0}, {'A0': 1}])
        """

        if __debug__:
            assert (is_tuple(p) and len(p)==2 and 
                    is_str(p[0]) and 
                    all(s in p[0] for s in ['lambda','[' ,']']) and
                    is_list(p[1]) and all(is_dict(v) for v in p[1])), p
            
        super(InvFlatArray,self).__init__(p[0].strip())
        self.idx_info = p[1]
Esempio n. 7
0
    def __init__(self, terms, tcs, xinfo):
        assert is_dict(xinfo), xinfo

        logger.info('*** {} ***'.format(self.__class__.__name__))

        self.terms = terms
        self.tcs = tcs
        self.xinfo = xinfo

        self.do_refine = True
        self.tcs_extra = []
        self._sols = []

        logger.debug('|terms|={}, |tcs|={}'.format(len(self.terms),
                                                   len(self.tcs)))
Esempio n. 8
0
    def preprocess(self, xinfo):
        """
        Preprocess input data
        1) transforms external functions to special arrays
        1) change arr repr to value->index repr to speed up arr idx lookup
        2) generate nodes
        """
        if __debug__:
            assert is_dict(xinfo), xinfo
        
        evs = ExtFun.gen_extvars(xinfo=xinfo)
        #arrays only
        evs = [OrderedDict([(k,v) for k,v in ev.iteritems() if is_list(v)])
               for ev in evs]
        evs = Miscs.keys_to_str(evs)
        
        if not is_empty(evs): #add to traces
            self.tcs = [merge_dict(evs + [tc]) for tc in self.tcs]
            self.tcs_extra = [merge_dict(evs + [tc]) for tc in self.tcs_extra]

        
        mytcs = []
        for tc in self.tcs:
            #arrs reprent ext funs (already in new format)
            efs = ExtFun.gen_extfuns(tc=tc,xinfo=xinfo)
            
            #convert normal arr format to new format
            arrs = [(k, Miscs.getListIdxs(v)) for k,v in tc.items()] 
            arrs = OrderedDict(arrs)
            
            d = merge_dict(efs + [arrs])
            mytcs.append(d)
         
 
        self.tcs = mytcs

        self.trees = [Tree({'root':k,
                            'children': [None] * len(c.values()[0][0]),
                            'commute': ExtFun(k).is_commute()})
                      for k,c in self.tcs[0].items()]
        
        self.xinfo = xinfo
Esempio n. 9
0
    def eval_lambda(f, idx_info, tc):
        """
        Evaluate array expression p, e.g. p:  A[i,j,k]=B[2i+3j+k]

        if idx_info is specified then only test p on the idxs from idx_info


        Assumes:
        the first array in lambda is the pivot
        lambda A,B,i,j,k: ...  =>  i,j,k  belong to A



        inv = 'lambda B,C,D,i,j: B[i][j]=C[D[2i+3]]'
        returns true if inv is true on tc

        Examples:

        sage: var('a,b,c,i,j')
        (a, b, c, i, j)

        sage: InvArray.eval_lambda('lambda a,b,c,i,j: a[i][j]==2*b[i]+c[j]', None, {'a':[[4,-5],[20,11]],'b':[1,9],'c':[2,-7]})
        True

        sage: InvArray.eval_lambda('lambda c,a,b,xor,i: c[i] == xor(a[i],b[i])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 334, 79, 281]})
        False

        sage: InvArray.eval_lambda('lambda c,a,b,xor,i1: c[i1] == xor(a[i1],b[i1])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 134, 79, 241]})
        True


        sage: InvArray.eval_lambda('lambda rvu, t, rvu1, rvu0: (rvu[rvu0][rvu1]) + (-t[4*rvu0 + rvu1]) == 0', None, {'t': [28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], 'rvu': [[28, 131, 11, 85], [133, 46, 179, 20], [227, 148, 225, 197], [38, 221, 221, 126]]})
        True

        #The following illustrate the use of idxVals,
        #i.e. p is only true under certain array rages

        sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', None, tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]})
        False

        sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', idx_info = [{'st0': 0, 'st1': 0}, {'st0': 0, 'st1': 1}, {'st0': 2, 'st1': 2}, {'st0': 2, 'st1': 3}, {'st0': 3, 'st1': 0}, {'st0': 3, 'st1': 1}, {'st0': 3, 'st1': 2}, {'st0': 3, 'st1': 3}, {'st0': 0, 'st1': 2}, {'st0': 0, 'st1': 3}, {'st0': 1, 'st1': 0}, {'st0': 1, 'st1': 1}, {'st0': 1, 'st1': 2}, {'st0': 1, 'st1': 3}, {'st0': 2, 'st1': 0}, {'st0': 2, 'st1': 1}], tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]})
        True

        """
        """
        Note: sage_eval vs eval
        sage_eval works on str of the format 'lambda x,y: 2*x+y'
        whereas eval works on str of the format 2*x+y directly (no lambda)
        Also, the result of sage_eval can apply on dicts whose keys are str
        e.g.  f(**{'x':2,'y':3})
        whereas the result of eval applies on dict whose keys are variables
        e.g.  f(**{x:2,y:3})
        """

        if __debug__:
            assert is_str(f) and 'lambda' in f, f
            assert (idx_info is None
                    or is_list(idx_info) and all(is_dict(v)
                                                 for v in idx_info)), indx_info
            assert is_dict(tc), tc
            assert all(is_str(k) for k in tc), tc.keys()

        f = sage_eval(f)
        vs = f.func_code.co_varnames

        arrs = [v for v in vs if v in tc]  #A,B
        extfuns = [v for v in vs if v in ExtFun.efdict]
        idxStr = [v for v in vs if v not in arrs + extfuns]  #i,j,k

        d_tc = dict([(v, tc[v]) for v in arrs])
        d_extfun = dict([(v, ExtFun(v).get_fun()) for v in extfuns])
        d_ = merge_dict([d_tc, d_extfun])

        if idx_info is None:  #obtain idxsVals from the pivot array
            pivotContents = tc[arrs[0]]
            idxVals = [idx for idx, _ in Miscs.travel(pivotContents)]
            idx_info = [dict(zip(idxStr, idxV)) for idxV in idxVals]

        ds = [merge_dict([d_, idx_info_]) for idx_info_ in idx_info]

        try:
            return all(f(**d) for d in ds)
        except IndexError:
            return False
        except TypeError:
            return False
        except NameError as msg:
            logger.warn(msg)
            return False
Esempio n. 10
0
    def eval_lambda(f, idx_info, tc):
        """
        Evaluate array expression p, e.g. p:  A[i,j,k]=B[2i+3j+k]

        if idx_info is specified then only test p on the idxs from idx_info


        Assumes:
        the first array in lambda is the pivot
        lambda A,B,i,j,k: ...  =>  i,j,k  belong to A



        inv = 'lambda B,C,D,i,j: B[i][j]=C[D[2i+3]]'
        returns true if inv is true on tc

        Examples:

        sage: var('a,b,c,i,j')
        (a, b, c, i, j)

        sage: InvArray.eval_lambda('lambda a,b,c,i,j: a[i][j]==2*b[i]+c[j]', None, {'a':[[4,-5],[20,11]],'b':[1,9],'c':[2,-7]})
        True

        sage: InvArray.eval_lambda('lambda c,a,b,xor,i: c[i] == xor(a[i],b[i])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 334, 79, 281]})
        False

        sage: InvArray.eval_lambda('lambda c,a,b,xor,i1: c[i1] == xor(a[i1],b[i1])', None, {'a': [147, 156, 184, 76], 'b': [51, 26, 247, 189], 'c': [160, 134, 79, 241]})
        True


        sage: InvArray.eval_lambda('lambda rvu, t, rvu1, rvu0: (rvu[rvu0][rvu1]) + (-t[4*rvu0 + rvu1]) == 0', None, {'t': [28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], 'rvu': [[28, 131, 11, 85], [133, 46, 179, 20], [227, 148, 225, 197], [38, 221, 221, 126]]})
        True

        #The following illustrate the use of idxVals,
        #i.e. p is only true under certain array rages

        sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', None, tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]})
        False

        sage: InvArray.eval_lambda('lambda st, rvu, st0, st1: (-st[st0][st1]) + (rvu[4*st0 + st1]) == 0', idx_info = [{'st0': 0, 'st1': 0}, {'st0': 0, 'st1': 1}, {'st0': 2, 'st1': 2}, {'st0': 2, 'st1': 3}, {'st0': 3, 'st1': 0}, {'st0': 3, 'st1': 1}, {'st0': 3, 'st1': 2}, {'st0': 3, 'st1': 3}, {'st0': 0, 'st1': 2}, {'st0': 0, 'st1': 3}, {'st0': 1, 'st1': 0}, {'st0': 1, 'st1': 1}, {'st0': 1, 'st1': 2}, {'st0': 1, 'st1': 3}, {'st0': 2, 'st1': 0}, {'st0': 2, 'st1': 1}], tc = {'rvu': [28, 131, 11, 85, 193, 124, 103, 215, 66, 26, 68, 54, 176, 102, 15, 237], 'st': [[28, 131, 11, 85, 133, 46, 179, 20, 227, 148, 225, 197, 38, 221, 221, 126], [193, 124, 103, 215, 106, 229, 162, 168, 166, 78, 144, 234, 199, 254, 152, 250], [66, 26, 68, 54, 206, 16, 155, 248, 231, 198, 240, 43, 208, 205, 213, 26], [176, 102, 15, 237, 49, 141, 213, 97, 137, 155, 50, 243, 112, 51, 124, 107]]})
        True

        """


        """
        Note: sage_eval vs eval
        sage_eval works on str of the format 'lambda x,y: 2*x+y'
        whereas eval works on str of the format 2*x+y directly (no lambda)
        Also, the result of sage_eval can apply on dicts whose keys are str
        e.g.  f(**{'x':2,'y':3})
        whereas the result of eval applies on dict whose keys are variables
        e.g.  f(**{x:2,y:3})
        """

        if __debug__:
            assert is_str(f) and 'lambda' in f, f
            assert (idx_info is None or 
                    is_list(idx_info) and all(is_dict(v) for v in idx_info)), indx_info
            assert is_dict(tc), tc
            assert all(is_str(k) for k in tc), tc.keys()

        f = sage_eval(f)
        vs = f.func_code.co_varnames

        arrs    = [v for v in vs if v in tc]        #A,B
        extfuns = [v for v in vs if v in ExtFun.efdict]
        idxStr  = [v for v in vs if v not in arrs+extfuns]  #i,j,k

        d_tc    = dict([(v,tc[v]) for v in arrs])
        d_extfun= dict([(v,ExtFun(v).get_fun()) for v in extfuns])
        d_      = merge_dict([d_tc,d_extfun])

        if idx_info is None: #obtain idxsVals from the pivot array
            pivotContents = tc[arrs[0]]
            idxVals  = [idx for idx,_ in Miscs.travel(pivotContents)]
            idx_info = [dict(zip(idxStr,idxV)) for idxV in idxVals]

        ds = [merge_dict([d_, idx_info_]) for idx_info_ in idx_info]

        try:
            return all(f(**d) for d in ds)
        except IndexError:
            return False
        except TypeError:
            return False
        except NameError as msg:
            logger.warn(msg)
            return False
Esempio n. 11
0
    def compute_new_trace(d, ainfo, tsinfo):
        """
        Convert array elements into new variables and generate traces from these.

        Examples:
        sage: var('A B')
        (A, B)
        sage: ainfo = {}
        sage: tc = FlatArray.compute_new_trace({A: [0,1,2], B: [[0, 1], [2, 3]]}, ainfo, {})
        sage: sorted(tc.items(),key= lambda (x,_) : str(x))
        [(A_0, 0), (A_1, 1), (A_2, 2), (B_0_0, 0), (B_0_1, 1), (B_1_0, 2), (B_1_1, 3)]
        sage: sorted(ainfo.items(), key=lambda (x,_): str(x))
        [(A_0, {'idx_': [(A0, 0)], 'name': 'A'}),
         (A_1, {'idx_': [(A0, 1)], 'name': 'A'}),
         (A_2, {'idx_': [(A0, 2)], 'name': 'A'}),
         (B_0_0, {'idx_': [(B0, 0), (B1, 0)], 'name': 'B'}),
         (B_0_1, {'idx_': [(B0, 0), (B1, 1)], 'name': 'B'}),
         (B_1_0, {'idx_': [(B0, 1), (B1, 0)], 'name': 'B'}),
         (B_1_1, {'idx_': [(B0, 1), (B1, 1)], 'name': 'B'})]

        
        sage: ainfo = {}
        sage: tc = FlatArray.compute_new_trace({'A':[['a','b'],['c','d'],['e','f',['z','w']]], \
        'B':[1,2,[7,8]],'C':[100]}, ainfo, {})
        sage: sorted(tc.items(),key= lambda (x,_) : str(x))
        [(A_0_0, 'a'), (A_0_1, 'b'), (A_1_0, 'c'), (A_1_1, 'd'), 
        (A_2_0, 'e'), (A_2_1, 'f'), (A_2_2_0, 'z'), (A_2_2_1, 'w'), 
        (B_0, 1), (B_1, 2), (B_2_0, 7), (B_2_1, 8), (C_0, 100)]

        sage: sorted(ainfo.items(), key=lambda (x,_): str(x))
        [(A_0_0, {'idx_': [(A0, 0), (A1, 0)], 'name': 'A'}),
         (A_0_1, {'idx_': [(A0, 0), (A1, 1)], 'name': 'A'}),
         (A_1_0, {'idx_': [(A0, 1), (A1, 0)], 'name': 'A'}),
         (A_1_1, {'idx_': [(A0, 1), (A1, 1)], 'name': 'A'}),
         (A_2_0, {'idx_': [(A0, 2), (A1, 0)], 'name': 'A'}),
         (A_2_1, {'idx_': [(A0, 2), (A1, 1)], 'name': 'A'}),
         (A_2_2_0, {'idx_': [(A0, 2), (A1, 2), (A2, 0)], 'name': 'A'}),
         (A_2_2_1, {'idx_': [(A0, 2), (A1, 2), (A2, 1)], 'name': 'A'}),
         (B_0, {'idx_': [(B0, 0)], 'name': 'B'}),
         (B_1, {'idx_': [(B0, 1)], 'name': 'B'}),
         (B_2_0, {'idx_': [(B0, 2), (B1, 0)], 'name': 'B'}),
         (B_2_1, {'idx_': [(B0, 2), (B1, 1)], 'name': 'B'}),
         (C_0, {'idx_': [(C0, 0)], 'name': 'C'})]
 
        """
        def compute_traces(aname, acontents, ainfo, tsinfo):
            vi = Miscs.travel(acontents)
            vals = Miscs.getVals(vi)
            idxs = Miscs.getIdxs(vi)
            aname = str(aname)
            newvars = [var(aname + '_' + list_str(idx, '_')) for idx in idxs]

            if aname not in tsinfo:
                tsinfo[aname] = newvars
            else:
                assert tsinfo[aname] == newvars
            
            dVals = dict(zip(newvars,vals)) #{A_0_0_1:'w'}
            for nv,idx in zip(newvars,idxs):
                if nv not in ainfo:
                    idx_ = zip([var('{}{}'.format(aname,li))
                                 for li in srange(len(idx))],idx)
                    ainfo[nv]={'name':aname, 'idx_':idx_}

            return dVals

        if __debug__:
            assert is_dict(d), d 
            assert is_dict(ainfo), d

        tcs = [compute_traces(k,v,ainfo,tsinfo) for k,v in d.iteritems()]
        tcs = merge_dict(tcs)
        return tcs
Esempio n. 12
0
    def get_influence_vs(v, defs, rs):
        """
        Return a list of variables that influences v
        (i.e. the definition of v depends on these variables)

        >>> from z3 import Bools, BoolVal
        >>> from scr_miscs import mk_OIA

        >>> s,t = Bools('s t')
        >>> x,y,z = Bools('x y z')
        >>> vs = [x,y,z]
        >>> o = mk_OIA(vs)
        >>> vv = [o,o,And(o,s)]
        >>> vs2 = [t]
        >>> vv2 = [BoolVal(True)]
        >>> vs_k = map(fhash,vs + vs2)
        >>> vs_v =vv + vv2
        >>> defs = OrderedDict(zip(vs_k,vs_v))
        >>> print Prog.get_influence_vs(x,defs,rs=[])
        [s, y, z]

        #>>> print Prog.get_influence_vs(x,defs,assumes=[x==s],rs=[])
        #[s, y, z]

        #>>> print Prog.get_influence_vs(x,defs,assumes=[y==t],rs=[])
        #[s, y, z, t]


        """
        if __debug__:
            assert is_expr_var(v), v
            assert is_dict(defs), defs
            assert is_list(rs), rs

        if is_pre(v):
            v = cur(v)

        #return if already in the result set
        if expr_member(v, rs):
            return rs

        try:
            vs = get_vars(defs[fhash(v)])
            #print vs

        except KeyError:
            return rs

        rs = rs + [v]

        #convert v_pre to v
        vs = [cur(v_) if is_pre(v_) else v_ for v_ in vs]
        vs = vset(vs, fhash)

        for v_ in vs:
            rs_ = Prog.get_influence_vs(v_, defs, rs)
            rs = rs + rs_

        rs = rs + vs
        rs = vset(rs, fhash)

        #remove myself
        v_idx = map(fhash, rs).index(fhash(v))
        rs = rs[:v_idx] + rs[v_idx + 1:]
        return sorted(rs, key=str)