Exemple #1
0
def IntervalToTick(aut):
    tickaut = data_structure.Automaton(aut.alphabet, aut.collection)
    dictionary = {}
    tickaut.initial = tickaut.add_new_state(aut.initial.marked)
    dictionary[aut.initial] = tickaut.initial
    tovisit = [aut.initial]
    if 'tick' not in aut.collection.events:
        aut.collection.make_event('tick', False, True, False)
    tick = aut.collection.events['tick']
    infinity = float('inf')
    edgestoadd = []
    while len(tovisit) != 0:
        intstate = tovisit.pop()
        tickstate = dictionary[intstate]
        maxticks = max([edge.l if edge.r == infinity else edge.r + 1 for edge in intstate.get_outgoing()])
        tickstates = [tickstate] + [tickaut.add_new_state(tickstate.marked) for i in range(maxticks)]
        edgestoadd.extend([data_structure.Edge(tickstate[i], tickstate[i+1], tick) for i in range(maxticks)])
        edgestoadd.append(data_structure.Edge(tickstate[maxticks+1], tickstate[maxticks+1], tick))
        for edge in intstate.get_outgoing():
            if edge.succ not in dictionary:
                newstate = tickaut.add_new_state(edge.succ.marked)
                dictionary[edge.succ] = newstate
                tovisit.append(newstate)
            succstate = dictionary[edge.succ]
            l,r = edge.l, min(maxticks, edge.r)+1
            for i in range(l,r):
                edgestoadd.append(data_structure.Edge(tickstates[i], succstate, edge.label))
    tickaut.add_edges(edgestoadd)
    return tickaut
Exemple #2
0
def automaton_abstraction(aut):
    """
    Compute new automaton by means of bisimularity computation with reduced
    number of states.

    @param aut: Input automaton
    @type  aut: L{Automaton}

    @return: Reduced automaton
    @rtype: L{Automaton}
    """

    # Compute partition
    partition_list = bisimilarity_partition(aut)

    # Construct new automaton based on bisimularity results
    new_aut = data_structure.Automaton(aut.alphabet, aut.collection)
    new_aut.set_kind(aut.aut_kind)

    state_map = {}  # Mapping of old state -> new_state
    for number, partition in enumerate(partition_list):
        # Decide on marker property of the partition
        assert len(partition) > 0
        # Get a value from the set without modifying it
        state = iter(partition).next()

        new_state = new_aut.add_new_state(marked = state.marked, num = number)
        for state in partition:
            state_map[state] = new_state

    # Set initial state
    new_aut.initial = state_map[aut.initial]

    # Add edges
    #
    # Since the Automaton silently drops duplicate edges, we will have unique
    # edges
    for state in aut.get_states():
        for edge in state.get_outgoing():
            new_aut.add_edge_data(state_map[state], state_map[edge.succ],
                                  edge.label)

    # Clearing local data
    state_map.clear()

    return new_aut
def convert_ads_file(ads_fname, coll):
    """
    Load ADS file, convert it to internal data format, and return the result.

    @param ads_fname: Filename of the ADS file to load.
    @type  ads_fname: C{str}

    @param coll: Collection to store the events of the automaton.
    @type  coll: L{Collection}

    @return: Converted automaton.
    @rtype: L{Automaton}
    """
    handle = open(ads_fname, 'r')
    _name, state_size, marker_lines, vocal_states, trans = read_ads_file(handle)

    assert len(vocal_states) == 0 # Vocal states are not supported atm.

    # Construct/query events of the automaton.
    evts = {}
    observable = True
    for src, evtnum, dest in trans:
        if evtnum not in evts:
            evt = coll.make_event(str(evtnum), evtnum & 1, observable, False)
            evts[evtnum] = evt

    aut = data_structure.Automaton(set(evts.itervalues()), coll)

    if marker_lines == ['*']:
        marker_states = None    # All states are marker state.
    else:
        marker_states = set(marker_lines)

    # Construct all states in the automaton.
    for num in range(state_size):
        aut.add_new_state(marker_states is None or num in marker_states, num)

    aut.set_initial(aut.get_state(0))

    for src, evtnum, dest in trans:
        srcstate = aut.get_state(src)
        deststate = aut.get_state(dest)
        aut.add_edge_data(srcstate, deststate, evts[evtnum])

    return aut
