示例#1
0
def make_nonconflicting_check(aut_fnames, use_heuristic):
    """
    Verify whether the automata do not conflict with each other.

    @param aut_fnames: Comma-seperated list of automata filenames.
    @type  aut_fnames: C{str}

    @param use_heuristic: Compute a smart order for the automata (rather than
                          use the supplied order).
    @type  use_heuristic: C{str}

    @return: Indication that no conflict has been found (all is ok).
    @rtype:  C{bool}
    """
    common.print_line("Started nonconflicting check (version %s)"
                        % automata.version)
    coll = collection.Collection()
    auts = load_automata(coll, aut_fnames, False, False)

    if parse_boolean(use_heuristic):
        auts = abstraction.order_automata(auts)
    # else, user has supplied the automata in the right order.

    result = abstraction.nonconflicting_check(auts)

    if result:
        print "nonconflicting_check: HOLDS"
    else:
        print "nonconflicting_check: CONFLICT FOUND"

    return result
示例#2
0
def n_ary_unweighted_product(auts, delete_aut = False,
                             report_progress = False, preserve_names = True):
    """
    N-ary unweighted automata product.

    @param auts: Input automata.
    @type  auts: C{list} of L{Automaton}

    @param delete_aut: Routine is allowed to delete the provided automata.
    @type  delete_aut: C{bool}

    @param report_progress: Output progress of the computation.
    @type  report_progress: C{bool}

    @param preserve_names: Try to preserve state names in the product.
    @type  preserve_names: C{bool}

    @return: Resulting unweighted automaton.
    @rtype:  L{Automaton}
    """
    if report_progress:
        common.print_line("Computing product of %d unweighted automata"
                                                                % len(auts))

    if len(auts) == 1:
        return auts[0]

    prod, mapping = n_ary_unweighted_product_map(auts, preserve_names)

    del mapping
    if delete_aut:
        for aut in auts:
            aut.clear()

    return prod
示例#3
0
def save_weighted_automaton(aut, title, fname):
    """
    Save weighted automaton L{aut} in file L{fname}.

    @param aut: Automaton to save.
    @type  aut: L{WeightedAutomaton}

    @param title: If existing, an additional text to output. If it contains
                  C{%s}, string formatting is used to insert the filename at
                  that point in the text.
    @type  title: Either a C{str} or C{None}

    @param fname: Filename to write the automaton to.
    @type  fname: C{str}
    """
    assert isinstance(aut, weighted_structure.WeightedAutomaton)

    frontend.make_backup_file(fname)
    weighted_structure.save_automaton(aut, fname, make_backup=False)

    if title is not None:
        if title.find("%s") >= 0:
            common.print_line(title % (fname, ))
        else:
            common.print_line(title)
示例#4
0
def make_weighted_projection(aut_name, evt_names, result_fname):
    """
    Perform projection over a weighted automaton.

    @param aut_name: Filename of the automaton to project.
    @type  aut_name: L{WeightedAutomaton}

    @param evt_names: Comma seperated list of event names to preserve.
    @type  evt_names: C{str}

    @param result_fname: Filename for writing the resulting weighted automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started weighted projection computation (version %s)" %
                      automata.version)
    coll = collection.Collection()

    waut = load_weighted_automaton(coll, aut_name, False, False)
    events = frontend.get_events(coll, evt_names)

    waut2 = weighted_projection.weighted_projection(waut, events)

    frontend.dump_stats("Computed weighted projection", waut2)
    save_weighted_automaton(waut2, "Projected automaton is saved in %s",
                            result_fname)
示例#5
0
def make_sequential_abstraction(aut_fnames, evt_names, result_fname):
    """
    Perform sequential abstraction on a number of automata.

    @param aut_fnames: Comma-seperated list of automata filenames.
    @type  aut_fnames: C{str}

    @param evt_names: Comma seperated list of event names.
    @type  evt_names: C{str}

    @param result_fname: Filename for writing the resulting automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started sequential abstraction computations "
                      "(version %s)" % automata.version)
    coll = collection.Collection()

    auts = load_automata(coll, aut_fnames, True, False)
    auts = abstraction.order_automata(auts)

    events = get_events(coll, evt_names)
    events = ensure_tau(coll, events)

    result = abstraction.sequential_abstraction(auts, events)
    save_automaton(result, "Abstraction is saved in %s",  result_fname)
