def reduce_automaton(waut, wvalues, evtdata, num_res, start = None): """ 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) sval = maxplus.otimes_mat_mat(rval, wvalues[state.number]) for edge in list(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) # Next iteration. not_done = new_not waut.reduce(True, True) return waut
def calcpath_mult(auts, eventdata, heap_len): pathstatetup = [aut.initial for aut in auts] weight = maxplus.matrix_to_vector(maxplus.make_rowmat(0, heap_len)) wavers = 0 alphabet = set() for aut in auts: alphabet.update(aut.alphabet) newwaver = None #newwaver = aut.collection.events['NewWaver'] while not (allmarked(pathstatetup) and wavers == 0): possibleedges = None beststart = None cannewwaver = None successors = [] for state in pathstatetup: successors.append( {edge.label: edge.succ for edge in state.get_outgoing()}) act_successors = [] for evt in alphabet: successor_tup = [] for i, dictionary in enumerate(successors): if evt not in auts[i].alphabet: successor_tup.append(pathstatetup[i]) elif evt not in dictionary: successor_tup = None break else: successor_tup.append(dictionary[evt]) if successor_tup: act_successors.append((evt, successor_tup)) for tup in act_successors: event, pathstate = tup if event == newwaver: cannewwaver = tup continue soonestfire = calcstarttime(weight, eventdata[event].used) if beststart == None or soonestfire < beststart: soonestfire = beststart possibleedges = [tup] elif beststart == soonestfire: possibleedges.append(tup) if wavers != 0 and cannewwaver != None and ( beststart == None or beststart >= calcstarttime(weight, eventdata[newwaver].used)): wavers -= 1 possibleedges = [cannewwaver] index = random.randrange(len(possibleedges)) tup = possibleedges[index] event = tup[0] pathstatetup = tup[1] weight = maxplus.newtimes_vec_vec(weight, eventdata[event].matHat) print event print weight print "weight: " + str(weight)
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
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)
def enhanced_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 = do_n_ary_product_map(comp_list) for comp in comp_list: comp.clear() del comp_list wsup = plant.get_automaton() if wsup is None: return None row_zero_mat = maxplus.make_rowmat(0, 1) row_epsilon_mat = maxplus.make_rowmat(maxplus.INFINITE, 1) marker_valfn = lambda state: row_zero_mat nonmarker_valfn = lambda state: row_epsilon_mat row_vecs = enhance_compute_state_row_vector(wsup, marker_valfn, nonmarker_valfn, eventdata, operator_class) return row_vecs
def calcpath(aut, eventdata, heap_len, num): pathstate = aut.initial weight = maxplus.matrix_to_vector(maxplus.make_rowmat(0, heap_len)) wavers = num #newwaver = aut.collection.events["R1-pick-C"] if "NewWaver" in aut.collection.events: newwaver = aut.collection.events["NewWaver"] else: newwaver = None procevent = aut.collection.events["R1-drop-C"] processed = 0 #newwaver = None while not (pathstate.marked and wavers == 0): possibleedges = None beststart = None cannewwaver = None for edge in pathstate.get_outgoing(): if edge.label == newwaver: cannewwaver = edge continue pathstate = edge.succ event = edge.label soonestfire = calcstarttime(weight, eventdata[event].used) if beststart == None or soonestfire < beststart: soonestfire = beststart possibleedges = [edge] elif beststart == soonestfire: possibleedges.append(edge) if wavers != 0 and cannewwaver != None and ( beststart == None or beststart >= calcstarttime(weight, eventdata[newwaver].used)): wavers -= 1 possibleedges = [cannewwaver] index = random.randrange(len(possibleedges)) edge = possibleedges[index] event = edge.label #print event pathstate = edge.succ weight = maxplus.newtimes_vec_vec(weight, eventdata[event].matHat) if event == procevent: processed += 1 print "weight: " + str(weight) + " processed: num"
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