Exemple #4
0
def prune_tree_automaton(wunfolded, weightmap):
    """
    Reduce the tree automaton L{wunfolded} by pruning away everything except
    the paths to the leafs with the lowest value.

    @param wunfolded: Weighted tree automaton.
    @type  wunfolded: L{WeightedAutomaton}

    @param weightmap: Mapping of weighted states to weight
                      (C{maxplus.INFINITE} for infinite).
    @type  weightmap: C{dict} of L{WeightedState} to C{int}/C{maxplus.INFINITE}

    @return: Pruned tree automaton.
    @rtype:  L{Automaton}

    @note: Weight at the edges is not used.
    """
    coll = wunfolded.collection
    pruned = data_structure.Automaton(wunfolded.alphabet, coll)
    ini_state = wunfolded.initial
    minval = weightmap[ini_state]
    assert minval is not None

    ini_s = pruned.add_new_state(ini_state.marked, ini_state.number)
    pruned.set_initial(ini_s)
    notdone = [ini_state]

    while len(notdone) > 0:
        state = notdone.pop()
        for edge in state.get_outgoing():
            assert weightmap[edge.succ] is not None  # Temp paranoia check
            if weightmap[edge.succ] is maxplus.INFINITE:
                continue  # Infinite weight is always bigger than minval

            if weightmap[edge.succ] <= minval:
                nst = pruned.add_new_state(edge.succ.marked, edge.succ.number)
                notdone.append(edge.succ)
                pruned.add_edge_data(pruned.get_state(state.number), nst,
                                     edge.label)
            else:
                assert weightmap[edge.succ] > minval

    return pruned
Exemple #5
0
def heap_unfold_product(aut_list, eventdata, heap_len, distances_to_marker, shortest_path):
    result_alphabet = set()
    for aut in aut_list:
        result_alphabet.update(aut.alphabet)
    plant = data_structure.Automaton(result_alphabet, aut_list[0].collection)
    mapping = {}
    heap_map = {}
    aut_resource_usage = calc_resource_usage(aut_list, eventdata, heap_len)
    initial_state_mapping = tuple(aut.initial for aut in aut_list)
    initial_state = plant.add_new_state(marker_calc(initial_state_mapping))
    plant.set_initial(initial_state)
    mapping[initial_state] = initial_state_mapping
    heap_map[initial_state] = maxplus.make_rowmat(0, heap_len)
    shortest_path_max = 0
    for comp, path in shortest_path.items():
        if path > shortest_path_max:
            shortest_path_max = path
    
    traverse(comp_list, plant, initial_state, mapping, heap_map, eventdata, aut_resource_usage, distances_to_marker, shortest_path_max)
    return plant
def construct_greedy_progressive_supervisor_epuck(aut, resources, progressive_events, triples, L):
  sup = data_structure.Automaton(set(aut.alphabet), aut.collection)
  dict = {}
  to_process = []
  f_index = find_index(triples, aut.initial, len(triples)-1)
  sup.initial = sup.add_new_state(aut.initial.marked)
  sup.initial.collisions = aut.initial.collisions
  dict[(aut.initial, f_index)] = sup.initial
  to_process.append((aut.initial, f_index))
  while (to_process):
    state, k = to_process.pop(0)
    sup_source = dict[(state, k)]
    theta, _, _ = triples[k][state]
    for edge in state.get_outgoing():
      if edge.label not in progressive_events:
        f_index = find_index(triples, edge.succ, len(triples)-1)
        if (edge.succ, f_index) not in dict:
          dict[(edge.succ, f_index)] = sup.add_new_state(edge.succ.marked)
          to_process.append((edge.succ, f_index))
        sup_target = dict[(edge.succ, f_index)]
        sup.add_edge_data(sup_source, sup_target, edge.label)
      else:
        f_index = find_index(triples, edge.succ, k-1)
        if f_index == -1:
          continue
        _, Q, _ = triples[f_index][edge.succ]
        contour = rev_res_plus(Q, edge)
        norm = calculate_norm(contour, L)
        print str(norm) + " " + str(theta) + " " + str(f_index) + " " + str(k)
        if (norm <= theta):
          if (edge.succ, f_index) not in dict:
            dict[(edge.succ, f_index)] = sup.add_new_state(edge.succ.marked)
            to_process.append((edge.succ, f_index))
            dict[(edge.succ, f_index)].collisions = edge.succ.collisions
          sup_target = dict[(edge.succ, f_index)]
          sup.add_edge_data(sup_source, sup_target, edge.label)
  for state in sup.get_states():
    for edge in state.get_outgoing():
      edge.weight = 1
  return sup
