Beispiel #1
0
def split_links_break_nodes(O, D, travel_time, new_node, break_time,
                            reset_time):
    """split the link from O to D in half
    arguments: O: origin node, integer
               D: destination node, integer
               travel_time: time from O to D, integer
               starting_node: starting point for new nodes, integer
    returns: 2 dimensional array of travel times for new nodes.
             This array is one-directional, from O to D.  Nodes
             are numbered from starting_node + zero, sequentially,
             new_node
    """
    bn = BN.BreakNode(O, D, travel_time, new_node, break_time, reset_time)
    new_times = Demand.zeroed_trip_triplets(3)
    # np.zeros(3,dtype=[('x', np.int), ('y', np.int),('t',np.float)])

    # # copy existing.  this is redundant
    # new_times[0] = [O,O,0]
    # new_times[1] = [O,D,travel_time]
    # new_times[2] = [D,D,0]

    # compute travel minutes
    new_times[0] = (O, new_node, bn.tt_o)
    new_times[1] = (new_node, new_node, 0)
    new_times[2] = (new_node, D, bn.tt_d)

    # new nodes are stored in "new_times" as keys of second dimension
    # not symmetric, but rather, directional.  Opposite way is impossible
    # so those values are NaN and easily set to infinity
    return (new_times, bn)
Beispiel #2
0
def split_break_node(record, travel_times, min_start=None):
    """Pass in a demand record, and split out all the required break nodes
    to get to the origin from the depot, to the destination from the
    origin, and back to the depot from the destination

    This function knows about the break rules.  Currently only one is
    implemented (drive 11, break 10).  Working on drive 8 break 0.5,
    then will work on on-duty 14 break 10.

    """

    if min_start == None:
        min_start = len(travel_times.index)
    new_times = Demand.zeroed_trip_triplets(0)
    # np.zeros(0,dtype=[('x', np.int), ('y', np.int),('t',np.float)])
    new_nodes = []
    tt = travel_times.loc[0, record.origin]
    if not np.isnan(tt):
        pair = break_node_splitter(0, record.origin, tt, min_start)
        new_times = np.concatenate((new_times, pair[0]), axis=0)
        new_nodes.extend(pair[1])
        min_start = pair[2]

    tt = travel_times.loc[record.origin, record.destination]
    if not np.isnan(tt):
        pair = break_node_splitter(record.origin, record.destination, tt,
                                   min_start)
        new_times = np.concatenate((new_times, pair[0]), axis=0)
        new_times = np.concatenate((new_times, pair[0]), axis=0)
        new_nodes.extend(pair[1])
        min_start = pair[2]

    tt = travel_times.loc[record.destination, 0]
    if not np.isnan(tt):
        pair = break_node_splitter(record.destination, 0, tt, min_start)
        new_times = np.concatenate((new_times, pair[0]), axis=0)
        new_nodes.extend(pair[1])
        min_start = pair[2]
    #print(new_times)

    return (new_times, new_nodes, min_start)
Beispiel #3
0
def break_node_splitter(origin, destination, tt, min_start):
    """Given an Origin and a Destination node, plus travel time between
    and the numbering of nodes (min start is an integer for the first
    node that will be created), create necessary break nodes between O
    and D that will satisfy the break rules.

    Currently knows only about the 11hr drive, 10hr break rule.

    Going to make it work for 8hr drive, 0.5hr break.

    """
    new_times = Demand.zeroed_trip_triplets(0)
    # np.zeros(0,dtype=[('x', np.int), ('y', np.int),('t',np.float)])
    new_nodes = []
    long_break_time = 60 * 10
    long_break_interval = 60 * 11
    short_break_time = 30
    short_break_interval = 60 * 8

    # for the 11 hour drive rule
    long_possible_breaks = math.ceil(tt / (11 * 60))
    if long_possible_breaks == 0:
        long_possible_breaks = 1

    # no real need to count up 8 hr breaks...at a minimum, can slot
    # one in between each 11 hr break
    segment_tt = tt
    for i in range(0, long_possible_breaks):
        # insert 11 hr break opportunity
        pair11 = split_links_break_nodes(origin, destination, segment_tt,
                                         min_start, long_break_time,
                                         long_break_interval)
        min_start += 1

        node11 = pair11[1]

        # possibly set up a dimension thing here?
        # node11.add_dimension_name('Drive') # or similar?

        # slot in an 8 hr break between origin and 11 hr
        pair8 = split_links_break_nodes(origin, node11.node, node11.tt_o,
                                        min_start, short_break_time,
                                        short_break_interval)
        node8 = pair8[1]
        # need to correct the destination of the node8 because of the
        # way the demand object stores and retrieves breaks between an
        # OD pair
        node8.destination = destination
        min_start += 1

        # possibly set up a dimension thing here too?
        # pair8[1].add_dimension_name('halfhrbreak') # or similar?

        # if i==long_possible_breaks-1:
        #     # closing in on destination, so include potential to get
        #     # from short break to goal?
        #     extra_link = np.array([node8.node,destination,node8.tt_d+node11.tt_d])
        #     new_times = np.concatenate(new_times,
        #                                 pair11[0],
        #                                 pair8[0])
        new_times = np.concatenate((new_times, pair11[0], pair8[0]), axis=0)

        # but I want the 8hr break nodes coming before the 11 hr ones
        new_nodes.append(pair8[1])
        new_nodes.append(pair11[1])

        # set for next loop
        segment_tt = node11.tt_d
        origin = node11.node

    # end of loop.  Consider boundary conditions
    node8 = new_nodes[-2]
    node11 = new_nodes[-1]
    # might not need a short break after long break prior to
    # arrival at destination, so make it so can just get to dest
    # from short break
    extra_connection = np.array(
        [(node8.node, destination, node8.tt_d + node11.tt_d)],
        dtype=[('x', np.int), ('y', np.int), ('t', np.float)])
    new_times = np.concatenate((new_times, extra_connection), axis=0)
    # print(tt,long_possible_breaks*long_break_interval,
    #       tt - long_possible_breaks*long_break_interval)

    # might need another 8 hr break node, but
    # only put in another 8 hr node if need to do so
    if tt - ((long_possible_breaks - 1) *
             long_break_interval) > short_break_interval:
        # in this case, might need a short break before long break,
        # then another short break prior to destination (worst case,
        # pickup, 0 time, long break, 8hrs, need short break,
        # dest). so make it here

        pair8 = split_links_break_nodes(node11.node, destination, node11.tt_d,
                                        min_start, short_break_time,
                                        short_break_interval)
        min_start += 1  # not necessary, but good habit

        new_times = np.concatenate((new_times, pair8[0]), axis=0)
        new_nodes.append(pair8[1])

    return (new_times, new_nodes, min_start)