plan_gen.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python3
  2. ''' plan_gen main functions '''
  3. import time
  4. import numpy as np
  5. import lxml.etree as etree
  6. # constants
  7. # ------------------
  8. MIN_DEPARTURE_TIME = '08:00:00'
  9. MAX_DEPARTURE_TIME = '09:00:00'
  10. WORK_DURATION = '04:00:00'
  11. # utils
  12. # ------------------
  13. def parse_value(string):
  14. ''' convert string to int, float or string '''
  15. try:
  16. return int(string)
  17. except ValueError:
  18. try:
  19. return float(string)
  20. except ValueError:
  21. return string
  22. def parse_params(param_str):
  23. ''' parse a param string to a dict '''
  24. dict_params = {}
  25. if param_str:
  26. for key_value_str in param_str.split(','):
  27. key, value = key_value_str.split('=')
  28. if key in ['hc', 'wc']:
  29. dict_params[key] = [file for file in value.split(':')]
  30. else:
  31. dict_params[key] = parse_value(value)
  32. return dict_params
  33. def get_seconds(time_str):
  34. ''' returns seconds from a time string '''
  35. h, m, s = time_str.split(':')
  36. return int(h) * 3600 + int(m) * 60 + int(s)
  37. # main functions
  38. # ------------------
  39. def rand_time(low, high):
  40. ''' returns a random time between low and high bounds '''
  41. low_s = get_seconds(low)
  42. high_s = get_seconds(high)
  43. delta = np.random.randint(high_s - low_s)
  44. return time.strftime('%H:%M:%S', time.gmtime(low_s + delta))
  45. def rand_node_xy(nodes, clusters):
  46. ''' returns a random node coordinates from a list of nodes '''
  47. used_nodes = nodes
  48. if any(clusters):
  49. cluster = np.random.randint(len(clusters))
  50. used_nodes = clusters[cluster]
  51. node = used_nodes[np.random.randint(len(used_nodes))]
  52. return (node.get('x'), node.get('y'))
  53. def rand_person(nodes, home_clusters, work_clusters):
  54. ''' returns a person as a dictionnary of random parameters '''
  55. home_xy = rand_node_xy(nodes, home_clusters)
  56. work_xy = rand_node_xy(nodes, work_clusters)
  57. home_departure = rand_time(MIN_DEPARTURE_TIME, MAX_DEPARTURE_TIME)
  58. return {'home': home_xy, 'work': work_xy, 'home_departure': home_departure}
  59. def create_child(parent_node, child_name, child_attrs=None):
  60. ''' creates an xml child element and set its attributes '''
  61. child = etree.SubElement(parent_node, child_name)
  62. if child_attrs is None:
  63. return child
  64. for attr, value in child_attrs.items():
  65. child.set(attr, value)
  66. return child
  67. def make_plans(persons):
  68. ''' makes xml tree of plans based on persons list '''
  69. plans = etree.Element('plans')
  70. for n, p in enumerate(persons):
  71. person = create_child(plans, 'person', {'id': str(n+1)})
  72. plan = create_child(person, 'plan')
  73. # plan
  74. create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1], 'end_time': p['home_departure']})
  75. create_child(plan, 'leg', {'mode': 'car'})
  76. create_child(plan, 'act', {'type': 'w', 'x': p['work'][0], 'y': p['work'][1], 'dur': WORK_DURATION})
  77. create_child(plan, 'leg', {'mode': 'car'})
  78. create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1]})
  79. return plans
  80. def read_nodes(input_network):
  81. ''' returns all network nodes as a list '''
  82. if not input_network:
  83. return None
  84. tree = etree.parse(input_network)
  85. return [node for node in tree.xpath("/network/nodes/node")]