Exemple #7
0
def remove_weights(waut):
    """
    Remove the weights of weighted automaton L{waut}.

    @param waut: Weighted automaton.
    @type  waut: L{collection.WeightedAutomaton}

    @return: Equivalent unweighted automaton.
    @rtype:  L{collection.Automaton}
    """
    aut = data_structure.Automaton(waut.alphabet, waut.collection)
    aut.set_kind(waut.aut_kind)

    for wstat in waut.get_states():
        aut.add_new_state(wstat.marked, wstat.number)
    aut.set_initial(aut.get_state(waut.initial.number))

    for wstat in waut.get_states():
        src = aut.get_state(wstat.number)
        for wedge in wstat.get_outgoing():
            dest = aut.get_state(wedge.succ.number)
            aut.add_edge_data(src, dest, wedge.label)

    return aut
Exemple #8
0
def natural_projection_map(aut, preserved):
    """
    Project an automaton on preserved events.

    For each cluster of states (connected with each other through non-preserved
    events), find the next cluster for each preserved event by computing the
    union of reachable state clusters (from the original cluster, do the
    preserved event for all states, and merge all states reachable through
    non-preserved events after the transition).

    @param aut: Automaton to project.
    @type  aut: L{Automaton}

    @param preserved: Set of event of the automaton to preserve.
    @type  preserved: C{set} of L{Event}

    @return: Automaton reduced to L{preserved} events, and a state map.
    @rtype: L{Automaton}, and a C{dictionary} of a C{set} of L{State} from the
            original automaton to a L{State} in the returned automaton.
    """
    non_preserved = aut.alphabet.difference(preserved)

    new_aut = data_structure.Automaton(preserved.copy(), aut.collection)

    def add_new_state(states, state_map, new_aut, notdone_list):
        frozen_states = frozenset(states)
        if frozen_states in state_map:
            return state_map[frozen_states]

        marked = False
        for state in states:
            if state.marked:
                marked = True
                break

        s = new_aut.add_new_state(marked)
        state_map[frozen_states] = s
        notdone_list.append((frozen_states, s))
        return s

    state_map = {}
    notdone_list = []
    states = aut.reachable_states(aut.initial, non_preserved)
    new_aut.set_initial(add_new_state(states, state_map, new_aut,
                                      notdone_list))
    while len(notdone_list) > 0:
        states, new_state = notdone_list.pop()

        outgoing_events = set(edge.label for state in states
                              for edge in state.get_outgoing())

        for evt in preserved.intersection(outgoing_events):
            dest_states = set()
            for state in states:
                for edge in state.get_outgoing(evt):
                    if edge.succ not in dest_states:
                        dest_states.update(
                            aut.reachable_states(edge.succ, non_preserved))
                    # else: edge.succ already handled

            if len(dest_states) > 0:
                s2 = add_new_state(dest_states, state_map, new_aut,
                                   notdone_list)
                new_aut.add_edge_data(new_state, s2, evt)

    return new_aut, state_map
