예제 #1
0
def tuple2fts(S, S0, AP, L, Act, trans, name='fts',
              prepend_str=None):
    """Create a Finite Transition System from a tuple of fields.

    Hint
    ====
    To remember the arg order:

    1) it starts with states (S0 requires S before it is defined)

    2) continues with the pair (AP, L), because states are more
    fundamental than transitions
    (transitions require states to be defined)
    and because the state labeling L requires AP to be defined.

    3) ends with the pair (Act, trans), because transitions in trans
    require actions in Act to be defined.

    See Also
    ========
    L{tuple2ba}

    @param S: set of states
    @type S: iterable of hashables

    @param S0: set of initial states, must be \\subset S
    @type S0: iterable of elements from S

    @param AP: set of Atomic Propositions for state labeling:
            L: S-> 2^AP
    @type AP: iterable of hashables

    @param L: state labeling definition
    @type L: iterable of (state, AP_label) pairs:
        [(state0, {'p'} ), ...]
        | None, to skip state labeling.

    @param Act: set of Actions for edge labeling:
            R: E-> Act
    @type Act: iterable of hashables

    @param trans: transition relation
    @type trans: list of triples: [(from_state, to_state, act), ...]
        where act \\in Act

    @param name: used for file export
    @type name: str
    """
    def pair_labels_with_states(states, state_labeling):
        if state_labeling is None:
            return
        if not isinstance(state_labeling, Iterable):
            raise TypeError('State labeling function: L->2^AP must be '
                            'defined using an Iterable.')
        state_label_pairs = True
        # cannot be caught by try below
        if isinstance(state_labeling[0], str):
            state_label_pairs = False
        if state_labeling[0] is None:
            state_label_pairs = False
        try:
            (state, ap_label) = state_labeling[0]
        except:
            state_label_pairs = False
        if state_label_pairs:
            return state_labeling
        logger.debug('State labeling L not tuples (state, ap_label),\n'
                     'zipping with states S...\n')
        state_labeling = zip(states, state_labeling)
        return state_labeling
    # args
    if not isinstance(S, Iterable):
        raise TypeError('States S must be iterable, even for single state.')
    # convention
    if not isinstance(S0, Iterable) or isinstance(S0, str):
        S0 = [S0]
    # comprehensive names
    states = S
    initial_states = S0
    ap = AP
    state_labeling = pair_labels_with_states(states, L)
    actions = Act
    transitions = trans
    # prepending states with given str
    if prepend_str:
        logger.debug('Given string:\n\t' + str(prepend_str) + '\n' +
                     'will be prepended to all states.')
    states = prepend_with(states, prepend_str)
    initial_states = prepend_with(initial_states, prepend_str)

    ts = FTS()
    ts.name = name

    ts.states.add_from(states)
    ts.states.initial |= initial_states

    ts.atomic_propositions |= ap

    # note: verbosity before actions below
    # to avoid screening by possible error caused by action

    # state labeling assigned ?
    if state_labeling is not None:
        for state, ap_label in state_labeling:
            if ap_label is None:
                ap_label = set()
            ap_label = str2singleton(ap_label)
            state = prepend_str + str(state)
            logger.debug('Labeling state:\n\t' + str(state) + '\n' +
                         'with label:\n\t' + str(ap_label) + '\n')
            ts.states[state]['ap'] = ap_label
    # any transition labeling ?
    if actions is None:
        for from_state, to_state in transitions:
            (from_state, to_state) = prepend_with([from_state, to_state],
                                                  prepend_str)
            logger.debug('Added unlabeled edge:\n\t' + str(from_state) +
                         '--->' + str(to_state) + '\n')
            ts.transitions.add(from_state, to_state)
    else:
        ts.actions |= actions
        for from_state, to_state, act in transitions:
            (from_state, to_state) = prepend_with([from_state, to_state],
                                                  prepend_str)
            logger.debug(
                'Added labeled edge (=transition):\n\t' +
                str(from_state) + '---[' + str(act) + ']--->' +
                str(to_state) + '\n')
            ts.transitions.add(from_state, to_state, actions=act)
    return ts
예제 #2
0
def tuple2ba(S,
             S0,
             Sa,
             Sigma_or_AP,
             trans,
             name='ba',
             prepend_str=None,
             atomic_proposition_based=True):
    """Create a Buchi Automaton from a tuple of fields.

    defines Buchi Automaton by a tuple (S, S0, Sa, \\Sigma, trans)
    (maybe replacing \\Sigma by AP since it is an AP-based BA ?)

    See Also
    ========
    L{tuple2fts}

    @param S: set of states
    @param S0: set of initial states, must be \\subset S
    @param Sa: set of accepting states
    @param Sigma_or_AP: Sigma = alphabet
    @param trans: transition relation, represented by list of triples::
            [(from_state, to_state, guard), ...]
    where guard \\in \\Sigma.

    @param name: used for file export
    @type name: str

    @rtype: L{BuchiAutomaton}
    """
    # args
    if not isinstance(S, Iterable):
        raise TypeError('States S must be iterable, even for single state.')
    if not isinstance(S0, Iterable) or isinstance(S0, str):
        S0 = [S0]
    if not isinstance(Sa, Iterable) or isinstance(Sa, str):
        Sa = [Sa]
    # comprehensive names
    states = S
    initial_states = S0
    accepting_states = Sa
    alphabet_or_ap = Sigma_or_AP
    transitions = trans
    # prepending states with given str
    if prepend_str:
        logger.debug('Given string:\n\t' + str(prepend_str) + '\n' +
                     'will be prepended to all states.')
    states = prepend_with(states, prepend_str)
    initial_states = prepend_with(initial_states, prepend_str)
    accepting_states = prepend_with(accepting_states, prepend_str)

    ba = BuchiAutomaton(atomic_proposition_based=atomic_proposition_based)
    ba.name = name

    ba.states.add_from(states)
    ba.states.initial |= initial_states
    ba.states.accepting |= accepting_states

    if atomic_proposition_based:
        ba.alphabet.math_set |= alphabet_or_ap
    else:
        ba.alphabet.add(alphabet_or_ap)
    for transition in transitions:
        (from_state, to_state, guard) = transition
        [from_state, to_state] = prepend_with([from_state, to_state],
                                              prepend_str)
        # convention
        if atomic_proposition_based:
            if guard is None:
                guard = set()
            guard = str2singleton(guard)
        ba.transitions.add(from_state, to_state, letter=guard)
    return ba
def prepend_with_check(states, prepend_str, expected):
    assert labeled_graphs.prepend_with(states, prepend_str) == expected
예제 #4
0
def tuple2fts(S, S0, AP, L, Act, trans, name='fts',
              prepend_str=None):
    """Create a Finite Transition System from a tuple of fields.

    Hint
    ====
    To remember the arg order:

    1) it starts with states (S0 requires S before it is defined)

    2) continues with the pair (AP, L), because states are more
    fundamental than transitions
    (transitions require states to be defined)
    and because the state labeling L requires AP to be defined.

    3) ends with the pair (Act, trans), because transitions in trans
    require actions in Act to be defined.

    See Also
    ========
    L{tuple2ba}

    @param S: set of states
    @type S: iterable of hashables

    @param S0: set of initial states, must be \\subset S
    @type S0: iterable of elements from S

    @param AP: set of Atomic Propositions for state labeling:
            L: S-> 2^AP
    @type AP: iterable of hashables

    @param L: state labeling definition
    @type L: iterable of (state, AP_label) pairs:
        [(state0, {'p'} ), ...]
        | None, to skip state labeling.

    @param Act: set of Actions for edge labeling:
            R: E-> Act
    @type Act: iterable of hashables

    @param trans: transition relation
    @type trans: list of triples: [(from_state, to_state, act), ...]
        where act \\in Act

    @param name: used for file export
    @type name: str
    """
    def pair_labels_with_states(states, state_labeling):
        if state_labeling is None:
            return
        if not isinstance(state_labeling, Iterable):
            raise TypeError('State labeling function: L->2^AP must be '
                            'defined using an Iterable.')
        state_label_pairs = True
        # cannot be caught by try below
        if isinstance(state_labeling[0], str):
            state_label_pairs = False
        if state_labeling[0] is None:
            state_label_pairs = False
        try:
            (state, ap_label) = state_labeling[0]
        except:
            state_label_pairs = False
        if state_label_pairs:
            return state_labeling
        logger.debug('State labeling L not tuples (state, ap_label),\n'
                     'zipping with states S...\n')
        state_labeling = zip(states, state_labeling)
        return state_labeling
    # args
    if not isinstance(S, Iterable):
        raise TypeError('States S must be iterable, even for single state.')
    # convention
    if not isinstance(S0, Iterable) or isinstance(S0, str):
        S0 = [S0]
    # comprehensive names
    states = S
    initial_states = S0
    ap = AP
    state_labeling = pair_labels_with_states(states, L)
    actions = Act
    transitions = trans
    # prepending states with given str
    if prepend_str:
        logger.debug('Given string:\n\t' + str(prepend_str) + '\n' +
                     'will be prepended to all states.')
    states = prepend_with(states, prepend_str)
    initial_states = prepend_with(initial_states, prepend_str)

    ts = FTS()
    ts.name = name

    ts.states.add_from(states)
    ts.states.initial |= initial_states

    ts.atomic_propositions |= ap

    # note: verbosity before actions below
    # to avoid screening by possible error caused by action

    # state labeling assigned ?
    if state_labeling is not None:
        for state, ap_label in state_labeling:
            if ap_label is None:
                ap_label = set()
            ap_label = str2singleton(ap_label)
            state = prepend_str + str(state)
            logger.debug('Labeling state:\n\t' + str(state) + '\n' +
                         'with label:\n\t' + str(ap_label) + '\n')
            ts.states[state]['ap'] = ap_label
    # any transition labeling ?
    if actions is None:
        for from_state, to_state in transitions:
            (from_state, to_state) = prepend_with([from_state, to_state],
                                                  prepend_str)
            logger.debug('Added unlabeled edge:\n\t' + str(from_state) +
                         '--->' + str(to_state) + '\n')
            ts.transitions.add(from_state, to_state)
    else:
        ts.actions |= actions
        for from_state, to_state, act in transitions:
            (from_state, to_state) = prepend_with([from_state, to_state],
                                                  prepend_str)
            logger.debug(
                'Added labeled edge (=transition):\n\t' +
                str(from_state) + '---[' + str(act) + ']--->' +
                str(to_state) + '\n')
            ts.transitions.add(from_state, to_state, actions=act)
    return ts
