def check_last_rescheduled_step():
        # stop in last possible cell, if no way to target
        for i, agent in enumerate(env.agents):
            controller = controllers[i]
            if agent.status not in [RailAgentStatus.ACTIVE, RailAgentStatus.READY_TO_DEPART]:
                continue

            if agent_position_duration[i] is None or len(cached_ways[i]) == 0:
                continue

            pos = agent_way_position[i]

            if pos == len(cached_ways[i]):
                #last vertex in new way is not target - stay here to end of simulation
                if cached_ways[i][-1].vertex_idx != controller.target_vertex:
                    locker.unlock(new_way[i][-1].vertex_idx, i, (new_way[i][-1].arrival_time, new_way[i][-1].departure_time + 1))

                    new_duration = (new_way[i][-1].arrival_time, INF_STEP)
                    locker.lock(new_way[i][-1].vertex_idx, i, new_duration )
                    new_way[i][-1].wait_steps = INF_STEP
                    new_way[i][-1].departure_time = new_duration[1]
            else:
                vertex_idx = cached_ways[i][pos].vertex_idx
                new_duration = (agent_position_duration[i][0], INF_STEP)
                locker.lock(vertex_idx, i, new_duration)
                new_way[i].append(AgentWayStep(vertex_idx=vertex_idx,
                                               direction=None,
                                               arrival_time=new_duration[0],
                                               departure_time=new_duration[1],
                                               wait_steps=INF_STEP,
                                               action=None,
                                               prev_way_id=-1))
    def rescheduling_main():
        # recalculate new duration for each agent on each cell of the cached way
        position_updated = True
        full_recalc_needed = False
        while position_updated:
            position_updated = False

            for i in range(len(controllers)):
                agent = env.agents[i]
                if (agent_way_position[i] >= len(cached_ways[i])) or agent_done(env, i):
                    continue

                vertex_idx = cached_ways[i][agent_way_position[i]].vertex_idx
                duration = agent_position_duration[i]

                if agent_way_position[i] == len(cached_ways[i])-1:
                    if vertex_idx == controllers[i].target_vertex:  # target vertex
                        new_way[i].append(AgentWayStep(vertex_idx=vertex_idx,
                                                       direction=None,
                                                       arrival_time=duration[0],
                                                       departure_time=duration[1],
                                                       wait_steps = 0,
                                                       action = None,
                                                       prev_way_id = -1))
                        locker.lock(vertex_idx, i, (duration[0], duration[1]))

                        assert len(vertex_agent_order[vertex_idx]) and vertex_agent_order[vertex_idx][0] == i
                        vertex_agent_order[vertex_idx].pop(0)
                        agent_position_duration[i] = None
                        agent_way_position[i] += 1
                        position_updated = True
                else:
                    next_vertex_idx = cached_ways[i][agent_way_position[i] + 1].vertex_idx
                    ticks_per_step = int(round(1 / env.agents[i].speed_data['speed']))

                    # if vertex_agent_order[next_vertex_idx][0] == i and vertex_agent_order[vertex_idx][0] == i: # possible move to next vertex
                    if vertex_agent_order[next_vertex_idx][0] == i:  # possible move to next vertex
                        new_duration = (duration[0], max(duration[1], locker.last_time_step(next_vertex_idx, i)))
                        # if agent_way_position[i]==0 and agent.speed_data['position_fraction'] > 0:
                        #     if new_duration != duration:
                        #         continue
                        duration = new_duration

                        #if not possible to reschedule right, do it with mistakes
                        if locker.is_locked(vertex_idx, i , duration):
                            d0 = duration[0]
                            d1 = duration[1]
                            ind = locker.equal_or_greater_index_end(vertex_idx, duration[0])
                            if ind>=0 and ind<len(locker.data[vertex_idx]):
                                d0 = max(d0, locker.data[vertex_idx][ind][0][1]+1)
                            ind = locker.equal_or_greater_index(vertex_idx, duration[0])
                            if ind >= 0 and ind < len(locker.data[vertex_idx]):
                                d1 = min(d1, locker.data[vertex_idx][ind][0][0])

                            if d1<=d0:
                                d1 = d0+1

                            print(f"Rescheduling mistake for train {i}. {duration[0]},{duration[1]} -> {d0}, {d1}")
                            duration = (d0, d1)
                            full_recalc_needed = True


                        new_way[i].append(AgentWayStep(vertex_idx=vertex_idx,
                                                       direction=None,
                                                       arrival_time=duration[0],
                                                       departure_time=duration[1],
                                                       wait_steps=0,
                                                       action=None,
                                                       prev_way_id=-1))

                        locker.lock(vertex_idx, i, (duration[0], duration[1]))

                        assert len(vertex_agent_order[vertex_idx]) and vertex_agent_order[vertex_idx][0] == i
                        vertex_agent_order[vertex_idx].pop(0)

                        # #bad situation... what can we do - the best we can
                        # assert len(vertex_agent_order[vertex_idx])
                        # index = vertex_agent_order[vertex_idx].index(i)
                        # if index>0:
                        #     print("Malfunction swapped order, ignore it for now")
                        #     full_recalc_needed = True
                        # vertex_agent_order[vertex_idx].pop(index)

                        position_updated = True

                        agent_way_position[i] += 1
                        if agent_way_position[i] == len(cached_ways[i]) - 1: # next vertex is target
                            duration = (duration[1], duration[1] + 1)
                        else:
                            duration = (duration[1], duration[1] + ticks_per_step)
                        agent_position_duration[i] = duration
        return full_recalc_needed
Example #3
0
    def rescheduling_main():
        # recalculate new duration for each agent on each cell of the cached way
        position_updated = True
        full_recalc_needed = False
        blocked_vertexes = set()

        for i, agent in enumerate(env.agents):
            if agent.status == RailAgentStatus.ACTIVE:
                controller = controllers[i]
                way = controller.get_cached_way()
                if len(way):
                    # assert len(way)
                    first_vertex = way[-1].vertex_idx

                    if vertex_agent_order[first_vertex][0] != i:
                        print('blocked at start', i, first_vertex)
                        blocked_vertexes.add(first_vertex)

                # assert vertex_agent_order[first_vertex][0] == i
                # assert way[0].arrival_time <= step_idx, (way[0].arrival_time, step_idx)

        while position_updated:
            position_updated = False

            for i in range(len(controllers)):
                agent = env.agents[i]
                if (agent_way_position[i] >= len(
                        cached_ways[i])) or agent_done(env, i):
                    continue

                vertex_idx = cached_ways[i][agent_way_position[i]].vertex_idx
                duration = agent_position_duration[i]

                if vertex_idx in blocked_vertexes:
                    continue

                if agent_way_position[i] == len(cached_ways[i]) - 1:
                    if vertex_idx == controllers[
                            i].target_vertex:  # target vertex
                        new_way[i].append(
                            AgentWayStep(vertex_idx=vertex_idx,
                                         direction=None,
                                         arrival_time=duration[0],
                                         departure_time=duration[1],
                                         wait_steps=0,
                                         action=None,
                                         prev_way_id=-1))
                        locker.lock(vertex_idx, i, (duration[0], duration[1]))

                        # assert len(vertex_agent_order[vertex_idx]) and vertex_agent_order[vertex_idx][0] == i
                        if not (len(vertex_agent_order[vertex_idx])
                                and vertex_agent_order[vertex_idx][0] == i):
                            blocked_vertexes.add(vertex_idx)
                            continue

                        vertex_agent_order[vertex_idx].pop(0)
                        agent_position_duration[i] = None
                        agent_way_position[i] += 1
                        position_updated = True
                else:
                    next_vertex_idx = cached_ways[i][agent_way_position[i] +
                                                     1].vertex_idx
                    ticks_per_step = int(
                        round(1 / env.agents[i].speed_data['speed']))

                    # if vertex_agent_order[next_vertex_idx][0] == i and vertex_agent_order[vertex_idx][0] == i: # possible move to next vertex
                    if vertex_agent_order[next_vertex_idx][
                            0] == i and next_vertex_idx not in blocked_vertexes:  # possible move to next vertex
                        new_duration = (duration[0],
                                        max(
                                            duration[1],
                                            locker.last_time_step(
                                                next_vertex_idx, i)))
                        # if agent_way_position[i]==0 and agent.speed_data['position_fraction'] > 0:
                        #     if new_duration != duration:
                        #         continue
                        duration = new_duration

                        if not (len(vertex_agent_order[vertex_idx])
                                and vertex_agent_order[vertex_idx][0] == i):
                            blocked_vertexes.add(vertex_idx)
                            continue

                        new_way[i].append(
                            AgentWayStep(vertex_idx=vertex_idx,
                                         direction=None,
                                         arrival_time=duration[0],
                                         departure_time=duration[1],
                                         wait_steps=0,
                                         action=None,
                                         prev_way_id=-1))

                        locker.lock(vertex_idx, i, (duration[0], duration[1]))

                        # assert len(vertex_agent_order[vertex_idx]) and vertex_agent_order[vertex_idx][0] == i
                        vertex_agent_order[vertex_idx].pop(0)

                        position_updated = True

                        agent_way_position[i] += 1
                        if agent_way_position[i] == len(
                                cached_ways[i]) - 1:  # next vertex is target
                            duration = (duration[1], duration[1] + 1)
                        else:
                            duration = (duration[1],
                                        duration[1] + ticks_per_step)
                        agent_position_duration[i] = duration
        return full_recalc_needed