Exemple #9
0
def make_supervisor_optimized(plants, specs, verbose=True):
    """
    Construct a supervisor for the L{plants} that behaves safely within the
    L{specs} requirements.

    @param plants: Plant automata.
    @type  plants: C{list} of L{BaseAutomaton}

    @param specs: Requirements specification automata.
    @type  specs: C{list} of L{BaseAutomaton}

    @return: Supervisor automaton if it exists, C{None} otherwise.
    @rtype: L{Automaton} or C{None}
    """
    assert len(plants) > 0
    assert len(specs) > 0

    # The iteration below replaces the specs by its own automaton.
    # To prevent leaking automata, these own automata should be deleted
    # before exit.
    delete_specs = False

    deterministic_and_all_observable = True
    # Check that all events are observable
    for plant in plants:
        for evt in plant.alphabet:
            if not evt.observable:
                deterministic_and_all_observable = False
                break

    if deterministic_and_all_observable:
        # Check that plant is deterministic
        for plant in plants:
            for state in plant.get_states():
                evts = set()  #: Set of events encountered at a state.
                for edge in state.get_outgoing():
                    if edge.label in evts:
                        deterministic_and_all_observable = False
                        break
                    evts.add(edge.label)

    while True:  # make_supervisor() is an iterative function

        result = controllable_coreachable_product_optimized(
            plants, specs, verbose)
        #result = controllable_coreachable_product(plants, specs, verbose)
        if result is None:
            if delete_specs:
                for spec in specs:
                    spec.clear()
            return None

        if deterministic_and_all_observable:  # We are finished!
            if delete_specs:
                for spec in specs:
                    spec.clear()
            return result[0]

        chi_aut, boundary_disableds = result

        if len(boundary_disableds) == 0:
            if delete_specs:
                for spec in specs:
                    spec.clear()
            #return unweighted_determinization(chi_aut)
            return tau_abstraction.subsetconstructionnotweighted(
                chi_aut, set(), 0)

        #
        # Construct automaton A
        #
        aut_A = data_structure.Automaton(chi_aut.alphabet.copy(),
                                         chi_aut.collection)

        for state in chi_aut.coreachable_states_set(
                set(boundary_disableds.keys()), None):
            aut_A.add_new_state(marked=False, num=state.number)

        assert aut_A.has_state(chi_aut.initial.number)
        aut_A.set_initial(aut_A.get_state(chi_aut.initial.number))

        # Copy edges
        edgestoadd = []
        for state in chi_aut.get_states():
            if not aut_A.has_state(state.number):
                continue

            for edge in state.get_outgoing():
                if not aut_A.has_state(edge.succ.number):
                    continue

                #aut_A.add_edge_data(aut_A.get_state(state.number),
                #aut_A.get_state(edge.succ.number), edge.label)
                edgestoadd.append(
                    data_structure.Edge(aut_A.get_state(state.number),
                                        aut_A.get_state(edge.succ.number),
                                        edge.label))
        # Add dump state
        dump_state = aut_A.add_new_state(True)
        for state, disableds in boundary_disableds.iteritems():
            for disabled in disableds:
                #aut_A.add_edge_data(aut_A.get_state(state.number), dump_state,
                #              disabled)
                edgestoadd.append(
                    data_structure.Edge(aut_A.get_state(state.number),
                                        dump_state, disabled))
        # Self-loops for all events in dump-state
        for evt in aut_A.alphabet:
            #aut_A.add_edge_data(dump_state, dump_state, evt)
            edgestoadd.append(data_structure.Edge(dump_state, dump_state, evt))

        aut_A.add_edges(edgestoadd)
        #A2 = unweighted_determinization(aut_A)
        A2 = tau_abstraction.subsetconstructionnotweighted(aut_A, set(), 0)
        b = A2.reduce(False, True)
        assert b

        #A3 = projection(A2)
        A3 = tau_abstraction.subsetconstructionnotweighted(
            A2, set([evt for evt in A2.alphabet if not evt.observable]), 0)
        #A4 = inverse_projection(A3)
        A4 = inverse_projection_optimized(A3)

        A2.clear()
        A3.clear()

        #A5 = product.n_ary_unweighted_product([chi_aut, A4])
        A5 = tau_abstraction.synchronousproduct([chi_aut, A4], 0)

        marked = False
        for state in A5.get_states():
            if state.marked:
                marked = True
                break
        if not marked:
            A4.clear()
            A5.clear()
            if delete_specs:
                for spec in specs:
                    spec.clear()

            #return unweighted_determinization(chi_aut)
            return tau_abstraction.subsetconstructionnotweighted(
                chi_aut, set(), 0)

        A5.clear()

        #A6 = complement(A4)
        A6 = complement_optimized(A4)
        #A7 = unweighted_determinization(
        #product.n_ary_unweighted_product([chi_aut, A6]))
        chiA6 = tau_abstraction.synchronousproduct([chi_aut, A6], 0)
        A7 = tau_abstraction.subsetconstructionnotweighted(chiA6, set(), 0)
        b = A7.reduce(False, True)
        if not b:
            if delete_specs:
                for spec in specs:
                    spec.clear()
            return None

        A4.clear()
        A6.clear()

        # Iteration:
        # plants = plants
        specs = [A7]
        delete_specs = True
