示例#1
0
    def do_start_search (self, method): 
        """Start the search algorithm based on the given method.

        Supported methods:
            'distance'  Straight-line distance
            'linkcount' Shortest-hop-count 
        """

        # Check for a zero-length trip.
        if self.startcity.get() == self.endcity.get():
            tkmsg.showwarning("Invalid Search State", "The start and end cities cannot be the same.")
            return

        # Create a search object...
        self.search_object = AStarSearch()

        # ... and fill its attributes.
        self.search_object.origin = [x for x in self.cities if x.name == self.startcity.get()][0]
        self.search_object.destination = [x for x in self.cities if x.name == self.endcity.get()][0]
        self.search_object.potholes = [x for x in self.cities if x.state == "blocking"] # no index


        # Here is where we choose a heuristic and distance function.
        if method == "distance":
            self.search_object.heuristic = lambda x: x.distance_to(self.search_object.destination)
            self.search_object.distance_func = lambda x, y: x.distance_to(y)
        elif method == "linkcount":
            self.search_object.heuristic = lambda x: 1
            # Distance function: One per hop (skipping the first "road" which isn't really there).
            self.search_object.distance_func = lambda x, y: (x is not None and y is not None) and 1 or 0

        # Redraw all the roads as un-probed.
        for city in self.cities:
            for road in city.neighbors:
                road.reset()

        # Enable the buttons for searching.
        self.enable_search_GUI()

        # Get the search object working.
        self.search_object.start_search()

        # Print the search method in the log
        self.log_message("Starting search using '%s' method." % method)
示例#2
0
from Graph import Graph
from AStarSearch import AStarSearch
from util import *

# Width and height of graph grid, must be redefined for various graphs
WIDTH = 10
HEIGHT = 8

if __name__ == "__main__":
    # Command line parser
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "input_file", help="The name of the file to treat as the search space")
    parser.add_argument("heuristic",
                        help="Name of search heuristic to use in A* search",
                        choices=("manhattan", "diagonal"),
                        default="manhattan")
    args = parser.parse_args()

    # open file
    f = open(args.input_file, 'r')
    g = Graph(WIDTH, HEIGHT)

    # Create our graph structure to traverse
    create_graph_from_file(f, g)

    # Create and perform A* search
    search = AStarSearch(g.get(0, 0), g.get(WIDTH - 1, HEIGHT - 1), g,
                         args.heuristic)
    search.search()
示例#3
0
    x = ReadFile("test.txt", "map-out.txt")
    t = x.read_file()

    food_fen = FoodGenerator()

    for m in range(0,11):
        init_state = GameMap(t, None, [0, 2], [[0, 2], [0, 1], [0, 0]], True)
        init_state_diagonal = GameMap(t, None, [0, 2], [[0, 2], [0, 1], [0, 0]], False)
        init_state.set_food_position(food_fen.generate_food(init_state.game_map))
        init_state_diagonal.set_food_position(food_fen.generate_food(init_state.game_map))

        movement_list_manhattan = []
        movement_list_diagonal = []
        for i in range(0, 30):
            # print "Score=", i
            mySearch = AStarSearch(init_state)
            diagonalSearch = AStarSearch(init_state_diagonal)
            diagonalSearch.start_search(False)
            mySearch.start_search(True)
            answer = mySearch.get_answer()
            answer_diagonal = diagonalSearch.get_answer()
            movement_list_manhattan.append(len(answer) - 1)
            movement_list_diagonal.append(len(answer_diagonal) - 1)
            pygame.init()
            map_length = 300
            screen = draw_table(len(t), map_length)
            draw_obstacles(len(t), screen, answer[0].get_obstacle_pos(), map_length)
            draw_snake(len(t), screen, answer[0].snake_position, map_length)
            draw_food(len(t), screen, answer[0].food_position, map_length)

            index = 0