示例#6
0
def make_natural_projection(aut_name, evt_names, result_fname):
    """
    Perform projection over a language.

    @param aut_name: Filename of the automaton to project.
    @type  aut_name: L{Automaton}

    @param evt_names: Comma seperated list of event names to preserve.
    @type  evt_names: C{str}

    @param result_fname: Filename for writing the resulting automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started natural projection computation (version %s)"
                        % automata.version)
    coll = collection.Collection()

    aut = load_automaton(coll, aut_name, False, False)
    events = get_events(coll, evt_names)

    aut2 = supervisor.unweighted_determinization(aut)
    result = supervisor.natural_projection_map(aut2, events)[0]

    dump_stats("Computed projection", result)
    save_automaton(result, "Projected automaton is saved in %s",  result_fname)
示例#7
0
def ensure_tau(collect, events):
    """
    Ensure that the C{tau} event exists and is part of L{events}.

    @param collect: Collection to get the events from.
    @type  collect: L{collection.Collection}

    @param events: Events.
    @type  events: A C{set} of L{Event}

    @return: Possibly updated events.
    @rtype:  A C{set} of L{Event}
    """

    if 'tau' not in collect.events:
        raise exceptions.ModelError("Event 'tau' does not exist.")

    tau = collect.events['tau']
    if tau not in events:
        common.print_line("Information: Adding event 'tau' to events.\n")

        evts = events.copy()
        evts.add(tau)
        return evts

    return events
示例#8
0
def make_weighted_supervisor(comp_name, req_name, sup_name):
    """
    Compute a weighted supervisor.

    @param comp_name: Available component (weighted automaton).
    @type  comp_name: C{str}

    @param req_name: Available requirement (unweighted automaton).
    @type  req_name: C{str}

    @param sup_name: Name of resulting supervisor (unweighted automaton).
    @type  sup_name: C{str}
    """
    common.print_line("Started weighted supervisor computation "
                      "(version %s)" % automata.version)
    coll = collection.Collection()
    comp = load_weighted_automaton(coll, comp_name, False, True)
    req = frontend.load_automaton(coll, req_name, False, True)

    sup = weighted_supervisor.compute_weighted_supervisor(comp, req)
    if sup is None:
        common.print_line("Weighted supervisor cannot be computed.")
        return
    else:
        frontend.dump_stats("Computed weighted supervisor", sup)
        frontend.save_automaton(sup, "Supervisor is saved in %s\n", sup_name)
示例#9
0
def compute_optimal_weighted_supervisor(comp, req):
    """
    Compute optimal weighted supervisor.

    @param comp: Available component (weighted automaton).
    @type  comp: C{WeightedAutomaton}

    @param req: Available requirement (unweighted automaton).
    @type  req: C{UnweightedAutomaton}

    @return: Resulting supervisor (unweighted automaton).
    @type:   C{UnweightedAutomaton}
    """
    # Compute supremal supervisor without considering weight.
    wsup = compute_weight.compute_weighted_supremal(comp, req)
    if wsup is None:
        return None

    obs_alphabet = set(evt for evt in comp.alphabet if evt.observable)
    waut2 = weighted_projection.weighted_projection(wsup, obs_alphabet)
    waut2 = weighted_determinization(waut2)
    weight_map = compute_weight.compute_state_weights(waut2,
                                                    marker_valfn = lambda s: 0)
    # Throw out all states with infinite weight.
    waut3 = remove_automaton_states(waut2,
                               lambda s: weight_map[s] is not maxplus.INFINITE)
    waut3.reduce(True, False)

    reduced_comp = weighted_product.n_ary_weighted_product([comp, waut3],
                                                          algorithm.FIRST_EDGE)

    unfolded, weight_map = compute_weight.unfold_automaton_map(reduced_comp,
                                               weight_map[waut2.initial])


    comp = conversion.remove_weights(comp)
    sup = unfolded
    prev_unfolded = None
    while True:
        sup = supervisor.make_supervisor([comp], [sup])
        if sup is None:
            break

        prev_unfolded = sup # 'sup' is a good solution.

        sup = sup.copy()
        state_map = make_state_mapping(sup, unfolded)
        max_weight = max(weight_map[state_map[state]]
                         for state in sup.get_states()
                         if sum(1 for edge in state.get_outgoing()) == 0)

        common.print_line("Pruning weight %d" % max_weight)
        for state in list(sup.get_states()):
            if weight_map[state_map[state]] == max_weight and \
                    sum(1 for edge in state.get_outgoing()) == 0:
                sup.remove_state(state)

    assert prev_unfolded is not None
    return prev_unfolded
示例#10
0
def dump_stats(title, aut):
    """
    Output some basic statistics about an automaton.

    @param title: Title to put above the statistics.
    @type  title: C{str}

    @param aut: Automaton.
    @type  aut: L{Automaton}
    """
    common.print_line(title + "\n" + str(aut))
示例#11
0
def generate_task_resource_use(comp_names, req_names, text_path, plots,
                               usefname):
    """
    Generate a task/resource usage picture for path L{text_path} with
    components L{comp_names} and requirements L{req_names}. Output data in
    L{usefname}.

    @param comp_names: Available components (weighted automata).
    @type  comp_names: C{list} of L{str}

    @param req_names: Available requirements (unweighted automata).
    @type  req_names: C{list} of L{str}

    @param text_path: Sequence of events on the path (a sequence of event
                      names, comma or white-space seperated).
    @type  text_path: C{string}

    @param plots: Names of automata to plot, if specified.
    @type  plots: C{str}

    @param usefname: Filename for writing task/resource use to.
    @type  usefname: C{str}

    @note: The L{comp_names} and L{req_names} are only used to compute the
           shape of the pieces at the heap. Therefore, for type 1 requirements
           (where the requirements automata are not used in that calculation),
           L{req_names} should be left empty.

    """
    common.print_line('Started generation of task/resource use (version %s)' %
                      automata.version)
    coll = collection.Collection()
    comp_list = load_weighted_automata(coll, comp_names, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)

    plots = set(plots.replace(',', ' ').split())
    if plots:  # Non-empty set.
        plot_auts = set(aut for aut in comp_list + req_list
                        if aut.name in plots)
    else:
        plot_auts = None  # All automata should be plotted.

    uses = compute_weight.generate_task_resource_use(comp_list, req_list,
                                                     plot_auts, text_path)

    if usefname:
        handle = open(usefname, 'w')
        for use in uses:
            handle.write('%s\t%s\t%s\t%s\n' % use)
        handle.close()
    else:
        for use in uses:
            print '%s\t%s\t%s\t%s' % use
示例#12
0
def make_get_weighted_size(aut_fname):
    """
    Display size of the weighted automaton.

    @param aut_fname: Filename of the weighted automaton.
    @type  aut_fname: C{str}
    """
    common.print_line("Started calculating size (version %s)" %
                      automata.version)
    coll = collection.Collection()
    aut = load_weighted_automaton(coll, aut_fname, False, False)

    print str(aut)
示例#13
0
def make_trim(aut_fname, out_fname):
    """
    Trim the automaton L{aut} (reduce to reachable and co-reachable states).

    @param aut_fname: Filename of the automaton.
    @type  aut_fname: C{str}

    @param out_fname: Filename of the resulting automaton.
    @type  out_fname: C{str}
    """
    common.print_line("Started trimming (version %s)" % automata.version)
    coll = collection.Collection()
    aut = load_automaton(coll, aut_fname, False, False)
    aut.reduce(True, True)

    dump_stats("Computed result", aut)
    save_automaton(aut, "Result is saved in %s\n", out_fname)
示例#14
0
def make_remove_tau_event(aut_fname, out_fname):
    """
    Remove 'tau' event from the automaton. May fail.

    @param aut_fname: Filename of the automaton.
    @type  aut_fname: C{str}

    @param out_fname: Filename of the resulting automaton.
    @type  out_fname: C{str}
    """
    common.print_line("Started removing 'tau' event (version %s)"
                        % automata.version)
    coll = collection.Collection()
    aut = load_automaton(coll, aut_fname, False, False)
    abstraction.remove_tau(aut) # Does in-place modification.

    dump_stats("Computed result", aut)
    save_automaton(aut, "Result is saved in %s\n", out_fname)
示例#15
0
def make_add_tau_event(aut_fname, out_fname):
    """
    Add 'tau' event to the automaton.

    @param aut_fname: Filename of the automaton.
    @type  aut_fname: C{str}

    @param out_fname: Filename of the resulting automaton.
    @type  out_fname: C{str}
    """
    common.print_line("Started adding 'tau' event (version %s)"
                        % automata.version)
    coll = collection.Collection()
    aut = load_automaton(coll, aut_fname, False, False)
    aut = abstraction.add_tau_event(aut)

    dump_stats("Computed result", aut)
    save_automaton(aut, "Result is saved in %s\n", out_fname)
示例#16
0
def make_remove_weighted(waut_fname, result_fname):
    """
    Remove the weights of weighted automaton L{waut_fname}, and write the
    result to L{result_fname}.

    @param waut_fname: Filename of weighted automaton to load.
    @type  waut_fname: C{str}

    @param result_fname: Filename of the resulting unweighted automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started removing weights (version %s)" %
                      automata.version)
    coll = collection.Collection()

    waut = load_weighted_automaton(coll, waut_fname, False, False)
    aut = conversion.remove_weights(waut)

    frontend.save_automaton(aut, "Result is saved in %s\n", result_fname)
示例#17
0
def make_reset_weighted(aut_fname, result_fname):
    """
    Reset the weights in weighted automaton L{aut_fname} to 0, and write the
    result to L{result_fname}.

    @param aut_fname: Filename of weighted automaton to load.
    @type  aut_fname: C{str}

    @param result_fname: Filename for writing the resulting weighted automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started resetting weights (version %s)" %
                      automata.version)
    coll = collection.Collection()

    aut = load_weighted_automaton(coll, aut_fname, False, False)
    aut.reset_weight(0)

    save_weighted_automaton(aut, "Result is saved in %s\n", result_fname)
示例#18
0
def n_ary_weighted_product(auts,
                           add_fn,
                           delete_aut=False,
                           report_progress=False):
    """
    N-ary weighted automata product.

    @param auts: Input automata.
    @type  auts: C{list} of L{WeightedAutomaton}

    @param add_fn: Name of the function to use for calculating the weight
                   at new edge.
    @type  add_fn: L{algorithm.SUM_EDGE_WEIGHTS},
                   L{algorithm.EQUAL_WEIGHT_EDGES},
                   L{algorithm.FIRST_EDGE}, or L{algorithm.FIRST_EDGE}

    @param delete_aut: Routine is allowed to delete the provided automata.
    @type  delete_aut: C{bool}

    @param report_progress: Output progress of the computation.
    @type  report_progress: C{bool}

    @return: Resulting weighted automaton.
    @rtype:  L{WeightedAutomaton}
    """
    if report_progress:
        common.print_line("Must do %d weighted product computations." \
                                                            % (len(auts) - 1))

    props = algorithm.ManagerProperties(auts[0].collection)
    props.aut_type = algorithm.WEIGHTED_AUT
    props.marker_func = algorithm.MARKED_ALL
    props.explore_mgr = algorithm.ORIGINAL_STATE
    props.edge_calc = add_fn

    prod, prod_map = product.do_n_ary_product_map(props, auts, True)
    prod_map.clear()

    if delete_aut:
        for aut in auts:
            aut.clear()

    return prod
示例#19
0
def make_unweight_time_optimal_supervisor(comp_names, req_names, evt_pairs,
                                          sup_name):
    """
    Compute a non weighted time optimal supervisor.

    @param comp_names: Available components (weighted automata).
    @type  comp_names: C{list} of L{str}

    @param req_names: Available requirements (unweighted automata).
    @type  req_names: C{list} of L{str}

    @param evt_pairs: Additional event pairs (eg "{(a, b), (c, e)}", "type1",
                      or "type2")
    @type  evt_pairs: C{str}

    @param sup_name: Name of the resulting supervisor.
    @type  sup_name: C{str}
    """
    common.print_line("Started time unweight optimal supervisor computations "
                      "(version %s)" % automata.version)
    coll = collection.Collection()
    comp_list = load_unweight_automata(coll, comp_names, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)
    evt_pairs = taskresource.process_event_pairs(coll, req_list, evt_pairs)

    result = compute_weight.compute_unweight_time_optimal_supervisor(
        comp_list, req_list, evt_pairs)
    if result is None:
        common.print_line('Could not compute the weighted supervisor')
        return

    wsup = result
    #one = maxplus.make_rowmat(0, heap_len)
    #one = maxplus.otimes_mat_mat(one, wmap[wsup.initial])
    #biggest = one.get_scalar()
    #common.print_line("Sub-optimal makespan is %s" % biggest)

    #wsup = weighted_supervisor.reduce_automaton(wsup, wmap, eventdata,
    #                                            heap_len)

    frontend.dump_stats("Computed unweighted supervisor", wsup)
    save_weighted_automaton(wsup, "Supervisor is saved in %s\n", sup_name)
示例#20
0
def make_greedy_time_optimal_supervisor_row_vectors(comp_names, req_names,
                                                    evt_pairs, sup_name,
                                                    row_vectors, operator):
    """
    Compute a greedy time optimal supervisor.

    @param comp_names: Available components (weighted automata).
    @type  comp_names: C{list} of L{str}

    @param req_names: Available requirements (unweighted automata).
    @type  req_names: C{list} of L{str}

    @param evt_pairs: Additional event pairs (eg "{(a, b), (c, e)}", "type1",
                      or "type2")
    @type  evt_pairs: C{str}

    @param sup_name: Name of the resulting supervisor.
    @type  sup_name: C{str}
    """
    common.print_line("Started greedy time optimal supervisor "
                      "computation (version %s)" % automata.version)
    coll = collection.Collection()
    comp_list = load_weighted_automata(coll, comp_names, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)

    evt_pairs = taskresource.process_event_pairs(coll, req_list, evt_pairs)

    result = taskresource.compute_custom_eventdata(comp_list, evt_pairs)
    if result is None:
        common.print_line('Could not compute the event data from the '
                          'components and event pairs\n'
                          'Perhaps they are inconsistent?')
        return

    eventdata, heap_len = result
    result = compute_weight.compute_greedy_time_optimal_supervisor(
        comp_list, req_list, eventdata, heap_len, row_vectors, operator)
    if result is None:
        common.print_line('Could not compute the weighted supervisor')
        return

    wsup, wmap = result
    one = maxplus.make_rowmat(0, heap_len)
    one = maxplus.otimes_mat_mat(one, wmap[wsup.initial])
    biggest = one.get_scalar()
    common.print_line("Sub-optimal makespan is %s" % biggest)

    wsup = weighted_supervisor.reduce_automaton_row_vecors(
        wsup, wmap, eventdata, heap_len, row_vectors)

    frontend.dump_stats("Computed weighted supervisor", wsup)
    save_weighted_automaton(wsup, "Supervisor is saved in %s\n", sup_name)
示例#21
0
def make_minimized(aut_name, result_fname):
    """
    Perform minimization of the automaton stored in L{aut_name}, and write the
    result to L{result_fname}.

    @param aut_name: Filename of the automaton to.
    @type  aut_name: L{Automaton}

    @param result_fname: Filename for writing the resulting automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started minimization computation (version %s)"
                        % automata.version)
    coll = collection.Collection()

    aut = load_automaton(coll, aut_name, False, False)
    result = abstraction.abstraction(aut, aut.alphabet)

    dump_stats("Computed minimized result", result)
    save_automaton(result, "Minimized automaton is saved in %s",  result_fname)
