0

I am trying to write a function that will take me from one state to the next until I reach the final state. When I run this with:

new_location = change_location()

next(new_location)

The first iteration works but once I get into the while loop it never leaves the first if clause and also has no connection to the previous location. I am trying to move from one state to another where the states are e(only comes once at the start), da, dr, f, s, and ch (and ex) (only come at the end!). The paths they follow are always separated by 'to'.

I also tried having a yield statement after each clause but the desired pattern was still not followed. p are the probability weights that each path to the next location will be taken.

import numpy as np

def change_location():
        location = np.random.choice(['etof', 'etoda', 'etos', 'etodr'], 
                                          p =[0.377435, 0.287576, 0.181463, 0.153526])
        yield location
        while True:
            print(location)
            if location == 'etoda' or 'datoda' or 'drtoda'or 'ftoda' or 'stoda':
                location = np.random.choice(a=['datoch', 'datoda', 'datodr', 'datof', 'datos'], 
                p =[0.100000,0.740000,0.060000,0.050000,0.050000])
            elif location == 'etodr' or 'drtodr' or 'datodr' or 'ftodr' or 'stodr':
                location = np.random.choice(a=['drtoch', 'drtoda', 'drtodr','drtof', 'drtos'], 
                p =[0.215710, 0.010899, 0.598499, 0.087909,0.086983])
            elif location == 'etof' or 'datof' or 'drtof' or 'ftof' or 'stof':
                location = np.random.choice(a=['ftoch', 'ftoda', 'ftodr', 'ftof', 'ftos'], 
                p =[0.201605,0.095924,0.054847,0.596947,0.050677])
            elif location == 'etos' or 'datos' or 'drtos' or 'ftos' or 'stos':
                location = np.random.choice(a=['stoch', 'stoda', 'stodr', 'stof', 'stos'], 
                p =[0.150685,0.193214,0.163109,0.090953,0.402039])
            else:
                location = 'chtoex'
                break
            yield location
  • 4
    You are misunderstanding how to check if `location` is one of multiple values. See https://stackoverflow.com/questions/15112125/how-to-test-multiple-variables-against-a-value – Chrispresso Apr 04 '20 at 20:15
  • 1
    statement `if location = 'etoda' or 'datoda' or [...]:`, etc should be `if location in ('etoda', 'datode', [...]):` – Johan Schiff Apr 04 '20 at 20:15
  • Thanks the link and tip were both a big help. Learning a lot. Just started all of this a few weeks ago. – SamuelAdamsMcGuire Apr 05 '20 at 10:38

1 Answers1

0

First thing is ofc the error pointed out in the comments. Bu I would also like to point out that whenever you see code with so many if:s and elif:s, all repeating a pattern, it gets very hard to spot and correct errors. There is a better way.

Structure the data separately, and keep the code lean using for and else.

import numpy as np

location_mappings = [
    {
        'from': [None],
        'to': ['etof', 'etoda', 'etos', 'etodr'],
        'p': [0.377435, 0.287576, 0.181463, 0.153526],
    },
    {
        'from': ['etoda', 'datoda', 'drtoda', 'ftoda', 'stoda'],
        'to': ['datoch', 'datoda', 'datodr', 'datof', 'datos'],
        'p': [0.100000,0.740000,0.060000,0.050000,0.050000],
    },
    {
        'from': ['etodr', 'drtodr', 'datodr', 'ftodr', 'stodr'],
        'to': ['drtoch', 'drtoda', 'drtodr','drtof', 'drtos'],
        'p': [0.215710, 0.010899, 0.598499, 0.087909,0.086983],
    },
    {
        'from': ['etof', 'datof', 'drtof', 'ftof', 'stof'],
        'to': ['ftoch', 'ftoda', 'ftodr', 'ftof', 'ftos'],
        'p': [0.201605,0.095924,0.054847,0.596947,0.050677],
    },
    {
        'from': ['etos', 'datos', 'drtos', 'ftos', 'stos'],
        'to': ['stoch', 'stoda', 'stodr', 'stof', 'stos'],
        'p': [0.150685,0.193214,0.163109,0.090953,0.402039],
    },
]
end_location = 'chtoex'

def change_location():
    location = None
    while location != end_location:
        for mapping in location_mappings:
            if location in mapping['from']:
                location = np.random.choice(mapping['to'], p=mapping['p'])
                break
        else:  # If break was not called
            location = end_location
        yield location
Johan Schiff
  • 651
  • 4
  • 13