Skip to content

enforce_route() doesn't act like expected #226

@Bolin-Z

Description

@Bolin-Z

I encouter this problem when I simulate the charging behavior of electric vehicles at nodes by adding self-loops virtual links to the nodes. I attempt to use the enforce_route() method to ensure that the electric vehicles pass through these specific charging links. I use traveled_route() to check the actual routes these electric vehicles take. However, they don't act like expected.

Therefore, I run the following script for testing:

import uxsim
for i in range(10):
    W = uxsim.World(name="test", tmax=1000, print_mode=0)
    W.addNode("A", 0, 0)
    W.addNode("B", 1, 1)
    W.addNode("C", 2, 2)

    W.addLink("A-B","A", "B", 1000)
    W.addLink("B-C","B", "C", 1000)
    W.addLink("A-A", "A", "A", 1000)
    W.addLink("A-C", "A", "C", 1000)    
    
    veh = W.addVehicle("A", "C", 0)
    veh.enforce_route(["A-A","A-B","B-C"])
    W.exec_simulation()
    
    route, _ = veh.traveled_route()
    print(f"[{i}]:\t {route} {W.analyzer.trip_all - W.analyzer.trip_completed}")

and the output is:

[0]:     <Route : [<Link A-B>, <Link B-C>]> 0
[1]:     <Route : [<Link A-B>, <Link B-C>]> 0
[2]:     <Route : [<Link A-B>, <Link B-C>]> 0
[3]:     <Route : [<Link A-A>, <Link A-B>, <Link B-C>]> 0
[4]:     <Route : [<Link A-B>, <Link B-C>]> 0
[5]:     <Route : [<Link A-B>, <Link B-C>]> 0
[6]:     <Route : [<Link A-B>, <Link B-C>]> 0
[7]:     <Route : [<Link A-B>, <Link B-C>]> 0
[8]:     <Route : [<Link A-B>, <Link B-C>]> 0
[9]:     <Route : [<Link A-A>, <Link A-B>, <Link B-C>]> 0

Sometimes <Link A-A> is included, and sometimes it is not.
When i delete <Link A-C>:

import uxsim
for i in range(10):
    W = uxsim.World(name="test", tmax=1000, print_mode=0)
    W.addNode("A", 0, 0)
    W.addNode("B", 1, 1)
    W.addNode("C", 2, 2)

    W.addLink("A-B","A", "B", 1000)
    W.addLink("B-C","B", "C", 1000)
    W.addLink("A-A", "A", "A", 1000)
    # W.addLink("A-C", "A", "C", 1000)    
    
    veh = W.addVehicle("A", "C", 0)
    veh.enforce_route(["A-A","A-B","B-C"])
    W.exec_simulation()
    
    route, _ = veh.traveled_route()
    print(f"[{i}]:\t {route} {W.analyzer.trip_all - W.analyzer.trip_completed}")

the result turns out to be:

[0]:     <Route : [<Link A-B>, <Link B-C>]> 0
[1]:     <Route : [<Link A-B>, <Link B-C>]> 0
[2]:     <Route : [<Link A-B>, <Link B-C>]> 0
[3]:     <Route : [<Link A-B>, <Link B-C>]> 0
[4]:     <Route : [<Link A-B>, <Link B-C>]> 0
[5]:     <Route : [<Link A-B>, <Link B-C>]> 0
[6]:     <Route : [<Link A-B>, <Link B-C>]> 0
[7]:     <Route : [<Link A-B>, <Link B-C>]> 0
[8]:     <Route : [<Link A-B>, <Link B-C>]> 0
[9]:     <Route : [<Link A-B>, <Link B-C>]> 0

I try to add a virtual node to avoid self-loop link like this:

import uxsim
for i in range(10):
    W = uxsim.World(name="test", tmax=1000, print_mode=0)
    W.addNode("A", 0, 0)
    W.addNode("B", 1, 1)
    W.addNode("C", 2, 2)
    W.addLink("A-B","A", "B", 1000)
    W.addLink("B-A", "B", "A", 1000)
    W.addLink("A-C","A", "C", 1000)
    
    veh = W.addVehicle("A", "C", 0)
    veh.enforce_route(["A-B","B-A","A-C"])
    
    W.exec_simulation()

    route, _ = veh.traveled_route()
    print(f"[{i}]:\t {route} {W.analyzer.trip_all - W.analyzer.trip_completed}")

but the output is:

[0]:     <Route : [<Link A-C>]> 0
[1]:     <Route : [<Link A-C>]> 0
[2]:     <Route : [<Link A-C>]> 0
[3]:     <Route : [<Link A-C>]> 0
[4]:     <Route : [<Link A-C>]> 0
[5]:     <Route : [<Link A-C>]> 0
[6]:     <Route : [<Link A-C>]> 0
[7]:     <Route : [<Link A-C>]> 0
[8]:     <Route : [<Link A-C>]> 0
[9]:     <Route : [<Link A-C>]> 0

I check the related code for selecting outgoing link. The code here does not seem to select based on the link specified in enforce_route().

def route_next_link_choice(s):
    """
    Select a next link from the current link.
    """
    if s.dest != s.link.end_node:
        outlinks = list(s.link.end_node.outlinks.values())

        if len(outlinks):

            #if links_prefer is given and available at the node, select only from the links in the list. if links_avoid is given, select links not in the list.
            if set(outlinks) & set(s.links_prefer):
                outlinks = sorted(set(outlinks) & set(s.links_prefer), key=lambda l:l.name)
            if set(outlinks) & set(s.links_avoid):
                outlinks = sorted(set(outlinks) - set(s.links_avoid), key=lambda l:l.name)

            preference = np.array([s.route_pref[l.id] for l in outlinks], dtype=float)
            if s.W.hard_deterministic_mode == False:
                if sum(preference) > 0:
                    s.route_next_link = s.W.rng.choice(outlinks, p=preference/sum(preference))
                else:
                    s.route_next_link = s.W.rng.choice(outlinks)
            else:
                s.route_next_link = max(zip(preference, outlinks), key=lambda x:x[0])[1]

        else:
            s.route_next_link = None

I want to know if uxsim supports specifying such routes that contain rings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions