def early_execution(network: STN, realization: dict) -> bool: ## Bookkeeping for events all_uncontrollables = set(network.uncontrollables) unused_events = set(network.verts.keys()) not_scheduled = PriorityQueue() final_schedule = {} # Mapping from contingent sources to uncontrollables contingent_pairs = network.contingentEdges.keys() disabled_uncontrollables = {src: sink for (src, sink) in contingent_pairs} # Initialize bounds for simulation - starts off with just controllables # and zero time point controllable_bounds = find_bounds(network) true_weight = {} for event in controllable_bounds: not_scheduled.push(event, controllable_bounds[0]) true_weight[event] = controllable_bounds[0] not_scheduled.addOrDecKey(ZERO_ID, 0) # Run simulation old_time = 0 while len(unused_events) > 0: current_time, activated_event = not_scheduled.pop() # This check ensures that we popped out a valid time_point # A better way to deal with this would be to just figure out a way to # increase priorities of elements in a heap if activated_event in true_weight: if true_weight[activated_event] > current_time: continue unused_events.remove(activated_event) final_schedule[activated_event] = current_time assert old_time < current_time, "Chronology violated!" if activated_event in disabled_uncontrollables: # If this is a contingent source, we add the associated uncontrollable sink # to the queue uncontrollable = disabled_uncontrollables[activated_event] delay = realization[uncontrollable] not_scheduled.push(uncontrollable, current_time + delay) # Update the bounds for all other timepoints # We only care about events being moved later in time relevant_edges = network.getEdges(activated_event) for edge in relevant_edges: if (edge.j == activated_event) and (edge.i not in all_uncontrollables): if needs_early_update(edge, activated_event, current_time, true_weight): lower_bound = current_time - edge.Cij true_weight[edge.i] = lower_bound # Keep track of this for next iteration of loop old_time = current_time # Check if we dispatched succesfully return emp.scheduleIsValid(network, final_schedule)
def safely_scheduled(network: STN, partial: dict, event) -> bool: assert event in partial, "Event not in partial schedule!" epsilon = 0.001 edges = network.getEdges(event) for edge in edges: if (edge.i in partial) and (edge.j in partial): start, end = (edge.i, edge.j) lBound, uBound = (-edge.Cji, edge.Cij) boundedAbove = (partial[end] - partial[start]) <= uBound + epsilon boundedBelow = (partial[end] - partial[start]) >= lBound - epsilon if ((not boundedAbove) or (not boundedBelow)): #print("Violated constraint", edge) return False return True