plan_gen.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/usr/bin/env python3
  2. ''' Python generator for MATSim plans. '''
  3. import sys
  4. import time
  5. import numpy as np
  6. import lxml.etree as etree
  7. # constants
  8. MIN_DEPARTURE_TIME = 8 * 3600 # '08:00:00'
  9. MAX_DEPARTURE_TIME = 9 * 3600 # '09:00:00'
  10. WORK_DURATION = '04:00:00'
  11. def read_nodes(input_network):
  12. ''' returns all network nodes as a list '''
  13. tree = etree.parse(input_network)
  14. return [node for node in tree.xpath("/network/nodes/node")]
  15. def rand_time(low, high):
  16. ''' returns a random time between low and high bounds (in seconds) '''
  17. delta = np.random.randint(high - low)
  18. return time.strftime('%H:%M:%S', time.gmtime(low + delta))
  19. def rand_person(nodes):
  20. ''' returns a person as a dictionnary of random parameters '''
  21. len_nodes = len(nodes)
  22. # home coordinates
  23. home_node = nodes[np.random.randint(len_nodes)]
  24. home_xy = (home_node.get('x'), home_node.get('y'))
  25. # work coordinates
  26. work_node = nodes[np.random.randint(len_nodes)]
  27. work_xy = (work_node.get('x'), work_node.get('y'))
  28. # home departure time
  29. home_departure = rand_time(MIN_DEPARTURE_TIME, MAX_DEPARTURE_TIME)
  30. return {'home': home_xy, 'work': work_xy, 'home_departure': home_departure}
  31. def create_child(parent_node, child_name, child_attrs=None):
  32. ''' creates an xml child element and set its attributes '''
  33. child = etree.SubElement(parent_node, child_name)
  34. if child_attrs is None:
  35. return child
  36. for attr, value in child_attrs.items():
  37. child.set(attr, value)
  38. return child
  39. def make_plans(persons):
  40. ''' makes xml tree of plans based on persons list '''
  41. plans = etree.Element('plans')
  42. for n, p in enumerate(persons):
  43. person = create_child(plans, 'person', {'id': str(n+1)})
  44. plan = create_child(person, 'plan')
  45. # plan
  46. create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1], 'end_time': p['home_departure']})
  47. create_child(plan, 'leg', {'mode': 'car'})
  48. create_child(plan, 'act', {'type': 'w', 'x': p['work'][0], 'y': p['work'][1], 'dur': WORK_DURATION})
  49. create_child(plan, 'leg', {'mode': 'car'})
  50. create_child(plan, 'act', {'type': 'h', 'x': p['home'][0], 'y': p['home'][1]})
  51. return plans
  52. if __name__ == '__main__':
  53. # command line arguments
  54. if len(sys.argv) != 3:
  55. print('usage:', sys.argv[0], '<input_network> <nb_persons>')
  56. sys.exit(-1)
  57. INPUT_NETWORK = sys.argv[1]
  58. NB_PERSONS = int(sys.argv[2])
  59. NODES = read_nodes(INPUT_NETWORK)
  60. PERSONS = [rand_person(NODES) for _ in range(NB_PERSONS)]
  61. PLANS = make_plans(PERSONS)
  62. # print XML
  63. print('<?xml version="1.0" ?>')
  64. print('<!DOCTYPE plans SYSTEM "http://www.matsim.org/files/dtd/plans_v4.dtd">')
  65. print(etree.tostring(PLANS, pretty_print=True).decode('utf-8'))