Esempio n. 1
0
 def goal_test(self, state):
     "goal_test(state) - Is state a goal?"
     testBoard = TileBoard(self.size, False, state)
     if (testBoard.solved()):
         return True
     else:
         return False
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)

        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.

        The parent's class constructor is then called with the TileBoard
        instance any any remaining arguments captured in **kwargs.
        """

        # Note on **kwargs:
        # **kwargs is Python construct that captures any remaining arguments
        # into a dictionary.  The dictionary can be accessed like any other
        # dictionary, e.g. kwargs["keyname"], or passed to another function
        # as if each entry was a keyword argument:
        #    e.g. foobar(arg1, arg2, …, argn, **kwargs).
        if force_state:
            temp_tileboard = TileBoard(n, force_state=force_state)
            super(NPuzzle, self).__init__(temp_tileboard,
                                          goals=None,
                                          g=kwargs["g"],
                                          h=kwargs["h"])
        else:
            temp_tileboard = TileBoard(n)
            super(NPuzzle, self).__init__(temp_tileboard,
                                          goals=None,
                                          g=kwargs["g"],
                                          h=kwargs["h"])
Esempio n. 3
0
    def h(cls, state: TileBoard):
        manhattan_sum = 0

        # Populates Solved State
        solved = [[None for c in range(state.cols)] for r in range(state.rows)]
        index = 1
        for row in range(state.boardsize):
            for col in range(state.boardsize):
                if row == state.rows // 2 and col == state.cols // 2:
                    solved[row][col] = None
                else:
                    solved[row][col] = index
                    index += 1

        # Calculate Displacements
        for row in range(state.boardsize):
            for col in range(state.boardsize):
                item = state.get(row, col)
                # Find location for solved state
                for solved_row in range(len(solved)):
                    if item in solved[solved_row]:
                        # Adds manhattan distance to manhattan_sum
                        # If item is at [1, 2] in state and [0, 0] in solved then distance is 1 + 2 = 3
                        manhattan_sum += abs(solved_row - row) + abs(solved[solved_row].index(item) - col)
        return manhattan_sum
Esempio n. 4
0
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)
        
        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.
        
        The parent's class constructor is then called with the TileBoard
        instance and any remaining arguments captured in **kwargs.
        """

        # Instantiate Tileboard
        self.puzzle = TileBoard(n, force_state=force_state)

        # Initialize parent class
        super().__init__(self.puzzle.state_tuple(), self.puzzle.goals,
                         kwargs["g"], kwargs["h"])