示例#22
0
def make_controllability_check(plant_fname, sup_fname):
    """
    Verify whether the plant is controllable with the supervisor.

    @param plant_fname: Filename of the plant automaton.
    @type  plant_fname: C{str}

    @param sup_fname: Filename of the supervisor.
    @type  sup_fname: C{str}
    """
    common.print_line("Started controllability check (version %s)"
                        % automata.version)
    coll = collection.Collection()
    sup_aut = load_automaton(coll, sup_fname, False, False)
    plant_aut = load_automaton(coll, plant_fname, False, False)

    contr_disableds, uncontr_disableds = \
                                find_disabled_events(sup_aut, plant_aut)

    if len(contr_disableds) > 0:
        print "States with disabled controllable events:"
        for sup_s, plant_s, dis_e in contr_disableds:
            print "    (%d, %d): {%s}" % (plant_s.number, sup_s.number,
                                          ", ".join([e.name for e in dis_e]))

        print

    if len(uncontr_disableds) > 0:
        print "States with disabled uncontrollable events:"
        for sup_s, plant_s, dis_e, sup_p, plant_p in uncontr_disableds:
            print "    (%d, %d): {%s}" % (plant_s.number, sup_s.number,
                                          ", ".join([e.name for e in dis_e]))
            print "        Supervisor path: " + make_path_string(sup_p)
            print "        Plant path: " + make_path_string(plant_p)
            print

        print "Supervisor is INCORRECT (has disabled uncontrollable events)"
        sys.exit(1)

    else:
        print "Supervisor is correct (no disabled uncontrollable events)"