Exemple #10
0
def controllable_coreachable_product_optimized(plants, specs, verbose=True):
    """
    Compute the controllable and co-reachable sub set of a product.

    @param plants: Plant automata.
    @type  plants: C{list} of L{BaseAutomaton}

    @param specs: Specification automata.
    @type  specs: C{list} of L{BaseAutomaton}

    @return: C{None} if empty automaton reached, or (L{Automaton}, disableds)
             where disableds is a map of automaton states to set of disabled
             events
    """
    #prod_aut, bad_states = compute_products(plants, specs, verbose)
    prod_aut, bad_states = tau_abstraction.synchronousproduct_supervisor(
        plants, specs, 0)
    prod_aut.reduce(True, False)

    # Construct controllable_states
    uncontrollables = set(evt for evt in prod_aut.alphabet
                          if not evt.controllable)

    controllable_states = set()
    for state in prod_aut.get_states():
        if state not in bad_states:
            controllable_states.add(state)

    while True:

        # Find coreachable states in L{controllable_states}
        coreachable_states = set()
        notdone_list = []
        for state in prod_aut.get_states():
            if state not in controllable_states:
                continue
            if state.marked:
                coreachable_states.add(state)
                notdone_list.append(state)

        while len(notdone_list) > 0:
            state = notdone_list.pop()
            for edge in state.get_incoming():
                if edge.pred not in controllable_states:
                    continue

                if edge.pred not in coreachable_states:
                    coreachable_states.add(edge.pred)
                    notdone_list.append(edge.pred)

        bad_states = supervisor_product.coreachable_bad_states(
            prod_aut, controllable_states.difference(coreachable_states),
            uncontrollables)
        if len(bad_states) == 0:
            break

        controllable_states = coreachable_states.difference(bad_states)

        coreachable_states.clear()
        bad_states.clear()

    if prod_aut.initial not in controllable_states:
        return None

    # Construct a new automaton from the reachable and controllable subset
    new_aut = data_structure.Automaton(prod_aut.alphabet, prod_aut.collection)

    def new_state(old_state, new_aut, notdone_list):
        if not new_aut.has_state(old_state.number):
            s = new_aut.add_new_state(old_state.marked, num=old_state.number)
            notdone_list.append(old_state)
            return s
        else:
            return new_aut.get_state(old_state.number)

    # Copy states
    boundary_disableds = {}  # Map of chi states to set of disabled events
    notdone_list = []
    s = new_state(prod_aut.initial, new_aut, notdone_list)
    new_aut.set_initial(s)
    edgestoadd = []
    while len(notdone_list) > 0:
        state = notdone_list.pop()
        for edge in state.get_outgoing():
            if edge.succ not in controllable_states:
                # Found an edge that leads to outside the controllable
                # subset, make a note of it

                # Find the same state as 'state' in the new automaton
                equiv_state = new_aut.get_state(state.number)

                if equiv_state not in boundary_disableds:
                    boundary_disableds[equiv_state] = set([edge.label])
                else:
                    boundary_disableds[equiv_state].add(edge.label)

                continue  # Ignore the state in the copying process

            new_state(edge.succ, new_aut, notdone_list)

    # Copy edges
    for state in prod_aut.get_states():
        if not new_aut.has_state(state.number):
            continue

        for edge in state.get_outgoing():
            if not new_aut.has_state(edge.succ.number):
                continue
            edgestoadd.append(
                data_structure.Edge(new_aut.get_state(state.number),
                                    new_aut.get_state(edge.succ.number),
                                    edge.label))
            #new_aut.add_edge_data(new_aut.get_state(state.number),
            #new_aut.get_state(edge.succ.number), edge.label)
    new_aut.add_edges(edgestoadd)
    prod_aut.clear()

    return new_aut, boundary_disableds