Esempio n. 5
0
 def h(cls, state: TileBoard):
     manhattan_distance = 0
     goal_state = list(state.goals[0])
     size = state.boardsize
     # calculate misplacement tiles
     # h = |x1 − x2| + |y1 − y2|
     # for index above board mod board_size will get cols
     # for index above board divide board_size will get rows
     for row in range(size):
         for col in range(size):
             # not count the blank for misplacement
             if state.get(row, col) is not None:
                 val_rc = state.get(row, col)
                 idx = goal_state.index(val_rc)
                 if idx > size - 1:
                     manhattan_distance += abs(idx // size - row) + abs(idx % size - col)
                 else:
                     manhattan_distance += row + abs(idx - col)
     return manhattan_distance
Esempio n. 6
0
class NPuzzle(Problem):
    """
    NPuzzle - Problem representation for an N-tile puzzle
    Provides implementations for Problem actions specific to N tile puzzles.
    """
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)
        
        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.
        
        The parent's class constructor is then called with the TileBoard
        instance any any remaining arguments captured in **kwargs.
        """

        # Note on **kwargs:
        # **kwargs is Python construct that captures any remaining arguments
        # into a dictionary.  The dictionary can be accessed like any other
        # dictionary, e.g. kwargs["keyname"], or passed to another function
        # as if each entry was a keyword argument:
        #    e.g. foobar(arg1, arg2, …, argn, **kwargs).

        self.size = n
        self.tileBoard = TileBoard(self.size, False, force_state)
        super().__init__(self.tileBoard,
                         **kwargs)  #call parent class with tileboard?

        return

    def getInitialBoardState(self):
        return self.tileBoard.state_tuple()

    def generateDebugBoard(self, state):
        return TileBoard(self.size, False, state)

    def actions(self, state):
        "actions(state) - find a set of actions applicable to specified state"
        actionBoard = TileBoard(self.size, False, state)
        actions = actionBoard.get_actions()
        return actions

    def result(self, state, action):
        "result(state, action)- apply action to state and return new state"
        actionBoard = TileBoard(self.size, False, state)
        newboard = actionBoard.move(action)
        return newboard.state_tuple()

    def goal_test(self, state):
        "goal_test(state) - Is state a goal?"
        testBoard = TileBoard(self.size, False, state)
        if (testBoard.solved()):
            return True
        else:
            return False
Esempio n. 7
0
def driver():
    start_overall_time = tic()
    sec_per_min = 60.0
    number_of_tileboard_instances = 2
    puzzle_size = 8
    methods = [BreadthFirst, DepthFirst, Manhattan]
    list_of_paths = list()
    list_of_number_of_nodes_explored = list()
    list_of_times = list()

    for n in range(number_of_tileboard_instances):
        board = TileBoard(puzzle_size)
        state_tuple = board.state_tuple(
        )  # do this becuase we din't want to modify the original board
        for method in methods:
            puzzle = NPuzzle(puzzle_size,
                             forced_state=state_tuple,
                             g=method.g,
                             h=method.h)
            (list_of_paths[n], list_of_number_of_nodes_explored[n],
             list_of_times[n]) = solve(puzzle)
Esempio n. 8
0
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)

        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.

        The parent's class constructor is then called with the TileBoard
        instance any any remaining arguments captured in **kwargs.
        """
        super().__init__(TileBoard(n, force_state=force_state),
                         g=kwargs['g'],
                         h=kwargs['h'])
Esempio n. 9
0
def driver():

    p_size = dict()
    n_size = dict()
    t = dict()

    for method in SEARCH_METHODS:
        t[method] = list()
        n_size[method] = list()
        p_size[method] = list()
        
       

    for i in range(TRIAL):

        board_layout = TileBoard(BOARD_SIZE).state_tuple()

        for method in SEARCH_METHODS:

            p = NPuzzle(BOARD_SIZE, g=method.g,h=method.h, force_state=board_layout)

            start_time = time.perf_counter()
                                      
            path, nodes_explored = graph_search(p)
                        
            dur = time.perf_counter() - start_time
            
            n_size[method].append(nodes_explored)
            
            t[method].append(dur)
            
            p_size[method].append(len(path))
            
            print('Trial %d via %s - plan %d node %d in %d seconds' %((i+1), method.__name__, len(path), nodes_explored, dur))



    for method in SEARCH_METHODS:
        
        print('Plan Method %s Mean %f Std %f' %(method.__name__, mean(p_size[method]), stdev(p_size[method])))
        print('Nodes Method %s Mean %f Std %f' %(method.__name__, mean(n_size[method]), stdev(n_size[method])))
        print('Time Method %s Mean %f Std %f' %(method.__name__, mean(t[method]), stdev(t[method])))
Esempio n. 10
0
    def h(cls, state: TileBoard):
        manhattan_solution = 0

        solved = [[None for c in range(state.cols)] for r in range(state.rows)]
        index = 1
        for row in range(state.boardsize):
            for col in range(state.boardsize):
                if row == state.rows // 2 and col == state.cols // 2:
                    solved[row][col] = None
                else:
                    solved[row][col] = index
                    index += 1

        # Calculate distance to solution
        for row in range(state.boardsize):
            for col in range(state.boardsize):
                item = state.get(row, col)
                for solved_row in range(len(solved)):
                    manhattan_solution += abs(solved_row - row) + \
                        abs(solved[solved_row].index(item) - col)

        return manhattan_solution
Esempio n. 11
0
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)
        
        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.
        
        The parent's class constructor is then called with the TileBoard
        instance any any remaining arguments captured in **kwargs.
        """
        # Note on **kwargs:
        # **kwargs is Python construct that captures any remaining arguments
        # into a dictionary.  The dictionary can be accessed like any other
        # dictionary, e.g. kwargs["keyname"], or passed to another function
        # as if each entry was a keyword argument:
        #    e.g. foobar(arg1, arg2, …, argn, **kwargs).

        # initialize parent
        # def __init__(self, initial, goals=None,
        #          g = lambda oldnode, action, newnode : oldnode.depth+1,
        #          h = lambda newnode : 0):
        nBoard = TileBoard(n, force_state=force_state)
        super().__init__(goals=nBoard.goals, g=kwargs['g'], g=kwargs['h'])
Esempio n. 12
0
def driver():
    manTime = [] 
    manLength = []
    manNodes = []
    depTime = []
    depLength = []
    depNodes = []
    breadTime = []
    breadLength = []
    breadNodes = []
    
    for i in range(0,31):
        tb = TileBoard(8)
        #starting with manhattan
        manprobs = NPuzzle(8,tb.state_tuple(),g=Manhattan.g,h=Manhattan.h)
        curTime = tic() #current time
        manList = graph_search(manprobs) #CONSIDER OTHER PARAMETERS LATER
        manTime.append(tock(curTime))
        manLength.append(len(manList[0]))
        manNodes.append(manList[1])
        
        #depth_first search
        depprobs = NPuzzle(8,tb.state_tuple(),g=DepthFirst.g,h=DepthFirst.h)
        curTime = tic() #current time
        depList = graph_search(depprobs) #CONSIDER OTHER PARAMETERS LATER
        depTime.append(tock(curTime))
        depLength.append(len(depList[0]))
        depNodes.append(depList[1])
        
        #breadth_first search
        breadprobs = NPuzzle(8,tb.state_tuple(),g=BreadthFirst.g,h=BreadthFirst.h)
        curTime = tic() #current time
        breadList = graph_search(breadprobs) #CONSIDER OTHER PARAMETERS LATER
        breadTime.append(tock(curTime))
        breadLength.append(len(breadList[0]))
        breadNodes.append(breadList[1])
    #calculate mean and stdevs for each list generated at beginning
    
    #manhattan statistics
    meanmantime = mean(manTime)
    stdmantime = stdev(manTime,meanmantime)
    meanmanlength = mean(manLength)
    stdmanlength = stdev(manLength,meanmanlength)
    meanmannodes = mean(manNodes)
    stdmannodes = stdev(manNodes,meanmannodes)

    #depth-first statistics
    meandeptime = mean(depTime)
    stddeptime = stdev(depTime)
    meandeplength = mean(depLength)
    stddeplength = stdev(depLength)
    meandepnodes = mean(depNodes)
    stddepnodes = stdev(depNodes)
    
    #breadth-first statistics
    meanbreadtime = mean(breadTime)
    stdbreadtime = stdev(breadTime)
    meanbreadlength = mean(breadLength)
    stdbreadlength = stdev(breadLength)
    meanbreadnodes = mean(breadNodes)
    stdbreadnodes = stdev(breadNodes)
    
    print("Manhattan Statistics - Mean Time: ", meanmantime, "StDev Time: ", stdmantime)
    print("Manhattan Statistics - Mean Length: ", meanmanlength, "StDev Length: ", stdmanlength)
    print("Manhattan Statistics - Mean Nodes: ", meanmannodes, "StDev Nodes: ", stdmannodes)

    print("Depth-First Statistics - Mean Time: ", meandeptime, "StDev Time: ", stddeptime)
    print("Depth-First Statistics - Mean Length: ", meandeplength, "StDev Length: ", stddeplength)
    print("Depth-First Statistics - Mean Nodes: ", meandepnodes, "StDev Nodes: ", stddepnodes)
    
    print("Breadth-First Statistics - Mean Time: ", meanbreadtime, "StDev Time: ", stdbreadtime)
    print("Breadth-First Statistics - Mean Length: ", meanbreadlength, "StDev Length: ", stdbreadlength)
    print("Breadth-First Statistics - Mean Nodes: ", meanbreadnodes, "StDev Nodes: ", stdbreadnodes)    
Esempio n. 13
0
 def generateDebugBoard(self, state):
     return TileBoard(self.size, False, state)
def driver():
    # Assign number of trials, size of tileboards, and set verbose / debug flags, and force_states
    ntrials = 31
    n = 8
    verbose, debug = False, True

    f_state = []

    # Create puzzle states for ntrials, dummy board to check if solvable
    for f in range(0, ntrials):
        dummy = TileBoard(n)
        done = False
        while not done:
            made = False
            # Create temporary state and check if solvable
            tmp_state = list(range(1, n + 1))
            tmp_state.append(None)
            random.shuffle(tmp_state)
            if dummy.solvable(tmp_state):
                made = done = True
            else:
                # Reshuffle temporary state if not solvable
                random.shuffle(tmp_state)
            if made:
                # If solvable, append to f_state list
                f_state.append(tmp_state)

    # Initialize empty arrays to hold stat values
    btime, dtime, atime = [], [], []
    bnodes, dnodes, anodes = [], [], []
    bsteps, dsteps, asteps = [], [], []
    """ Run ntrials: each loop runs a breadth search, 
        depth search, and A* search for each force_state"""
    for state in f_state:
        # Initialize timer before each search
        # Create puzzle with same initial state & costs specific to search type
        # Run graph search on created puzzle
        # Add stats to stat arrays

        bt = Timer()
        breadthpuzzle = NPuzzle(n,
                                force_state=state,
                                g=BreadthFirst.g,
                                h=BreadthFirst.h)
        bsearch = graph_search(breadthpuzzle, verbose, debug)
        bsteps.append(len(bsearch[0]))
        bnodes.append(bsearch[1])
        btime.append(bt.elapsed_s())

        dt = Timer()
        depthpuzzle = NPuzzle(n,
                              force_state=state,
                              g=DepthFirst.h,
                              h=DepthFirst.g)
        dsearch = graph_search(depthpuzzle, verbose, debug)
        dsteps.append(len(dsearch[0]))
        dnodes.append(dsearch[1])
        dtime.append(dt.elapsed_s())

        at = Timer()
        astarpuzzle = NPuzzle(n,
                              force_state=state,
                              g=Manhattan.g,
                              h=Manhattan.h)
        asearch = graph_search(astarpuzzle, verbose, debug)
        asteps.append(len(asearch[0]))
        anodes.append(asearch[1])
        atime.append(at.elapsed_s())

    # Merge each stat array into an array for each search
    bdata, ddata, adata = [], [], []
    """ Compile stats and create table """
    if ntrials > 1:
        # Find mean and standard deviation for each stat of each search
        bdata = [
            mean(bsteps),
            stdev(bsteps, mean(bsteps)),
            mean(bnodes),
            stdev(bnodes, mean(bnodes)),
            mean(btime),
            stdev(btime, mean(btime))
        ]

        ddata = [
            mean(dsteps),
            stdev(dsteps, mean(dsteps)),
            mean(dnodes),
            stdev(dnodes, mean(dnodes)),
            mean(dtime),
            stdev(dtime, mean(dtime))
        ]

        adata = [
            mean(asteps),
            stdev(asteps, mean(asteps)),
            mean(anodes),
            stdev(anodes, mean(anodes)),
            mean(atime),
            stdev(atime, mean(atime))
        ]

        # Combine all data into one list and round as necessary
        data = [bdata, ddata, adata]
        data = [[round(elem, 6) for elem in lis] for lis in data]

        # Create lists for table labels
        searches = ["Breadth Search", "Depth Search", "A* Search"]
        stats = [
            "Mean Steps", "Std Steps", "Mean Nodes", "Std Nodes", "Mean Time",
            "Std Time"
        ]

        # Create table using formatted strings and for loop
        i = 0
        row_format = ("{:>14}" * (len(stats) + 1))
        print(row_format.format("", *stats))
        for stat, row in zip(stats, data):
            print(row_format.format(searches[i], *row))
            i += 1
Esempio n. 15
0
 def goal_test(self, state):
     "goal_test(state) - Is state a goal?"
     #create a temporary board and determine if it's solved
     temporaryboard = TileBoard(self.puzzletype,force_state=state.state_tuple())
     return temporaryboard.solved()
Esempio n. 16
0
 def result(self, state, action):
     "result(state, action)- apply action to state and return new state"
     #return the state of the board after the action command,
     #using the board's move command.
     temporaryboard = TileBoard(self.puzzletype,force_state=state.state_tuple())
     return temporaryboard.move(action)
Esempio n. 17
0
 def actions(self, state):
     "actions(state) - find a set of actions applicable to specified state"
     #create a temporary board from current state, return its actions
     temporaryboard = TileBoard(self.puzzletype,force_state=state.state_tuple())
     return temporaryboard.get_actions()
Esempio n. 18
0
def driver():
    print("============================= TileBoard Game ==============================")
    print("CS 550 Artificial Intelligence | Prof. Roch | Assignment 2 | kingofthenorth")
    print("======================== Going through searches... ========================")

    plan_size = dict()
    nodes_size = dict()
    time = dict()

    for method in SEARCH_METHODS:
        plan_size[method] = list()
        nodes_size[method] = list()
        time[method] = list()

    for i in range(TRIAL_SIZE):
        if INFO:
            print('Trial #%d commence...' % (i + 1))

        # Standard layout for the board
        board_layout = TileBoard(BOARD_SIZE).state_tuple()

        # Trying the methods
        for method in SEARCH_METHODS:
            if INFO:
                print('Solving puzzle via %s' % method.__name__)

            puzzle = NPuzzle(BOARD_SIZE, g=method.g,
                             h=method.h, force_state=board_layout)

            start_time = tic()
            path, nodes_explored = graph_search(
                puzzle, debug=DEBUG, verbose=VERBOSE)
            duration = tock(start_time)
            assert path is not None

            plan_size[method].append(len(path))
            nodes_size[method].append(nodes_explored)
            time[method].append(duration)

            if INFO:
                print('Solved puzzle via %s in %d seconds' %
                      (method.__name__, duration))

        print('Finished Trial #%d' % (i + 1))

    if INFO or DEBUG or VERBOSE:
        print("\n\n======================== Going through searches... ========================\n\n\n")

    header = ["Search / Result   ",
              "Plan Size (Mean/STDEV)",
              "Node Size (Mean/STDEV)",
              "Time (Mean/STDEV)"]
    rows = list()

    # Formatting
    rows.append(['-' * (len(header[i]) + 1) for i in range(len(header))])

    for method in SEARCH_METHODS:
        rows.append([' '.join(re.sub('(?!^)([A-Z][a-z]+)', r' \1', method.__name__).split()),
                     '{:.3f} / {:.3f}'.format(
                         mean(plan_size[method]), stdev(plan_size[method])),
                     '{:.3f} / {:.3f}'.format(
                         mean(nodes_size[method]), stdev(nodes_size[method])),
                     '{:.3f} / {:.3f}'.format(mean(time[method]), stdev(time[method]))])

    print_table(rows, header=header, sep="\t| ")
Esempio n. 19
0
def driver() :
    bfsLengthList = []
    bfsNodesExpandedList = []
    bfsTimeList = []

    dfsLengthList = []
    dfsNodesExpandedList = []
    dfsTimeList = []

    manLengthList = []
    manNodesExpandedList = []
    manTimeList = []

    for i in range(2):      #change back to 31
        tempBoard = TileBoard(8)        #force_state=(1,2,3,4,5,6,7,8,None)

        #Breadth First Search
        bfs = NPuzzle(8,g=BreadthFirst.g,force_state=tempBoard.state_tuple())
        tempTimer = Timer()
        path,numNodes = graph_search(bfs, verbose=True)
        bfsTimeList.append(tempTimer.elapsed_s())
        bfsNodesExpandedList.append(numNodes)
        bfsLengthList.append(len(path))

        #Depth First Search
        dfs = NPuzzle(8,g=DepthFirst.g,force_state=tempBoard.state_tuple())
        tempTimer = Timer()
        path,numNodes = graph_search(dfs, verbose=True)
        dfsTimeList.append(tempTimer.elapsed_s())
        dfsNodesExpandedList.append(numNodes)
        dfsLengthList.append(len(path))

        #Manhattan Search
        manhattan = NPuzzle(8, h=Manhattan.h, force_state=tempBoard.state_tuple())
        tempTimer = Timer()
        path, numNodes = graph_search(manhattan, verbose=True)
        manTimeList.append(tempTimer.elapsed_s())
        manNodesExpandedList.append(numNodes)
        manLengthList.append(len(path))

    print("BFS Average Path Length:",mean(bfsLengthList))
    print("BFS Average Nodes Expanded:",mean(bfsNodesExpandedList))
    print("BFS Average Time Elapsed:",mean(bfsTimeList))

    print("DFS Average Path Length:", mean(dfsLengthList))
    print("DFS Average Nodes Expanded:",mean(dfsNodesExpandedList))
    print("DFS Average Time Elapsed:",mean(dfsTimeList))

    print("Manhattan Average Path Length:", mean(manLengthList))
    print("Manhattan Average Nodes Expanded:", mean(manNodesExpandedList))
    print("Manhattan Average Time Elapsed:", mean(manTimeList))

    print("BFS Standard Deviation Path Length:", stdev(bfsLengthList))
    print("BFS Standard Deviation Nodes Expanded:", stdev(bfsNodesExpandedList))
    print("BFS Standard Deviation Time Elapsed:", stdev(bfsTimeList))
  
    print("DFS Standard Deviation Path Length:", stdev(dfsLengthList))
    print("DFS Standard Deviation Nodes Expanded:", stdev(dfsNodesExpandedList))
    print("DFS Standard Deviation Time Elapsed:", stdev(dfsTimeList))

    print("Manhattan Standard Deviation Path Length:", stdev(manLengthList))
    print("Manhattan Standard Deviation Nodes Expanded:", stdev(manNodesExpandedList))
    print("Manhattan Standard Deviation Time Elapsed:", stdev(manTimeList))
Esempio n. 20
0
 def actions(self, state):
     "actions(state) - find a set of actions applicable to specified state"
     actionBoard = TileBoard(self.size, False, state)
     actions = actionBoard.get_actions()
     return actions
Esempio n. 21
0
def driver():
    length_of_plan = dict()
    number_of_nodes = dict()
    elapsed_time = dict()

    for method in SOLUTION_METHODS:
        length_of_plan[method] = list()
        number_of_nodes[method] = list()
        elapsed_time[method] = list()

    for i in range(TRIAL_SIZE):
        if INFO:
            print('Starting Trial #%d' % (i + 1))

        # Standard Config
        board_layout = TileBoard(TRIAL_BOARD_SIZE).state_tuple()

        # Random Board - For testing
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[8, None, 6, 5, 4, 7, 2, 3, 1]).state_tuple()
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[7, 3, None, 5, 1, 2, 4, 8, 6]).state_tuple()

        # Solvable in 1 move
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[1, None, 3, 4, 2, 5, 6, 7, 8]).state_tuple()

        # Solvable in ~5 moves
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[4, 1, 2, None, 5, 3, 6, 7, 8]).state_tuple()
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[1, None, 3, 7, 2, 5, 4, 6, 8]).state_tuple()

        # Solvable in ~15 moves
        # board_layout = TileBoard(TRIAL_BOARD_SIZE, force_state=[5, 3, 7, None, 1, 2, 4, 6, 8]).state_tuple()

        for method in SOLUTION_METHODS:
            if INFO:
                print('Solving puzzle via %s' % method.__name__)

            puzzle = NPuzzle(TRIAL_BOARD_SIZE,
                             g=method.g,
                             h=method.h,
                             force_state=board_layout)

            start_time = tic()
            path, nodes_explored = graph_search(puzzle,
                                                debug=DEBUG,
                                                verbose=VERBOSE)
            duration = tock(start_time)
            assert path is not None

            length_of_plan[method].append(len(path))
            number_of_nodes[method].append(nodes_explored)
            elapsed_time[method].append(duration)

            if INFO:
                print('Solved puzzle via %s in %d seconds' %
                      (method.__name__, duration))

        print('Finished Trial #%d' % (i + 1))

    if INFO or DEBUG or VERBOSE:
        print("\n\n==================================================\n\n\n")

    header = [
        "Method / Result   ", "Length of Plan (Mean/STDEV)",
        "Number of Nodes (Mean/STDEV)", "Elapsed Time (Mean/STDEV)"
    ]
    rows = list()

    # Header Separator
    rows.append(['-' * (len(header[i]) + 1) for i in range(len(header))])

    # Table Values
    for method in SOLUTION_METHODS:
        rows.append([
            ' '.join(
                re.sub('(?!^)([A-Z][a-z]+)', r' \1', method.__name__).split()),
            '{:.3f} / {:.3f}'.format(mean(length_of_plan[method]),
                                     stdev(length_of_plan[method])),
            '{:.3f} / {:.3f}'.format(mean(number_of_nodes[method]),
                                     stdev(number_of_nodes[method])),
            '{:.3f} / {:.3f}'.format(mean(elapsed_time[method]),
                                     stdev(elapsed_time[method]))
        ])

    print_table(rows, header=header, sep="\t| ")
Esempio n. 22
0
def driver():
    print(
        "-------------------------- TileBoard searching...-----------------------------------"
    )
    # declarations
    path_length = dict()
    num_nodes = dict()
    elapsed_sec = dict()
    elapsed_min = dict()

    for method in search_method:
        path_length[method] = list()
        num_nodes[method] = list()
        elapsed_sec[method] = list()
        elapsed_min[method] = list()

    for i in range(num_puzzle):
        print('\n###Puzzle %d###' % (i + 1))

        for method in search_method:
            if method.__name__ is 'Manhattan':
                name = 'A*'
            else:
                name = method.__name__
            print('Solving puzzle using %s' % name)

            # set the puzzle
            npuzzle = NPuzzle(board_size,
                              g=method.g,
                              h=method.h,
                              force_state=TileBoard(board_size).state_tuple())
            t = Timer()
            # (1,2,3,None,4,6,7,5,8) solve in 3 moves
            """--------------------One Path Demo using A---------------------------*  
            temp = False
            if method.__name__ is 'Manhattan':
                temp = True
            path, nodes_explored = graph_search(npuzzle, debug=False, verbose=temp)
            ----------------------------------------------------------------------"""
            path, nodes_explored = graph_search(npuzzle,
                                                debug=False,
                                                verbose=False)

            if method.__name__ is 'Manhattan':
                name = "A*"
            else:
                name = method.__name__
            print('Puzzle Solved in %d sec or  %d min' %
                  (t.elapsed_s(), t.elapsed_min()))

            assert path is not None
            path_length[method].append(len(path))
            num_nodes[method].append(nodes_explored)
            elapsed_sec[method].append(t.elapsed_s())
            elapsed_min[method].append(t.elapsed_min())

    # use pandas tabulate and print table pretty
    data = list()

    # round 2digit and formatting
    for method in search_method:
        if method.__name__ is 'Manhattan':
            name = 'A*'
        else:
            name = method.__name__
        # create list according to column names
        data.append([
            ' '.join(re.sub('(?!^)([A-Z][a-z]+)', r' \1', name).split()),
            '{:.2f} / {:.2f}'.format(mean(path_length[method]),
                                     stdev(path_length[method])),
            '{:.2f} / {:.2f}'.format(mean(num_nodes[method]),
                                     stdev(num_nodes[method])),
            '{:.2f} / {:.2f}'.format(mean(elapsed_sec[method]),
                                     stdev(elapsed_sec[method])),
            '{:.2f} / {:.2f}'.format(mean(elapsed_min[method]),
                                     stdev(elapsed_min[method]))
        ])

    df_data = pd.DataFrame(data)
    df_data.columns = [
        'Search Type', 'Path_Length (Mean/Stdev)',
        'Node_Explored (Mean/Stdev)', 'Time in Sec(Mean/Stdev)',
        'Time in Min(Mean/Stdev)'
    ]

    pd_tabulate = lambda df_data: tabulate(
        df_data, headers='keys', tablefmt='psql')
    print(pd_tabulate(df_data))
Esempio n. 23
0
 def result(self, state, action):
     "result(state, action)- apply action to state and return new state"
     actionBoard = TileBoard(self.size, False, state)
     newboard = actionBoard.move(action)
     return newboard.state_tuple()
Esempio n. 24
0
class NPuzzle(Problem):
    """
    NPuzzle - Problem representation for an N-tile puzzle
    Provides implementations for Problem actions specific to N tile puzzles.
    """
    def __init__(self, n, force_state=None, **kwargs):
        """"__init__(n, force_state, **kwargs)
        
        NPuzzle constructor.  Creates an initial TileBoard of size n.
        If force_state is not None, the puzzle is initialized to the
        specified state instead of being generated randomly.
        
        The parent's class constructor is then called with the TileBoard
        instance and any remaining arguments captured in **kwargs.
        """

        # Instantiate Tileboard
        self.puzzle = TileBoard(n, force_state=force_state)

        # Initialize parent class
        super().__init__(self.puzzle.state_tuple(), self.puzzle.goals,
                         kwargs["g"], kwargs["h"])

        # Note on **kwargs:
        # **kwargs is Python construct that captures any remaining arguments
        # into a dictionary.  The dictionary can be accessed like any other
        # dictionary, e.g. kwargs["keyname"], or passed to another function
        # as if each entry was a keyword argument:
        #    e.g. foobar(arg1, arg2, …, argn, **kwargs).

    def actions(self, state):
        """actions(state) - find a set of actions applicable to specified state"""
        # Convert state tuple to 2D list
        boarddims = [self.puzzle.get_rows(), self.puzzle.get_cols()]
        state_list = [
            state[i:i + boarddims[0]]
            for i in range(0, len(state), boarddims[0])
        ]

        # Find empty tile coordinates
        found = False
        for y in range(len(state_list)):
            for x in range(len(state_list[y])):
                if state_list[y][x] is None:
                    empty = [y, x]
                    found = True
                    break
            if found:
                break

        actions = []  # Initialize empty list for actions

        for dim in [0, 1]:  # rows, then columns
            # Append offsets to the actions list,
            # e.g. move left --> (0, -1)
            #      move down --> (1, 0)
            # Note that when we append to the list of actions,
            # we use list( ) to make a copy of the list, otherwise
            # we just get a pointer to it and modification of offset
            # will change copies in the list.
            offset = [0, 0]
            # Add if we don't go off the top or left
            if empty[dim] - 1 >= 0:
                offset[dim] = -1
                actions.append(list(offset))
            # Append if we don't go off the bottom or right
            if empty[dim] + 1 < boarddims[dim]:
                offset[dim] = 1
                actions.append(list(offset))

        return actions

    def result(self, state, action):
        """result(state, action)- apply action to state and return new state"""
        # Convert tuple into 2D list
        n = self.puzzle.get_rows()
        state_list = [list(state[i:i + n]) for i in range(0, len(state), n)]

        # Find empty tile coordinates
        r = c = 0
        found = False
        for y in range(len(state_list)):
            for x in range(len(state_list[y])):
                if state_list[y][x] is None:
                    r, c = y, x
                    found = True
                    break
            if found:
                break

        [delta_r, delta_c] = action

        # Validate actions
        rprime = r + delta_r
        cprime = c + delta_c
        if rprime < 0 or cprime < 0 or \
                rprime >= n or cprime >= n:
            raise ValueError("Illegal move (%d,%d) from (%d,%d)" %
                             (delta_r, delta_c, r, c))

        # Apply move offset accordingly
        if delta_r != 0:
            # Move up or down
            state_list[r][c] = state_list[rprime][c]
            state_list[rprime][c] = None
        elif delta_c != 0:
            # Move left or right
            state_list[r][c] = state_list[r][cprime]
            state_list[r][cprime] = None

        # Create new state after moving empty
        new_state = [item for sublist in state_list for item in sublist]
        # Convert to tuple (hashable) and return
        return tuple(new_state)

    def goal_test(self, state):
        """goal_test(state) - Is state a goal?"""
        # If state is in puzzle goals, return True
        goal = state in self.puzzle.goals
        return goal

    def value(self, state):
        pass