run_search.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import argparse
  2. from timeit import default_timer as timer
  3. from aimacode.search import InstrumentedProblem
  4. from aimacode.search import (breadth_first_search, astar_search,
  5. breadth_first_tree_search, depth_first_graph_search, uniform_cost_search,
  6. greedy_best_first_graph_search, depth_limited_search,
  7. recursive_best_first_search)
  8. from my_air_cargo_problems import air_cargo_p1, air_cargo_p2, air_cargo_p3
  9. PROBLEM_CHOICE_MSG = """
  10. Select from the following list of air cargo problems. You may choose more than
  11. one by entering multiple selections separated by spaces.
  12. """
  13. SEARCH_METHOD_CHOICE_MSG = """
  14. Select from the following list of search functions. You may choose more than
  15. one by entering multiple selections separated by spaces.
  16. """
  17. INVALID_ARG_MSG = """
  18. You must either use the -m flag to run in manual mode, or use both the -p and
  19. -s flags to specify a list of problems and search algorithms to run. Valid
  20. choices for each include:
  21. """
  22. PROBLEMS = [["Air Cargo Problem 1", air_cargo_p1],
  23. ["Air Cargo Problem 2", air_cargo_p2],
  24. ["Air Cargo Problem 3", air_cargo_p3]]
  25. SEARCHES = [["breadth_first_search", breadth_first_search, ""],
  26. ['breadth_first_tree_search', breadth_first_tree_search, ""],
  27. ['depth_first_graph_search', depth_first_graph_search, ""],
  28. ['depth_limited_search', depth_limited_search, ""],
  29. ['uniform_cost_search', uniform_cost_search, ""],
  30. ['recursive_best_first_search', recursive_best_first_search, 'h_1'],
  31. ['greedy_best_first_graph_search', greedy_best_first_graph_search, 'h_1'],
  32. ['astar_search', astar_search, 'h_1'],
  33. ['astar_search', astar_search, 'h_ignore_preconditions'],
  34. ['astar_search', astar_search, 'h_pg_levelsum'],
  35. ]
  36. class PrintableProblem(InstrumentedProblem):
  37. """ InstrumentedProblem keeps track of stats during search, and this
  38. class modifies the print output of those statistics for air cargo
  39. problems.
  40. """
  41. def __repr__(self):
  42. return '{:^10d} {:^10d} {:^10d}'.format(self.succs, self.goal_tests, self.states)
  43. def run_search(problem, search_function, parameter=None):
  44. start = timer()
  45. ip = PrintableProblem(problem)
  46. if parameter is not None:
  47. node = search_function(ip, parameter)
  48. else:
  49. node = search_function(ip)
  50. end = timer()
  51. print("\nExpansions Goal Tests New Nodes")
  52. print("{}\n".format(ip))
  53. show_solution(node, end - start)
  54. print()
  55. def manual():
  56. print(PROBLEM_CHOICE_MSG)
  57. for idx, (name, _) in enumerate(PROBLEMS):
  58. print(" {!s}. {}".format(idx+1, name))
  59. p_choices = input("> ").split()
  60. print(SEARCH_METHOD_CHOICE_MSG)
  61. for idx, (name, _, heuristic) in enumerate(SEARCHES):
  62. print(" {!s}. {} {}".format(idx+1, name, heuristic))
  63. s_choices = input("> ").split()
  64. main(p_choices, s_choices)
  65. print("\nYou can run this selection again automatically from the command " +
  66. "line\nwith the following command:")
  67. print("\n python {} -p {} -s {}\n".format(__file__,
  68. " ".join(p_choices),
  69. " ".join(s_choices)))
  70. def main(p_choices, s_choices):
  71. problems = [PROBLEMS[i-1] for i in map(int, p_choices)]
  72. searches = [SEARCHES[i-1] for i in map(int, s_choices)]
  73. for pname, p in problems:
  74. for sname, s, h in searches:
  75. hstring = h if not h else " with {}".format(h)
  76. print("\nSolving {} using {}{}...".format(pname, sname, hstring))
  77. _p = p()
  78. _h = None if not h else getattr(_p, h)
  79. run_search(_p, s, _h)
  80. def show_solution(node, elapsed_time):
  81. if node is None:
  82. print("The selected planner did not find a solution for this problem. " +
  83. "Make sure you have completed the AirCargoProblem implementation " +
  84. "and pass all unit tests first.")
  85. else:
  86. print("Plan length: {} Time elapsed in seconds: {}".format(len(node.solution()), elapsed_time))
  87. for action in node.solution():
  88. print("{}{}".format(action.name, action.args))
  89. if __name__=="__main__":
  90. parser = argparse.ArgumentParser(description="Solve air cargo planning problems " +
  91. "using a variety of state space search methods including uninformed, greedy, " +
  92. "and informed heuristic search.")
  93. parser.add_argument('-m', '--manual', action="store_true",
  94. help="Interactively select the problems and searches to run.")
  95. parser.add_argument('-p', '--problems', nargs="+", choices=range(1, len(PROBLEMS)+1), type=int, metavar='',
  96. help="Specify the indices of the problems to solve as a list of space separated values. Choose from: {!s}".format(list(range(1, len(PROBLEMS)+1))))
  97. parser.add_argument('-s', '--searches', nargs="+", choices=range(1, len(SEARCHES)+1), type=int, metavar='',
  98. help="Specify the indices of the search algorithms to use as a list of space separated values. Choose from: {!s}".format(list(range(1, len(SEARCHES)+1))))
  99. args = parser.parse_args()
  100. if args.manual:
  101. manual()
  102. elif args.problems and args.searches:
  103. main(list(sorted(set(args.problems))), list(sorted(set((args.searches)))))
  104. else:
  105. print()
  106. parser.print_help()
  107. print(INVALID_ARG_MSG)
  108. print("Problems\n-----------------")
  109. for idx, (name, _) in enumerate(PROBLEMS):
  110. print(" {!s}. {}".format(idx+1, name))
  111. print()
  112. print("Search Algorithms\n-----------------")
  113. for idx, (name, _, heuristic) in enumerate(SEARCHES):
  114. print(" {!s}. {} {}".format(idx+1, name, heuristic))
  115. print()
  116. print("Use manual mode for interactive selection:\n\n\tpython run_search.py -m\n")