def prepend_with_check(states, prepend_str, expected):
    assert labeled_graphs.prepend_with(states, prepend_str) == expected
예제 #6
0
def tuple2ba(S, S0, Sa, Sigma_or_AP, trans, name='ba', prepend_str=None,
             atomic_proposition_based=True):
    """Create a Buchi Automaton from a tuple of fields.

    defines Buchi Automaton by a tuple (S, S0, Sa, \\Sigma, trans)
    (maybe replacing \\Sigma by AP since it is an AP-based BA ?)

    See Also
    ========
    L{tuple2fts}

    @param S: set of states
    @param S0: set of initial states, must be \\subset S
    @param Sa: set of accepting states
    @param Sigma_or_AP: Sigma = alphabet
    @param trans: transition relation, represented by list of triples::
            [(from_state, to_state, guard), ...]
    where guard \\in \\Sigma.

    @param name: used for file export
    @type name: str

    @rtype: L{BuchiAutomaton}
    """
    # args
    if not isinstance(S, Iterable):
        raise TypeError('States S must be iterable, even for single state.')
    if not isinstance(S0, Iterable) or isinstance(S0, str):
        S0 = [S0]
    if not isinstance(Sa, Iterable) or isinstance(Sa, str):
        Sa = [Sa]
    # comprehensive names
    states = S
    initial_states = S0
    accepting_states = Sa
    alphabet_or_ap = Sigma_or_AP
    transitions = trans
    # prepending states with given str
    if prepend_str:
        logger.debug('Given string:\n\t' + str(prepend_str) + '\n' +
                     'will be prepended to all states.')
    states = prepend_with(states, prepend_str)
    initial_states = prepend_with(initial_states, prepend_str)
    accepting_states = prepend_with(accepting_states, prepend_str)

    ba = BuchiAutomaton(atomic_proposition_based=atomic_proposition_based)
    ba.name = name

    ba.states.add_from(states)
    ba.states.initial |= initial_states
    ba.states.accepting |= accepting_states

    if atomic_proposition_based:
        ba.alphabet.math_set |= alphabet_or_ap
    else:
        ba.alphabet.add(alphabet_or_ap)
    for transition in transitions:
        (from_state, to_state, guard) = transition
        [from_state, to_state] = prepend_with([from_state, to_state],
                                              prepend_str)
        # convention
        if atomic_proposition_based:
            if guard is None:
                guard = set()
            guard = str2singleton(guard)
        ba.transitions.add(from_state, to_state, letter=guard)
    return ba