Exemple #11
0
def model_conversion(aut, preserved_events):
    """
    Compute automaton with only observable events.

    @note: If marker events are to be preserved, they should be added to the
           L{preserved_events} by the user.

    @param aut: Original automaton
    @type  aut: L{Automaton}

    @param preserved_events: Observable events
    @type  preserved_events: C{set} of C{Event}

    @return: Reduced automaton
    @rtype: L{Automaton}
    """
    non_preserved_events = aut.alphabet.difference(preserved_events)
    new_aut = data_structure.Automaton(preserved_events, aut.collection)

    def get_new_state(old_state):
        """
        From a state of the old automaton (old_state), return the associated
        state of the new automaton (or create one)
        """
        if not new_aut.has_state(old_state.number):
            new_state = new_aut.add_new_state(marked = old_state.marked,
                                              num = old_state.number)
            return new_state

        return new_aut.get_state(old_state.number)


    for state in aut.get_states():
        for edge in state.get_outgoing():
            if edge.label in preserved_events or edge.label.marker:
                reachables = aut.reachable_states(edge.succ,
                                                          non_preserved_events)
                coreachables = aut.coreachable_states(state,
                                                          non_preserved_events)

                for start_state in coreachables:
                    # Find or create same start state in new automaton
                    new_start = get_new_state(start_state)

                    for dest_state in reachables:
                        # Find or create same dest state in new automaton
                        new_dest = get_new_state(dest_state)
                        new_aut.add_edge_data(new_start, new_dest, edge.label)

                reachables.clear()
                coreachables.clear()

    # Initial state must have a path with an observable event to make the
    # line below hold
    new_aut.set_initial(new_aut.get_state(aut.initial.number))

    valid_aut = new_aut.reduce(reachability = True)
    assert valid_aut == True

    non_preserved_events.clear()
    return new_aut
 def setup(self, props):
     self.aut = data_structure.Automaton(props.alphabet, props.coll)
def dothis(local_alphabet):
    print local_alphabet.pop()


coll = collection.Collection()
comp_list = weighted_frontend.load_weighted_automata(coll, "plant1.cfg", False,
                                                     True)
local_alphabet = comp_list[0].alphabet
print local_alphabet
dothis(local_alphabet)
print local_alphabet
temp_coll = collection.Collection()
temp_automaton = weighted_structure.WeightedAutomaton(local_alphabet,
                                                      temp_coll)
# temp_automaton.add_new_state(False, comp_list[0].initial.number)
for state in comp_list[0].get_states():
    ns = temp_automaton.add_new_state(state.marked, state.number)

for state in comp_list[0].get_states():
    for edge in state.get_outgoing():
        if edge.label in local_alphabet:
            print "this happends"
            new_edge = edge.copy(temp_automaton.get_state(edge.pred.number),
                                 temp_automaton.get_state(edge.succ.number))
            temp_automaton.add_edge(new_edge)

temp_automaton.initial = temp_automaton.get_state(comp_list[0].initial.number)
temp_automaton.reduce(True, True)
temp_req = data_structure.Automaton(set([next(iter(local_alphabet))]),
                                    temp_coll)