示例#4
0
class GUI(object):


    
    def __init__ (self, root):
        """Initialize all GUI widgets."""
        self.root = root
        self.root.title("A* Algorithm")

        self._initialize_menus()
        self._initialize_window()

    


    def _initialize_menus (self):
        """Initialize menu bar items."""


        # Yes, this code is fugly.

        self.menubar = tk.Menu(self.root)

        self.filemenu = tk.Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(label="Open locations file...",
                             command=self.do_open_locations)
        self.filemenu.add_command(label="Open connections file...",
                             command=self.do_open_connections,
                             state=tk.DISABLED)
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Quit",
                             command=self.do_quit)

        self.menubar.add_cascade(label="File", menu=self.filemenu)

        self.searchmenu = tk.Menu(self.menubar, tearoff=0)
        self.searchmenu.add_command(label="Start search by distance",
                command=lambda: self.do_start_search("distance"),
                state=tk.DISABLED)
        self.searchmenu.add_command(label="Start search by link count",
                command=lambda: self.do_start_search("linkcount"),
                state=tk.DISABLED)
        self.searchmenu.add_command(label="Stop search",
                command=self.do_stop_search,
                state=tk.DISABLED)

        self.menubar.add_cascade(label="Search", menu=self.searchmenu)

        self.root.config(menu=self.menubar)




    def _initialize_window (self):
        """Initialize window widgets."""

        # Set minimum size, prevent vertical stretching.
        self.root.minsize(width=1200, height=800)
        self.root.resizable(width=True, height=False)

        # On the left, create a canvas.
        canvasframe = tk.Frame(self.root)
        canvasframe.pack(side=tk.LEFT)
        self.canvas = tk.Canvas(canvasframe,
                                width=910, height=800,
                                relief=tk.SUNKEN,
                                borderwidth=1)
        self.canvas.pack(side=tk.LEFT,
                         fill=tk.NONE,
                         expand=False)

        # On the right, we have the side panel.
        sideframe = tk.Frame(self.root)
        sideframe.pack(side=tk.RIGHT,
                       fill=tk.BOTH,
                       expand=1)

        # The top of the side frame gets buttons.
        buttonframe = tk.Frame(sideframe)
        buttonframe.pack(side=tk.TOP, fill=tk.X)
        buttonframe.grid_columnconfigure(2, weight=1)

        # Start city option menu
        startlabel = tk.Label(buttonframe, text="Start city")
        startlabel.grid(row=0, column=0)
        self.startcity = tk.StringVar(buttonframe)
        self.startcity.set("")
        self.startoptionmenu = tk.OptionMenu(buttonframe, self.startcity, "")
        self.startoptionmenu.grid(row=0, column=1)

        # End city option menu
        endlabel = tk.Label(buttonframe, text="End city")
        endlabel.grid(row=1, column=0)
        self.endcity = tk.StringVar(buttonframe)
        self.endcity.set("")
        self.endoptionmenu = tk.OptionMenu(buttonframe, self.endcity, "")
        self.endoptionmenu.grid(row=1, column=1)

        # Images to put in the buttons.
        playimage = tk.PhotoImage(file="images/play_button.gif")
        nextimage = tk.PhotoImage(file="images/next_button.gif")

        # "Play" button.
        self.playbutton = tk.Button(buttonframe,
                               image=playimage,
                               command=self.do_play,
                               state=tk.DISABLED)
        self.playbutton.image = playimage
        self.playbutton.grid(row=0, rowspan=2, column=3)
        
        # "Next Step" button.
        self.nextbutton = tk.Button(buttonframe,
                               image=nextimage,
                               command=self.do_next,
                               state=tk.DISABLED)
        self.nextbutton.image = nextimage
        self.nextbutton.grid(row=0, rowspan=2, column=4)

        # A place to log actions.
        logframe = tk.Frame(sideframe)
        logframe.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
        logscroll = tk.Scrollbar(logframe, orient=tk.VERTICAL)
        self.log = tk.Listbox(logframe, yscrollcommand=logscroll.set)
        logscroll.config(command=self.log.yview)
        logscroll.pack(side=tk.RIGHT, fill=tk.Y, expand=0)
        self.log.pack(side=tk.LEFT,
                      fill=tk.BOTH,
                      expand=1)




    def enable_search_GUI (self):
        """Enable the widgets having to do with search."""

        # Enable search buttons
        self.nextbutton.config(state=tk.NORMAL)
        self.playbutton.config(state=tk.NORMAL)
        for city in self.cities:
            city.lock_state()
        
        # Enable/disable search menu items
        self.searchmenu.entryconfig(0, state=tk.DISABLED)
        self.searchmenu.entryconfig(1, state=tk.DISABLED)
        self.searchmenu.entryconfig(2, state=tk.NORMAL)

    def disable_search_GUI (self):
        """Disable the widgets having to do with search."""

        # Disable search buttons
        self.nextbutton.config(state=tk.DISABLED)
        self.playbutton.config(state=tk.DISABLED)
        for city in self.cities:
            city.unlock_state()

        # Enable/disable search menu items
        self.searchmenu.entryconfig(0, state=tk.NORMAL)
        self.searchmenu.entryconfig(1, state=tk.NORMAL)
        self.searchmenu.entryconfig(2, state=tk.DISABLED)





    # Callbacks

    def do_next(self):
        """Search the next adjacent cities for the next best path."""
        
        # If somehow we got here without a valid search object,
        # disable the button and stop.
        if self.search_object is None:
            self.disable_search_GUI()
            return

        # Run one iteration of the algorithm, and get information back.
        try:        
            current_road, total_distance, distance, estimate = self.search_object.next_step()
        
        # The code throws a RuntimeError if no route exists.
        except RuntimeError as ex:
            self.disable_search_GUI()
            tkmsg.showerror(
                    "Invalid Search State", 
                    "No valid route exists between the selected cities.")
            return

        # If the current road is None, we've reached the end.
        if current_road is None:
            # Hooray, we found it.
            
            # Now that the search is over, disable the search buttons.
            self.disable_search_GUI()

            # Highlight the roads we've traveled.
            for road in self.search_object.generate_path_from(self.current_city):
                road.highlight()

            self.log_message("Search stopped. Shortest route found.")
            return 0
        else:
            # Keep this information for the next iteration if needed.
            self.current_city = current_road.destination

        # Otherwise, show all neighboring roads as probed.
        for road in current_road.destination.neighbors:
            road.probe()
        # Mark the current road as being traveled.
        current_road.travel()

        # Dump some information to the log.
        if current_road.origin is None:
            self.log_message("Beginning search at " + current_road.destination.name)
        else:
            self.log_message("Going from " + current_road.origin.name + " to " + current_road.destination.name)
            self.log_message("Total distance traveled: %.2f" % total_distance)
            self.log_message("Estimated distance from " + current_road.destination.name + ": %.2f" % estimate)
        return 1





    def do_open_locations(self):
        """Open the locations file and extract city locations."""

        # Get the filename.
        newfilename = tkfile.askopenfilename()
        # If they press "cancel", skip the rest.
        if not newfilename:
            return

        # Set the filenames; setting location should clear connections.
        self.location_file_name = newfilename
        self.connection_file_name = None

        # Try to open the file.
        try:
            locationsfile = open(self.location_file_name)
        # Complain if the file can't be opened.
        except IOError:
            print(repr(self.location_file_name))
            tkmsg.showerror("Error", "Error loading locations file.")
            return

        # Read the cities from the file.
        self.cities = parse_locations_file(locationsfile)

        # Clear the old cities from the canvas.
        self.canvas.delete(tk.ALL)

        # Draw all of the cities.
        for city in self.cities:
            city.draw(self.canvas)
        
        # Show some log information.
        self.log_message("Loaded " + str(len(self.cities)) + " cities.")

        # Set states of menu items.
        self.filemenu.entryconfig(1, state=tk.NORMAL)
        self.searchmenu.entryconfig(0, state=tk.DISABLED)
        self.searchmenu.entryconfig(1, state=tk.DISABLED)

        # Add cities to the start and end city option menus
        citynames = sorted([x.name for x in self.cities])

        # Remove 'dummy' menu items
        self.startoptionmenu['menu'].delete(0, 'end')
        self.endoptionmenu['menu'].delete(0, 'end')

        # Add each city as a menu item
        for city in citynames:
            self.startoptionmenu['menu'].add_command(label=city, \
                    command=lambda item=city: self.do_set_start_city(item))

            self.endoptionmenu['menu'].add_command(label=city, \
                    command=lambda item=city: self.do_set_end_city(item))

        # Set default start and end cities
        self.startcity.set(citynames[0])
        self.endcity.set(citynames[-1])
        self.do_set_endpoint_cities()

        # Enable exclude button
        #self.excludebutton.config(state=tk.NORMAL)
        #self.clearexcludebutton.config(state=tk.NORMAL)


    def do_set_start_city (self, city):
        self.startcity.set(city)
        self.do_set_endpoint_cities()

    def do_set_end_city (self, city):
        self.endcity.set(city)
        self.do_set_endpoint_cities()

    def do_set_endpoint_cities(self):
        """Update origin and destination cities on the canvas."""

        prevcities = [x for x in self.cities if x.state in ['starting', 'ending']]
        for city in prevcities:
            city.set_normal()
            city.draw(self.canvas)
       
        startcity = [x for x in self.cities if x.name == self.startcity.get()][0]
        startcity.set_starting()
        startcity.draw(self.canvas)

        endcity = [x for x in self.cities if x.name == self.endcity.get()][0]
        endcity.set_ending()
        endcity.draw(self.canvas)





    def do_open_connections(self):
        """Open the connections file and extract roads connecting cities."""

        # Get the filename.
        newfilename = tkfile.askopenfilename()
        # If they cancel, cancel.
        if not newfilename:
            return
        self.connection_file_name = newfilename

        # Try to open the file.
        try:
            connectionsfile = open(self.connection_file_name)
        # And complain if we can't.
        except IOError:
            tkmsg.showerror("Error", "Error loading connections file.")
            return

        # Get rid of any previous connections.
        for city in self.cities:
            city.neighbors = []

        # Load new connections from the file.
        self.cities = parse_connections_file(connectionsfile, self.cities)

        # Count the number of connections we just loaded and log it.
        roadcount = 0
        for city in self.cities:
            roadcount += len(city.neighbors)
        self.log_message("Loaded " + str(roadcount) + " roads.")

        # Draw the new connections onto the canvas.
        for city in self.cities:
            for road in city.neighbors:
                road.draw(self.canvas)

        # Let the user start a search.
        self.searchmenu.entryconfig(0, state=tk.NORMAL)
        self.searchmenu.entryconfig(1, state=tk.NORMAL)





    def do_start_search (self, method): 
        """Start the search algorithm based on the given method.

        Supported methods:
            'distance'  Straight-line distance
            'linkcount' Shortest-hop-count 
        """

        # Check for a zero-length trip.
        if self.startcity.get() == self.endcity.get():
            tkmsg.showwarning("Invalid Search State", "The start and end cities cannot be the same.")
            return

        # Create a search object...
        self.search_object = AStarSearch()

        # ... and fill its attributes.
        self.search_object.origin = [x for x in self.cities if x.name == self.startcity.get()][0]
        self.search_object.destination = [x for x in self.cities if x.name == self.endcity.get()][0]
        self.search_object.potholes = [x for x in self.cities if x.state == "blocking"] # no index


        # Here is where we choose a heuristic and distance function.
        if method == "distance":
            self.search_object.heuristic = lambda x: x.distance_to(self.search_object.destination)
            self.search_object.distance_func = lambda x, y: x.distance_to(y)
        elif method == "linkcount":
            self.search_object.heuristic = lambda x: 1
            # Distance function: One per hop (skipping the first "road" which isn't really there).
            self.search_object.distance_func = lambda x, y: (x is not None and y is not None) and 1 or 0

        # Redraw all the roads as un-probed.
        for city in self.cities:
            for road in city.neighbors:
                road.reset()

        # Enable the buttons for searching.
        self.enable_search_GUI()

        # Get the search object working.
        self.search_object.start_search()

        # Print the search method in the log
        self.log_message("Starting search using '%s' method." % method)




    def do_stop_search (self):
        """Stop the search algorithm, returning control to the user."""

        self.search_object = None

        self.disable_search_GUI()

        self.log_message("Search stopped by user.")


    def do_play(self):
        """Run the entire search algorithm."""

        while self.do_next():
            continue



    def do_quit(self):
        """Exit program."""

        self.root.quit()




    def log_message (self, message):
        """Prints out a message to the log window."""

        self.log.insert(tk.END, message)
        self.log.see(tk.END)
示例#5
0
locations = parse_connections_file(connectionsfile, parse_locations_file(locationsfile))

try:
    startcity = [x for x in locations if x.name == sys.argv[3]][0]
except IndexError:
    print("Could not find origin city:", sys.argv[3])
    exit(1)

try:
    destcity = [x for x in locations if x.name == sys.argv[4]][0]
except IndexError:
    print("Could not find destination city:", sys.argv[4])
    exit(1)

avoidcities = [x for x in locations if x.name in sys.argv[5:]]


# Create the search object
search = AStarSearch(startcity, destcity, lambda x: x.distance_to(destcity), potholes=avoidcities)

# Run the search algorithm
search.start_search()

# Get the shortest path traversed
path = search.run_to_end()

# Output path to standard output
print("->".join([x.name for x in path]))

# vim: set et sw=4 ts=4: