Beispiel #1
0
    def __init__(self, event, duration, resources):
        """
        Constructor.

        @param event: Event.
        @type  event: L{Event}

        @param duration: Duration of the use.
        @type  duration: C{int} or C{float}

        @param resources: Available resources (alphabets).
        @type  resources: C{list} of C{set} of L{Event}
        """
        self.event = event
        self.duration = duration
        self.used = [(event in res) for res in resources]

        mat = self._compute_mat(resources, event, duration)
        q_tilde = [
            self._q_tilde_val(event in res, duration) for res in resources
        ]
        q_check = [
            self._q_check_val(event in res, duration) for res in resources
        ]
        q_check_mat = maxplus.ColumnMatrix(q_check)
        q_tilde_mat = maxplus.RowMatrix(q_tilde)
        multiply = maxplus.otimes_mat_mat(q_check_mat, q_tilde_mat)
        qq = maxplus.oplus_mat_mat(maxplus.make_unit_matrix(len(resources)),
                                   multiply)
        self.matHat = maxplus.otimes_mat_mat(mat, qq)
Beispiel #2
0
def reduce_automaton_row_vecors(waut, wvalues, evtdata, num_res, rvecs):
    """
    Reduce the weighted automaton.

    @param waut: (Weighted) automaton (the weight is not used).
    @type  waut: L{Automaton}

    @param wvalues: Column matrix data, associated with each state in L{waut}.
    @type  wvalues: L{maxplus.DataCollection}

    @param evtdata: Event information.
    @type  evtdata: L{EventData}

    @param num_res: Number of resources.
    @type  num_res: C{int}

    @param start: Start vector (row-matrix), if specified.
    @type  start: C{None}, or L{maxplus.DataCollection}

    @return: Reduced automaton.
    @rtype:  L{Automaton}
    """
    waut = waut.copy() # Make a copy
    wvalues = dict((st.number, val) for st, val in wvalues.iteritems())

    # Do a breadth-first expansion over the automaton.

    #: Mapping of states to their row matrix value.
    seen_states = set([waut.initial])
    not_done = [waut.initial]

    while len(not_done) > 0:
        # Since we do a breadth-first expansion, make a new 'not_done'
        # from scratch on each iteration.
        new_not = []
        for state in not_done:
            #rval = maxplus.make_rowmat(0, num_res)
            rval =  rvecs[state]
            sval = maxplus.otimes_mat_mat(rval, wvalues[state.number])
            toremove = []
            for edge in state.get_outgoing():
                result = maxplus.otimes_mat_mat(rval,
                                                evtdata[edge.label].matHat)
                cm = maxplus.otimes_mat_mat(result, wvalues[edge.succ.number])
                if cm.get_scalar() <= sval.get_scalar():
                    # Keep the edge.
                    if edge.succ not in seen_states: # It is a new state.
                        seen_states.add(edge.succ)
                        new_not.append(edge.succ)
                else:
                    # Drop the edge.
                    #waut.remove_edge(edge)
                    toremove.append(edge)
            for edge in toremove:
              waut.remove_edge(edge)
        # Next iteration.
        not_done = new_not

    waut.reduce(True, True)
    return waut
def add_abstracted_tau_paths(aut, eventdata, cliques, start_state, end_state,
                             evt_path):
    new_tau_evt_name = "tau"
    for evt in evt_path:
        if evt.name.find("tau") == 0:
            new_tau_evt_name = new_tau_evt_name + "-(" + evt.name + ")"
        else:
            new_tau_evt_name = new_tau_evt_name + "-" + evt.name
    new_tau_evt = aut.collection.make_event(new_tau_evt_name, True, True,
                                            False)
    if not new_tau_evt in aut.alphabet:
        aut.alphabet.add(new_tau_evt)
    aut.add_edge_data(start_state, end_state, new_tau_evt, 1)
    # fake init of ExtendedEventData
    tau_evt_data = taskresource.ExtendedEventData(
        new_tau_evt, 0, set([frozenset(aut.alphabet)]))
    # setting of actual resources and Matrix
    tau_evt_data.used = []
    for i in range(len(eventdata[evt_path[0]].used)):
        tau_evt_data.used.append(False)
        for j in range(len(evt_path)):
            if eventdata[evt_path[j]].used[i] == True:
                tau_evt_data.used[i] = True
                break
    tau_evt_data.matHat = eventdata[evt_path[0]].matHat
    for i in range(1, len(evt_path)):
        tau_evt_data.matHat = maxplus.otimes_mat_mat(
            tau_evt_data.matHat, eventdata[evt_path[i]].matHat)
    for i in range(len(tau_evt_data.matHat.data)):
        for j in range(len(tau_evt_data.matHat.data[i])):
            tau_evt_data.duration = maxplus.maximum(
                tau_evt_data.duration, tau_evt_data.matHat.data[i][j])
    eventdata[new_tau_evt] = tau_evt_data
Beispiel #4
0
def reduce_automaton_greedy_correctly(waut, wvalues, evtdata, num_res, L):
    """
    Reduce the weighted automaton.

    @param waut: (Weighted) automaton (the weight is not used).
    @type  waut: L{Automaton}

    @param wvalues: Column matrix data, associated with each state in L{waut}.
    @type  wvalues: L{maxplus.DataCollection}

    @param evtdata: Event information.
    @type  evtdata: L{EventData}

    @param num_res: Number of resources.
    @type  num_res: C{int}

    @param start: Start vector (row-matrix), if specified.
    @type  start: C{None}, or L{maxplus.DataCollection}

    @return: Reduced automaton.
    @rtype:  L{Automaton}
    """
    waut = waut.copy() # Make a copy
    wvalues = dict((st.number, val) for st, val in wvalues.iteritems())

    # Do a breadth-first expansion over the automaton.

    #: Mapping of states to their row matrix value.
    seen_states = set([waut.initial])
    not_done = [waut.initial]

    while len(not_done) > 0:
        # Since we do a breadth-first expansion, make a new 'not_done'
        # from scratch on each iteration.
        new_not_done = []
        for state in not_done:

            for edge in list(state.get_outgoing()):
                mq = maxplus.otimes_mat_mat(evtdata[edge.label].matHat, wvalues[edge.succ.number])
                th = wvalues[edge.pred.number]
                if compute_weight.compute_norm(mq, L) <= compute_weight.compute_norm(th, L):
                    # Keep the edge.
                    if edge.succ not in seen_states: # It is a new state.
                        seen_states.add(edge.succ)
                        new_not_done.append(edge.succ)
                else:
                    # Drop the edge.
                    waut.remove_edge(edge)

        # Next iteration.
        not_done = new_not_done

    waut.reduce(True, True)
    return waut
Beispiel #5
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)
Beispiel #6
0
def enhance_compute_state_row_vector(aut, marker_valfn, nonmarker_valfn,
                                     eventdata, operate_class):
    """
        Compute row vector of each state

        Attach a weight to each state, and iteratively update these weights until a
        stable situation is found.
         - Initial setup:
            - Marker states have weight 'marker_valfn(state)'.
            - Other states have weight 'nonmarker_valfn(state)'
         - Update rules:

        Update until all weights are stable.

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

        @return: Dictionary of states to their row vector.
        @rtype:  C{dict} of L{WeightedState} to (C{int} or C{None} if infinite)

        @todo: THIS CODE LOOKS LIKE A DUPLICATE
        """
    # 1. Compute state information for each state.
    computation = {}

    for state in aut.get_states():
        if state.marked:
            computation[state] = (MARKER_STATE, )
        #  continue

        # Non-marked states
        edges = []  #: Edges collected so far
        controllable = True  #: Collect controllable edges

        # Collect successor states from 'state' by event.
        evt_dests = {}  #: event to list (weight, dest-state).
        controllable = True  #: State has only edges with controllable events.
        for edge in state.get_outgoing():
            weight_dests = evt_dests.get(edge.label)
            if weight_dests is None:
                weight_dests = []
                evt_dests[edge.label] = weight_dests

                controllable = (controllable and edge.label.controllable)

            weight_dests.append((edge.weight, edge.succ))

        if controllable:
            # Keep all edges (all have controllable event label).
            edges = list(evt_dests.iteritems())
            # assert len(edges) > 0 # Otherwise cannot compute min or max.
            computation[state] = (CONTROLLABLE, edges)
        else:
            # Only keep edges with uncontrollable event labels.
            edges = [(evt, dests) for evt, dests in evt_dests.iteritems()
                     if not evt.controllable]
            #assert len(edges) > 0 # Otherwise cannot compute min or max.
            computation[state] = (UNCONTROLLABLE, edges)

    # 2. Initialize weights.
    row_vectors = {}  #: Map of states to a set of row vectors.
    need_to_update = set()
    for state in computation.iteritems():
        if state[0].number == MARKER_STATE:
            row_vectors[state[0]] = marker_valfn(state[0])
        else:
            row_vectors[state[0]] = nonmarker_valfn(state[0])
        need_to_update.update(compute_weight.pred_states(state[0]))

    count = 0
    # 3. Iteratively update the row vector with new ones until stable.
    while True:
        count = count + 1
        # Compute new row_vectors
        update_f = 0
        for state, comp in computation.iteritems():
            if state not in need_to_update:
                continue

            if comp[0] == MARKER_STATE:
                continue

            for evt, statedestlist in comp[1]:
                dest = (statedestlist[0])[1]
                tmp_vector = maxplus.otimes_mat_mat(row_vectors[state],
                                                    eventdata[evt].matHat)

                if operate_class == 1:
                    scalar1 = scalar_compute(tmp_vector)
                    scalar2 = scalar_compute(row_vectors[dest])
                    if scalar_compare(scalar1, scalar2) == -1:
                        row_vectors[dest] = tmp_vector
                        update_f = 1
                elif operate_class == 2:
                    flag = -1
                    row_vectors[dest], flag = minimal_compute(
                        tmp_vector, row_vectors[dest])
                    if flag == 0:
                        update_f = 1

        if update_f == 0:
            break

    return row_vectors
Beispiel #7
0
def compute_state_row_vector(aut, marker_valfn, nonmarker_valfn, eventdata,
                             operate_class):
    """
        Compute row vector of each state

        Attach a weight to each state, and iteratively update these weights until a
        stable situation is found.
         - Initial setup:
            - Marker states have weight 'marker_valfn(state)'.
            - Other states have weight 'nonmarker_valfn(state)'
         - Update rules:

        Update until all weights are stable.

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

        @return: Dictionary of states to their row vector.
        @rtype:  C{dict} of L{WeightedState} to (C{int} or C{None} if infinite)

        @todo: THIS CODE LOOKS LIKE A DUPLICATE
        """
    # 1. Compute state information for each state.
    computation = compute_weight.make_state_info_mapping(aut)

    # 2. Initialize weights.
    row_vectors = {}  #: Map of states to a set of row vectors.
    need_to_update = set()
    for state, comp in computation.iteritems():
        if state.number == MARKER_STATE:
            row_vectors[state] = marker_valfn(state)
        else:
            row_vectors[state] = nonmarker_valfn(state)
        need_to_update.update(compute_weight.pred_states(state))
    count = 0
    # 3. Iteratively update the row vector with new ones until stable.
    while True:
        count = count + 1
        # Compute new row_vectors
        new_need_to_update = set()
        for state, comp in computation.iteritems():
            if state not in need_to_update:
                continue

            if comp[0] == MARKER_STATE:
                continue

            for evt, statedestlist in comp[1]:
                dest = (statedestlist[0])[1]
                tmp_vector = maxplus.otimes_mat_mat(row_vectors[state],
                                                    eventdata[evt].matHat)

                if vector_equal_compare(tmp_vector, row_vectors[dest]) != 0:
                    new_need_to_update.update(
                        compute_weight.pred_states(state))

                if operate_class == 1:
                    scalar1 = scalar_compute(tmp_vector)
                    scalar2 = scalar_compute(row_vectors[dest])
                    if scalar_compare(scalar1, scalar2) == -1:
                        row_vectors[dest] = tmp_vector
                elif operate_class == 2:
                    row_vectors[dest], f = minimal_compute(
                        tmp_vector, row_vectors[dest])

        if len(new_need_to_update) == 0:
            break

        need_to_update = new_need_to_update

    for state, comp in computation.iteritems():
        M = row_vectors[state]
    return row_vectors
Beispiel #8
0
def traverse(aut_list, plant, start_state, mapping, heap_map, eventdata, aut_resource_usage, distances_to_marker, shortest_path_max):
    global path_found
    if path_found:
        return
    if plant.get_num_states() % 1000 == 0:
        common.print_line("%d states traversed." % plant.get_num_states())
    edges = []
    disabled = set()
    for aut, state in zip(aut_list, mapping[start_state]):
        aut_edges = []
        aut_events = set()
        for edge in state.get_outgoing():
            aut_edges.append(edge)
            aut_events.add(edge.label)
        edges.append(aut_edges)
        disabled.update(aut.alphabet.difference(aut_events))
        
    for evt in plant.alphabet.difference(disabled):
        if path_found:
            return
        target_mapping = calc_target(aut_list, mapping[start_state], evt)
        
        # state collision part, make it nicer
        state_name_list = []
        for aut, state in zip(aut_list, target_mapping):
            for name in aut.state_names[state.number].split("_"):
                state_name_list.append(name)
        if len(state_name_list) > len(set(state_name_list)):
            continue
        
        target_heap = maxplus.otimes_mat_mat(heap_map[start_state], eventdata[evt].matHat)
        
        do_this_event = True
        if target_mapping in mapping.values():
            do_this_event = False
            for state, map in mapping.items():
                if map == target_mapping:
                    for heap_old, heap_new in zip(heap_map[state].data[0], target_heap.data[0]):
                        if heap_new < heap_old:
                            do_this_event = True
                            break
                if do_this_event == True:
                    break
        if do_this_event == False:
            continue
        do_this_event = False
        for aut, start, target in zip(aut_list, mapping[start_state], target_mapping):
            if distances_to_marker[aut][start] > distances_to_marker[aut][target]:
                do_this_event = True
                break
        if do_this_event == False:
            continue
        for aut, start, target in zip(aut_list, mapping[start_state], target_mapping):
            if target_heap.data[0][aut_resource_usage[aut]] + distances_to_marker[aut][target] > shortest_path_max:
                do_this_event = False
                break
        if do_this_event == False:
            continue
        if do_this_event:
            # add target state to plant
            target_state = plant.add_new_state(marker_calc(target_mapping))
            # add transition to plant
            new_edge = data_structure.Edge(start_state, target_state, evt)
            plant.add_edge(new_edge)
            # add mapping
            mapping[target_state] = target_mapping
            heap_map[target_state] = target_heap
            if marker_calc(target_mapping):
                path_found = True
                common.print_line("Path length:")
                print max(target_heap.data[0])
                break
            else:
                traverse(aut_list, plant, target_state, mapping, heap_map, eventdata, aut_resource_usage, distances_to_marker, shortest_path_max)