print temp_automaton.initial.get_outgoing().pop()
def progressive_synthesis(automaton, resources, progressive_events):
  #print progressive_events
  tim = -time()
  automaton = finite_makespan_restricted(automaton, progressive_events)
  supervisor = data_structure.Automaton(set(automaton.alphabet), automaton.collection)
  zero_contour = frozendict()
  for r in resources:
    zero_contour[r] = 0
  init = supervisor.add_new_state(automaton.initial.marked)
  init.x = automaton.initial
  init.x_f = zero_contour
  dictionary = {}
  dictionary[(init.x, init.x_f)] = init
  supervisor.initial = init
  to_process = [init]
  Q = {}
  num_uncont = {}
  covered_uncont = {}
  Q_process = set()
  while to_process:
    state = to_process.pop()
    x, x_f = state.x, state.x_f
    uncont = 0
    for edge in state.x.get_outgoing():
      if edge.label in progressive_events and not edge.label.controllable:
        uncont = uncont + 1
      y, y_f = edge.succ, ground(res_plus(x_f, edge))
      if (y, y_f) not in dictionary:
        new_state = supervisor.add_new_state(y.marked)
        dictionary[(y, y_f)] = new_state
        new_state.x = y
        new_state.x_f = y_f
        to_process.append(new_state)
      succ_state = dictionary[(y, y_f)]
      new_edge = data_structure.Edge(state, succ_state, edge.label)
      new_edge.weight = edge.weight
      supervisor.add_edge(new_edge)
      #supervisor.add_edge_data(state, succ_state, edge.label)
    if not state.marked or uncont != 0:
      Q[state] = None
    else:
      Q[state] = ceil(x_f)
      Q_process.add(state)
    num_uncont[state] = uncont
    covered_uncont[state] = 0
  print "states: " + str(supervisor.get_num_states())
  print supervisor
  while Q_process:
    print len(Q_process)
    Q_processnew = set()
    for state in Q_process:
      if num_uncont[state] > 0:
        m = None
        for edge in state.get_outgoing():
          if edge.label in progressive_events and not edge.label.controllable:
            temp = floor(res_plus(state.x_f, edge)) + Q[edge.succ]
            if (m == None):
              m = temp
            else:
              m = max(m, temp)
        if (Q[state] == m):
          continue
        Q[state] = m
      for edge in state.get_incoming():
        if edge.label in progressive_events:
          if edge.label.controllable and num_uncont[edge.pred] == 0:
            temp = floor(res_plus(edge.pred.x_f, edge)) + Q[state]
            if Q[edge.pred] == None:
              Q[edge.pred] = temp
              Q_processnew.add(edge.pred)
              for edge2 in edge.pred.get_incoming():
                if edge2.label in progressive_events and not edge2.label.controllable:
                  covered_uncont[edge2.pred] = covered_uncont[edge2.pred] + 1
            elif (temp < Q[edge.pred]):
              Q[edge.pred] = temp
              if edge.pred not in Q_processnew:
                Q_processnew.add(edge.pred)
          elif not edge.label.controllable and num_uncont[edge.pred] == covered_uncont[edge.pred]:
            temp = floor(res_plus(edge.pred.x_f, edge)) + Q[state]
            if (Q[edge.pred] == None):
              for edge2 in edge.pred.get_incoming():
                if edge2.label in progressive_events and not edge2.label.controllable:
                  covered_uncont[edge2.pred] = covered_uncont[edge2.pred] + 1
            if (Q[edge.pred] == None or temp < Q[edge.pred]):
              Q_processnew.add(edge.pred)
    if (len(Q_processnew) == 0):
      break
    else:
      Q_process = Q_processnew
  edgestoremove = []
  for state in supervisor.get_states():
    for edge in state.get_outgoing():
      if edge.label in progressive_events:
        temp = floor(res_plus(edge.pred.x_f, edge)) + Q[edge.succ]
        if Q[state] < temp:
          edgestoremove.append(edge)
  for edge in edgestoremove:
    supervisor.remove_edge(edge)
  supervisor.reduce(True, True)
  print supervisor
  tim = tim + time()
  print tim
  return supervisor, Q[automaton.initial]