示例#23
0
def make_weighted_product(aut_fnames, result_fname):
    """
    Multiply the weighthed automata in the L{aut_fnames} list, and write the
    result to L{result_fname}.

    @param aut_fnames: Comma-seperated list of weighted automata filenames.
    @type  aut_fnames: C{str}

    @param result_fname: Filename for writing the resulting weighted automaton.
    @type  result_fname: C{str}
    """
    common.print_line("Started weighted product computations (version %s)" %
                      automata.version)
    coll = collection.Collection()

    aut_list = load_weighted_automata(coll, aut_fnames, False, False)
    result = weighted_product.n_ary_weighted_product(
        aut_list, algorithm.SUM_EDGE_WEIGHTS, True, True)

    frontend.dump_stats("Computed product", result)
    save_weighted_automaton(result, "Product is saved in %s\n", result_fname)
示例#24
0
def row_vector_compute(plant, req_names, evt_pairs, row_vector_names,
                       operator_class):
    coll = collection.Collection()
    comp_list = weighted_frontend.load_weighted_automata(
        coll, plant, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)
    evt_pairs = taskresource.process_event_pairs(coll, req_list, evt_pairs)
    result = taskresource.compute_custom_eventdata(comp_list, evt_pairs)
    if result is None:
        common.print_line('Could not compute the event data from the '
                          'components and event pairs\n'
                          'Perhaps they are inconsistent?')
        return

    eventdata, heap_len = result

    plant = weighted_product.n_ary_weighted_product(
        comp_list, algorithm.EQUAL_WEIGHT_EDGES)
    requirement = product.n_ary_unweighted_product(req_list)

    for comp in comp_list:
        comp.clear()
    del comp_list

    wsup = compute_weight.compute_weighted_supremal(plant, requirement)
    if wsup is None:
        return None
    requirement.clear()
    del requirement

    row_zero_mat = maxplus.make_rowmat(0, heap_len)
    row_epsilon_mat = maxplus.make_rowmat(maxplus.INFINITE, heap_len)

    marker_valfn = lambda state: row_zero_mat
    nonmarker_valfn = lambda state: row_epsilon_mat

    row_vecs = compute_state_row_vector(wsup, marker_valfn, nonmarker_valfn,
                                        eventdata, operator_class)

    return row_vecs
示例#25
0
def check_marking_aware(waut, events):
    """
    Verify that all incoming edges to marker states use events from the
    L{events} set.

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

    @param events: Events that must be used at incoming edges of marker states.
    @type  events: A C{set} of L{Event}
    """
    common.print_line("Started marking aware computations (version %s)" %
                      automata.version)
    warnings = []
    for state in waut.get_states():
        if state.marked:
            labels = set(edge.label for edge in state.get_incoming())
            for evt in labels:
                if evt not in events:
                    warnings.append(
                        "\tevent %s to state %d is not observable" %
                        (evt.name, state.number))
    if len(warnings) > 0:
        common.print_line(["Warning: Plant is not marking aware"])
        common.print_line(warnings)
示例#26
0
def make_time_optimal_supervisor(comp_names, req_names, evt_pairs, sup_name):
    """
    Compute a time optimal supervisor.

    @param comp_names: Available components (weighted automata).
    @type  comp_names: C{list} of C{str}

    @param req_names: Available requirements (unweighted automata).
    @type  req_names: C{List} of C{str}

    @param evt_pairs: Additional event pairs (eg "{(a, b), (c, e)}", "type1",
                      or "type2")
    @type  evt_pairs: C{str}

    @param sup_name: Name of resulting supervisor (unweighted automaton).
    @type  sup_name: C{str}
    """
    common.print_line("Started time optimal supervisor computations "
                      "(version %s)" % automata.version)
    coll = collection.Collection()
    comp_list = load_weighted_automata(coll, comp_names, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)

    evt_pairs = taskresource.process_event_pairs(coll, req_list, evt_pairs)
    result = compute_weight.compute_time_optimal_supervisor(
        comp_list, req_list, evt_pairs)

    if result is None:
        common.print_line("Time optimal supervisor cannot be computed.")
        return
    else:
        sup, min_weight = result
        common.print_line("Minimum makespan is %d" % min_weight)
        frontend.dump_stats("Computed time optimal supervisor", sup)
        frontend.save_automaton(sup, "Supervisor is saved in %s\n", sup_name)
示例#27
0
def make_observer_check(aut_name, evt_names):
    """
    Perform observer_check of the automaton stored in L{aut_name}.

    @param aut_name: Filename of the automaton to abstract.
    @type  aut_name: L{Automaton}

    @param evt_names: Comma seperated list of event names to preserve.
    @type  evt_names: C{str}
    """
    common.print_line("Started observer-check computation (version %s)"
                        % automata.version)
    coll = collection.Collection()

    aut = load_automaton(coll, aut_name, True, False)
    events = get_events(coll, evt_names)
    bad_events = abstraction.observer_check(aut, events)

    if len(bad_events) == 0:
        common.print_line("Observer-check property HOLDS")
    else:
        if len(bad_events) == 1:
            evt_text = "event"
        else:
            evt_text = "events"

        evts = ", ".join(event.name for event in bad_events)
        common.print_line("Observer-check property does not hold "
                          "due to %s %s" % (evt_text, evts))
示例#28
0
def make_supervisor(plant_fnames, spec_fnames, sup_fname):
    """
    Construct a supervisor for controlling a plant within its specification.

    Function aborts if supervisor construction fails.


    @param plant_fnames: Filenames of the plant automata.
    @type  plant_fnames: C{str}

    @param spec_fnames: Filenames of the specification automata.
    @type  spec_fnames: C{str}

    @param sup_fname: Filename for the resulting supervisor.
    @type  sup_fname: C{str}

    @todo: Supervisor computation should set the automaton kind by itself.
    """
    common.print_line("Started supervisor computations (version %s)"
                        % automata.version)
    coll = collection.Collection()

    plants = load_automata(coll, plant_fnames, False, True)
    specs  = load_automata(coll, spec_fnames, False, True)

    sup = supervisor.make_supervisor(plants, specs)
    if sup is None:
        print "Supervisor is empty"
        sys.exit(1)
    else:
        # FIXME: This is the wrong place for setting the result kind
        npl = sum(1 for plant in plants if plant.aut_kind == 'plant')
        nsp = sum(1 for spec in specs   if spec.aut_kind == 'requirement')
        if npl == len(plants) and nsp == len(specs):
            if sup.aut_kind == 'unknown':
                sup.set_kind('supervisor')

        dump_stats("Computed supervisor", sup)
        save_automaton(sup, "Supervisor saved in %s", sup_fname)
示例#29
0
def compute_shortest_path(comp_names, req_names, evt_pairs):
    """
    Compute shortest path with A* algorithm and type 1 requirements.

    @param comp_names: Available components (weighted automata).
    @type  comp_names: C{list} of L{str}

    @param req_names: Name of the requirement automata (unweighted automata).
    @type  req_names: C{list} of L{str}

    @param evt_pairs: Additional event pairs (eg "{(a, b), (c, e)}", "type1",
                      or "type2")
    @type  evt_pairs: C{str}
    """
    common.print_line('Started shortest path type 1 computation (version %s)' %
                      automata.version)
    coll = collection.Collection()
    comp_list = load_weighted_automata(coll, comp_names, False, True)
    req_list = frontend.load_automata(coll, req_names, False, True)

    evt_pairs = taskresource.process_event_pairs(coll, req_list, evt_pairs)
    compute_weight.compute_shortest_path(comp_list, req_list, evt_pairs)
示例#30
0
def make_language_equivalence_test(aut1_fname, aut2_fname):
    """
    Check whether the language of L{aut1_fname} is included in the language of
    L{aut2_fname}.

    @param aut1_fname: Filename of the first automaton.
    @type  aut1_fname: C{str}

    @param aut2_fname: Filename of the second automaton.
    @type  aut2_fname: C{str}
    """
    common.print_line("Started language equivalence test (version %s)"
                        % automata.version)
    coll = collection.Collection()

    aut1 = load_automaton(coll, aut1_fname, False, False)
    aut2 = load_automaton(coll, aut2_fname, False, False)

    res = verification.language_equivalence(aut1, aut2)
    if res:
        print "Language equivalence HOLDS"
    else:
        print "Language equivalence is INCORRECT"