Пример #1
0
def init_dfs_stack(g, eqs):
    # heap key: eq, value: nzeros
    heap = None
    connected = is_connected(g)
    if connected:
        heap = PriorityQueue()
        heap.populate((eq, len(g[eq])) for eq in sorted(eqs))
    root_node = Node(0, [], g, heap, connected)
    return [root_node]
Пример #2
0
def init_dfs_stack(g, eqs, indent):
    # heap key: eq, value: nzeros
    heap = None
    connected = is_connected(g)
    if connected:
        heap = PriorityQueue()
        heap.populate((eq, len(g[eq])) for eq in sorted(eqs))
    remaining_eqs = set(eqs)
    asm_key = to_asm_key(remaining_eqs)
    root_node = Node(0, [ ], g, heap, connected, remaining_eqs, None, asm_key,
                     None, None, get_id())
    register('init', indent)
    return [root_node]
Пример #3
0
def dijkstra(graph: Graph, source: object) -> tuple:
    """
    calcule les plus courts chemins entre les sommets d'un graphe à partir d'une origine source
    :param graph: le graphe
    :param source: le sommet d'origine
    :return: une tuple avec les distance stockés dans la variable dist
                et le tableau de routage
    """
    dist: dict = {source: 0}  # initialization
    routage: dict = {}  # routing table
    Q: PriorityQueue = PriorityQueue()  # create vertex priority queue Q
    for v in graph.get_vertices():
        if v != source:
            dist[v] = math.inf  # unknown distance from source to v
        routage[v] = None  # predecessor of v
        Q.add(v, priority=dist[v])

    while not Q.is_empty():  # the main loop
        vertex: tuple = Q.pop()  # remove and return best vertex
        u: object = vertex[1]
        for v in graph.neighbors(u):  # only v that are still in Q
            alt = dist[u] + graph.get_weight(u, v)
            if alt < dist[v]:
                dist[v] = alt
                routage[v] = u
                Q.add(v, priority=alt)
    return dist, routage
Пример #4
0
    def __init__(self, cfg, width, height):
        self.cfg = cfg
        # Set up the state of the game board using the LevelState
        # object. This is the main class that holds things like the
        # amount of fuel that the player has left.
        initialFuel = 30  # A default value of fuel to use if one is
        # not specified in config.json

        try:
            initialFuel = self.cfg["initialfuel"]
        except:
            pass
        self.state = LevelState(initialFuel)
        # The actual board, represented as an width-by-height matrix
        # (array of arrays)
        self.board = [[0 for x in range(height)] for y in range(width)]
        # A "dirty" matrix. This is used for efficiency: don't redraw
        # tiles that don't need to be redrawn.
        self.dirty = [[True for x in range(height)] for y in range(width)]
        # Set the width/height
        self.width = width
        self.height = height

        # Build the board as a matrix of priority queues
        for x in range(width):
            for y in range(height):
                self.board[x][y] = PriorityQueue()

        # The set of things that want to listen to clock ticks.
        self.clockTickListeners = []
        self.ferrets = []
        self.healthpacks = []
        self.stones = []
Пример #5
0
def TCPSimulator():
    """
    This function implements the test program for the assignment.
    It begins by creating the client and server objects and then
    executes an event loop driven by a priority queue for which
    the priority value is time.
    """
    eventQueue = PriorityQueue()
    client = TCPClient()
    server = TCPServer()
    client.server = server
    server.client = client
    client.queueRequestMessage(eventQueue, 0)
    while not eventQueue.isEmpty():
        e, t = eventQueue.dequeueWithPriority()
        if EVENT_TRACE:
            print(str(e) + " at time " + str(t))
        e.dispatch(eventQueue, t)
Пример #6
0
def applyDijkstra(g, start, finish):
    """
    Applies Dijkstra's algorithm to the graph g, updating the
    distance from start to each node in g.
    """
    #MAKE SURE THAT THE ALGORITHM IS APPLIED ONLY TO THE START/FINISH NODE
    #USE node.predecessor, node.distance

    #initializeSingleSource(g, start)

    finalized = set()
    frontier = PriorityQueue()
    finishedendnode = False
    #explored = set()
    start.distance = 0
    start.predecessor = None

    frontier.enqueue(start)

    while not frontier.isEmpty() and finishedendnode == False:
        node = frontier.dequeue()
        #print(type(node))
        finalized.add(node)
        if node == finish:
            finishedendnode = True
            break
        for arc in node.getArcsFrom():
            n1 = arc.getStart()
            n2 = arc.getFinish()
            #print("n1: "+ str(n1))
            #print("n2: "+ str(n2))
            #print("node: "+ str(node))
            if n2 not in finalized:
                #print("n2: "+ str(n2))
                if n2 not in frontier:
                    initIndivNode(n1, n2, arc)
                    frontier.enqueue(n2, n2.distance)
                #init single source
                else:
                    oldDistance = n2.distance
                    relax(n1, n2, arc.getCost())
                    if n2.distance < oldDistance:
                        frontier.raisePriority(n2, n2.distance)
Пример #7
0
def initial_solution(g_orig, eqs):
    # Duplication of heap_md.min_degree with none forbidden
    g = fast_copy(g_orig)
    eq_nzeros = PriorityQueue()
    eq_nzeros.populate((eq, len(g[eq])) for eq in sorted(eqs))
    rowp, n_tears = [ ], len(g) - len(eqs)
    while eq_nzeros:
        nzeros, eq = eq_nzeros.popitem()
        if nzeros:
            n_tears -= 1
        rowp.append(eq)
        vrs = sorted(g[eq])
        eqs_update = set(chain.from_iterable(g[v] for v in vrs))
        eqs_update.discard(eq)
        g.remove_node(eq)
        g.remove_nodes_from(vrs)
        for e in sorted(eqs_update):
            eq_nzeros[e]  = len(g[e])
    assert len(rowp) == len(eqs)
    return n_tears, rowp
Пример #8
0
def applyDijkstra(g, start, finish=None):
    """
    Applies Dijkstra's algorithm to the graph g, updating the
    distance from start to each node in g.
    """
    initializeSingleSource(g, start)
    finalized = set()
    pq = PriorityQueue()
    pq.enqueue(start)
    while not pq.isEmpty():
        node = pq.dequeue()
        finalized.add(start)
        if node == finish:  #if we are at the finish node then we are all done!
            break
        for arc in node.getArcsFrom():
            n1 = arc.getStart()
            n2 = arc.getFinish()
            if n2 not in finalized:
                if n2.distance is math.inf:  #check if the node is one that we have not visited before, in which case we will add it to the queue
                    pq.enqueue(n2)
                oldDistance = n2.distance
                relax(n1, n2, arc.getCost())
                if n2.distance < oldDistance:
                    pq.raisePriority(n2, n2.distance)
Пример #9
0
def eliminate(g, eqs, eq):
    rowp = [eq]
    remaining_eqs = sorted(n for n in g if n in eqs and n != eq)
    heap = PriorityQueue()
    heap.populate((r, len(g[r])) for r in remaining_eqs)
    elimination_step(g, heap, eq)
    while heap:
        eq, nzeros = heap.peekitem()
        if nzeros > 1:
            break
        heap.popitem()
        rowp.append(eq)
        elimination_step(g, heap, eq)
    return rowp, heap
Пример #10
0
    def __init__(self, cfg, width, height):
        self.cfg = cfg
        fuel = 20
        try:
            fuel = self.cfg["initialfuel"]
        except:
            pass
        self.state = LevelState(fuel)
        self.board = [[0 for x in range(width)] for y in range(height)]
        self.dirty = [[True for x in range(width)] for y in range(height)]
        self.width = width
        self.height = height

        for x in range(width):
            for y in range(height):
                self.board[x][y] = PriorityQueue()
Пример #11
0
def eliminate(g, remaining_eqs, eq):
    rowp = [ eq ]
    remaining_eqs.remove(eq)
    heap = PriorityQueue()
    heap.populate((r, len(g[r])) for r in sorted(remaining_eqs))
    elimination_step(g, heap, eq)
    while heap:
        eq, nzeros = heap.peekitem()
        if nzeros > 1:
            break
        remaining_eqs.remove(eq)
        heap.popitem()
        rowp.append(eq)
        elimination_step(g, heap, eq)
    return rowp, heap
Пример #12
0
def applyDijkstraOrig(g, start):
    """
    Applies Dijkstra's algorithm to the graph g, updating the
    distance from start to each node in g.
    """
    initializeSingleSource(g, start)
    finalized = set()
    pq = PriorityQueue()
    for node in g.getNodes():
        pq.enqueue(node, node.distance)
    while not pq.isEmpty():
        node = pq.dequeue()
        finalized.add(node)
        for arc in node.getArcsFrom():
            n1 = arc.getStart()
            n2 = arc.getFinish()
            if n2 not in finalized:
                oldDistance = n2.distance
                relax(n1, n2, arc.getCost())
                if n2.distance < oldDistance:
                    pq.raisePriorityOrig(n2, n2.distance)
Пример #13
0
def astar(graph, start, goal):
    # Fringe. Nodes not visited yet
    openList = PriorityQueue()

    # Visited Nodes. Each one will store it's parent position
    closedList = {}

    node = Node(start)
    openList.push(node)

    while openList:
        node, _ = openList.pop()
        position, cost = node.position, node.cost

        if position in closedList:
            # Oops. Already expanded.
            continue

        # Save the node in the closed list, and keep track of its parent
        closedList[position] = node.parent
        if position == goal:
            break
        for childPosition, actionCost in graph.getChildren(position):
            # Only add to the open list if it's not expanded yet
            if not childPosition in closedList:
                childNode = Node(childPosition, cost + actionCost, position)
                openList.push(
                    childNode,
                    childNode.cost + graph.getHCost(childPosition, goal))

    path = []
    if position == goal:
        # Ensure a path has been found
        path.insert(0, position)
        while position and position != start:
            position = closedList[position]
            path.insert(0, position)

    return path
Пример #14
0
class WaitingQueue:
    def __init__(self):
        self.queue = PriorityQueue()
        self.log = []

    def push(self, current_time, p):
        self.queue.push([p.healthy, current_time], p)
        self.log.append((Log.ENTER, p.healthy, current_time))

    def empty(self):
        return self.queue.empty()

    def pop(self, current_time):
        p = self.queue.pop()[-1]
        self.log.append((Log.EXIT, p.healthy, current_time))
        return p

    def remove(self, current_time, p):
        self.queue.remove(p)
        self.log.append((Log.EXIT, p.healthy, current_time))

    def size(self):
        return self.queue.size()
Пример #15
0
def astar(graph, start, goal):
    # Fringe. Nodes not visited yet
    openList = PriorityQueue()

    # Visited Nodes. Each one will store it's parent position
    closedList = {}

    node = Node(start)
    openList.push(node)

    while openList:
        node, _ = openList.pop()
        position, cost = node.position, node.cost

        if position in closedList:
            # Oops. Already expanded.
            continue

        # Save the node in the closed list, and keep track of its parent
        closedList[position] = node.parent
        if position == goal:
            break
        for childPosition, actionCost in graph.getChildren(position):
            # Only add to the open list if it's not expanded yet
            if not childPosition in closedList:
                childNode = Node(childPosition, cost + actionCost, position)
                openList.push(childNode, childNode.cost + graph.getHCost(childPosition, goal))

    path = []
    if position == goal:
        # Ensure a path has been found
        path.insert(0, position)
        while position and position != start:
            position = closedList[position]
            path.insert(0, position)

    return path
Пример #16
0
def solve(mode):

    if mode == 1:
        # test code for grid class
        print("sup")
        a = Grid([0, 1, 2, 3, 4, 5, 6, 7, 8])
        b = Grid([1, 2, 3, 8, 0, 4, 7, 6, 5])
        c = Grid([0, 1, 2, 3, 4, 5, 6, 7, 8])

        print(a)
        print(b)
        print(c)
        print("a = b? %s" % a.equals(b))
        print("a = c? %s" % a.equals(c))
        print("a = c? %s" % Grid.equal(a, c))
        print("is a soln? %s" % a.is_solution())
        print("is b soln? %s" % b.is_solution())

    if mode == 2:
        # test code for node class
        a = Node(Grid([0, 1, 2, 3, 4, 5, 6, 7, 8]), 0, 0)
        b = Node(a.data, a, 0)
        a.print_tree()

    if mode == 3:
        # test code for get_moves()
        soln = Grid([1, 2, 3, 8, 0, 4, 7, 6, 5])
        a = Node(generate_problem(soln), 0, 0)
        a.print_tree()
        for move in a.data.get_moves():
            print(move)
            Node(Grid(a.data.move(move)), a, 0)
        a.print_tree()

    if mode == 4:
        # A* search algorithm
        pq = PriorityQueue()
        soln = Grid([1, 2, 3, 8, 0, 4, 7, 6, 5])
        root = Node(generate_problem(soln), 0, 0)

        def expand_node(node):
            # expands node to generate all possible moves
            if len(node.children) == 0:
                for move in node.data.get_moves():
                    m = Grid(node.data.move(move))
                    if not root.find_item(m):
                        # makes sure there are no duplicates
                        Node(m, node, move)

        if root.data.is_solution():
            return

        pq.push(root, 0)

        gui = EightPuzzleGUI()
        best = B(root)
        gui.draw_grid(best.data.data, gui.mainFrame, 50)

        def increment(button, button1):
            gui.mainFrame.update()
            nxt = pq.pop()  # gets next thing in PQ
            expand_node(nxt)

            if len(pq) > 0:
                gui.draw_grid(pq.data.data[0][0].data, gui.rightFrame1, 12)
            if len(pq) > 1:
                gui.draw_grid(pq.data.data[1][0].data, gui.rightFrame2, 12)
            if len(pq) > 2:
                gui.draw_grid(pq.data.data[2][0].data, gui.rightFrame3, 12)
            if len(pq) > 3:
                gui.draw_grid(pq.data.data[3][0].data, gui.rightFrame4, 12)
            if len(pq) > 4:
                gui.draw_grid(pq.data.data[4][0].data, gui.rightFrame5, 12)

            for child in nxt.children:
                # adds children to PQ with h(n) + g(n)
                # gui.draw_grid(child.data, gui.mainFrame, 50)
                if child.data.h_score() < best.data.data.h_score():
                    best.data = child
                    gui.draw_grid(best.data.data, gui.mainFrame, 50)
                pq.push(child, child.data.h_score() + 0.5 * child.level)
                if child.data.is_solution():
                    button.destroy()
                    button1.destroy()
                    # print(child.moves)
                    gui.draw_moves(child.moves)
                    return True
                # pq.print()
            return False

        def loop_to_end(button, button1):
            # loops until solution is found
            while True:
                if increment(button, button1):
                    return

        start = tk.Button(gui.root,
                          text="Increment",
                          command=lambda: increment(start, loop),
                          width=5,
                          height=5)
        start.grid(column=0, row=4, sticky=tk.N + tk.S + tk.E + tk.W)

        loop = tk.Button(gui.root,
                         text="Loop",
                         command=lambda: loop_to_end(start, loop),
                         width=5,
                         height=5)
        loop.grid(column=1, row=4, sticky=tk.N + tk.S + tk.E + tk.W)

        gui.root.mainloop()
Пример #17
0
 def __init__(self):
     self.queue = PriorityQueue()
     self.log = []
Пример #18
0
            return True
    
    return False


def is_bounded(x):
    return x[0] >= 0 and x[0] <= 100 and x[1] >= 0 and x[1] <= 100


path = []
start = (0,50)

while in_circle(start):
    start = (0,np.random.randint(101))

frontier = PriorityQueue()
frontier.insert(start,0)

visited = set()
while frontier.heap:
    dist,node = frontier.pop()
    path.append(node)

    if node[0] == 100:
        break
    
    visited.add(node)
    
    up = (node[0], node[1] + d)
    up_right = (node[0] + d, node[1] + d)
    right = (node[0] + d + 1, node[1])
Пример #19
0
def get_ready_queue(job_list, pattern, time_quantum):

    # obtain job key function as key for priority queue comparison
    job_key = job_keys[pattern]

    if job_key == round_robin:
        job_list.sort(key=first_come_first_serve)
        i = 0
        while i < len(job_list):
            job = job_list[i]
            job.instance_id = i
            if job.duration > time_quantum:

                split_job = Job(job.arrival + time_quantum,
                                job.duration - time_quantum, job.priority,
                                job.id, True)
                job.terminate = False
                job.duration = time_quantum
                job_list.append(split_job)
            i += 1

    global last_index
    last_index.clear()

    # prepare job queue
    job_queue = PriorityQueue(job_list, key=job_key)

    # prepare the ready queue
    ready_queue = []
    global time_elapsed
    time_elapsed = 0

    global idd
    idd = 0

    def schedule(job):

        # schedule a job to the ready queue
        if ready_queue and ready_queue[-1].id == job.id:
            # merge with the previous job because same ID
            # this happens when pre-emptive
            ready_queue[-1].duration += job.duration
            ready_queue[-1].terminate = job.terminate
        else:
            # append new job
            ready_queue.append(job)
        # update time elapsed after scheduling
        global time_elapsed
        time_elapsed = ready_queue[-1].end()

        global last_index, idd
        last_index[job.id] = idd
        idd += 1

    # simulate scheduling algorithm
    while job_queue:

        # get the next job
        job = job_queue.pop()
        global last_index
        if job.idd != (last_index[job.id] if job.id in last_index else -1):
            job.idd = (last_index[job.id] if job.id in last_index else -1)
            job_queue.push(job)
        elif job.arrival < time_elapsed:  # this job will arrive later, repush to the queue
            job.arrival = time_elapsed
            #job.instance_id = Job.instance_id
            #Job.instance_id += 1
            job_queue.push(job)

        elif job_key == round_robin and job.duration > time_quantum:
            # split job into two for round robin
            part_two = Job(arrival=job.arrival + time_quantum,
                           duration=job.duration - time_quantum,
                           priority=job.priority,
                           job_id=job.id,
                           terminate=job.terminate)
            # part_two.instance_id = job.instance_id + len(job_list)
            job_queue.push(part_two)  # repush part 2
            # process part 1
            job.duration = time_quantum
            job.terminate = False
            job_queue.push(job)
            # schedule(job)

        elif not pre_emptive(job_key):
            # schedule immediately
            schedule(job)

        else:  # pre_emptive

            # special case: find possible jobs that can interrupt
            put_back = []
            interrupted = False

            while job_queue and job_queue.top().arrival < job.end():

                # check if the next job is better than having the other end of the current job
                interrupt = job_queue.top()
                split_job = Job(arrival=interrupt.arrival,
                                duration=job.end() - interrupt.arrival,
                                priority=job.priority,
                                job_id=job.id,
                                terminate=job.terminate)
                # print interrupt, 'wants to interrupt', split_job
                # print job_key(interrupt), job_key(split_job)

                if job_key(interrupt) < job_key(split_job):
                    # job has been interrupted! split then repush into the queue
                    job.duration -= split_job.duration
                    job.terminate = False

                    # push new parts of the job
                    job_queue.push(job)
                    job_queue.push(split_job)
                    interrupted = True
                    break

                put_back.append(job_queue.pop())

            # return tested jobs back into queue
            for tested_job in put_back:
                job_queue.push(tested_job)

            if not interrupted:
                # finalize job schedule
                schedule(job)

    return ready_queue
Пример #20
0
def limited_infection(g, source=None, limit=5, threshold=0):
    '''
    Runs limited infection using adjusted BFS 

    params
    ------
    g: input graph
    source: node to start infection from
    limit: max number of nodes
    threshold: min value of edge weights to traverse on and accept

    returns
    ------
    iterations for animation
    '''
    if not source:
        source = pick_source(g)

    # create dictionary of nodes to store state for animation
    infected = OrderedDict()
    for node in g.nodes():
        infected[node] = False

    # store initial state
    iterations = [list(infected.items())]

    # run altered bfs algorithm
    visited = set()
    queue = PriorityQueue()
    queue.add(source, 1)
    count=0

    while not queue.is_empty():
        # exact if limit reached
        if count >= limit:
            break

        # pop node from priority queue of nodes
        p, n = queue.pop_smallest()
        print(p, n)
        user = g.node[n]['data'] 

        if n not in visited:
            # infect current node
            user.version = 'new'
            infected[n] = True
            iterations.append(list(infected.items()))
            visited.add(n)
            # increment count of infected nodes
            count+=1

            # children of current node not yet infected
            suc = [adj for adj in g.successors(n) if adj not in visited]
            # parents of current node not yet infected
            pre = [adj for adj in g.predecessors(n) if adj not in visited]

            # if there are enough children to be under limit
            # add them with priority 1
            if suc and len(suc) <= (limit - count - queue.size(1)):
                for adj in suc:
                    if g[n][adj]['weight'] > threshold:
                        queue.add(adj, 1) 

            # else add them with priority 2
            else:
                for adj in suc:
                    if g[n][adj]['weight'] > threshold:
                        queue.add(adj, 2) 

            # add parents with priority 3
            for adj in pre:
                if g[adj][n]['weight'] > threshold:
                    queue.add(adj, 3)

            # add all adjacent nodes if nothing in queue
            if queue.is_empty():
                for adj in suc:
                    if g[n][adj]['weight'] > threshold:
                        queue.add(adj, 4)
                for adj in pre:
                    if g[adj][n]['weight'] > threshold:
                        queue.add(adj, 4)

    # flush output for testing
    sys.stdout.flush()

    return iterations
Пример #21
0
def get_ready_queue(job_list, pattern, time_quantum):

	# obtain job key function as key for priority queue comparison
	job_key = job_keys[pattern]
	
	if job_key == round_robin:
		job_list.sort(key=first_come_first_serve)
		i = 0
		while i < len(job_list):
			job = job_list[i]
			job.instance_id = i
			if job.duration > time_quantum:
				
				split_job = Job(job.arrival + time_quantum, job.duration - time_quantum, job.priority, job.id, True)
				job.terminate = False
				job.duration = time_quantum
				job_list.append(split_job)
			i += 1
	
	global last_index
	last_index.clear()
	
	# prepare job queue
	job_queue = PriorityQueue(job_list, key=job_key)

	# prepare the ready queue
	ready_queue = []
	global time_elapsed
	time_elapsed = 0
	
	global idd
	idd = 0
	
	def schedule(job):
			
		# schedule a job to the ready queue
		if ready_queue and ready_queue[-1].id == job.id:
			# merge with the previous job because same ID
			# this happens when pre-emptive
			ready_queue[-1].duration += job.duration
			ready_queue[-1].terminate = job.terminate	
		else:
			# append new job
			ready_queue.append(job)
		# update time elapsed after scheduling
		global time_elapsed
		time_elapsed = ready_queue[-1].end()
		
		global last_index, idd
		last_index[job.id] = idd
		idd += 1

	# simulate scheduling algorithm
	while job_queue:

		# get the next job
		job = job_queue.pop()
		global last_index
		if job.idd != (last_index[job.id] if job.id in last_index else -1):
			job.idd = (last_index[job.id] if job.id in last_index else -1)
			job_queue.push(job)
		elif job.arrival < time_elapsed: # this job will arrive later, repush to the queue
			job.arrival = time_elapsed
			#job.instance_id = Job.instance_id
			#Job.instance_id += 1
			job_queue.push(job)
			
		elif job_key == round_robin and job.duration > time_quantum:
			# split job into two for round robin
			part_two = Job(
				arrival   = job.arrival + time_quantum,
				duration  = job.duration - time_quantum,
				priority  = job.priority,
				job_id    = job.id,
				terminate = job.terminate
			)
			# part_two.instance_id = job.instance_id + len(job_list)
			job_queue.push(part_two) # repush part 2
			# process part 1
			job.duration = time_quantum
			job.terminate = False
			job_queue.push(job)
			# schedule(job)
		
		elif not pre_emptive(job_key):
			# schedule immediately
			schedule(job)

		else: # pre_emptive

			# special case: find possible jobs that can interrupt
			put_back = []
			interrupted = False

			while job_queue and job_queue.top().arrival < job.end():
				
				# check if the next job is better than having the other end of the current job
				interrupt = job_queue.top()
				split_job = Job(
					arrival   = interrupt.arrival,
					duration  = job.end() - interrupt.arrival,
					priority  = job.priority,
					job_id    = job.id,
					terminate = job.terminate
				)
				# print interrupt, 'wants to interrupt', split_job
				# print job_key(interrupt), job_key(split_job)
				
				if job_key(interrupt) < job_key(split_job):
					# job has been interrupted! split then repush into the queue
					job.duration -= split_job.duration
					job.terminate = False

					# push new parts of the job
					job_queue.push(job)
					job_queue.push(split_job)
					interrupted = True
					break

				put_back.append(job_queue.pop())

			# return tested jobs back into queue
			for tested_job in put_back:
				job_queue.push(tested_job)

			if not interrupted:
				# finalize job schedule
				schedule(job)

	return ready_queue
Пример #22
0
def astarItemsMultiPath(graph, start, goal, itemsAvailable, initialRaftState,
                        illegalEdges):

    #itemsAvailable = intialItems.copy()
    #print("initial state") print(itemsAvailable)

    # Fringe. Nodes not visited yet
    openList = PriorityQueue()

    # Visited Nodes. Each one will store it's parent position
    closedList = {}
    nodeTable = {}

    # assign some start and goal points
    # and push start point as a node to openList.
    start_tuple = tuple(start)
    goal_tuple = tuple(goal)
    node = PathNode(start_tuple, itemsAvailable.copy())
    node.setRaftState(initialRaftState)
    openList.push(node)

    while openList:

        # if openList does not contain any node
        # we will break.
        curr_node, _ = openList.pop()
        if not curr_node:
            break

        position, cost = curr_node.position, curr_node.cost

        if position in closedList:
            # Oops. Already expanded.
            continue

        # Save the node in the closed list, and keep track of its parent
        if curr_node.parent != None:
            closedList[position] = curr_node.parent.position
        else:
            closedList[position] = curr_node.position

        #track of its items remainings
        nodeTable[position] = curr_node

        # arrived to goal so save it as goal node.
        if position == goal_tuple:
            goalNode = curr_node
            break

        # copy some parent properties
        curr_available = curr_node.getItemAvailable()
        raftState = curr_node.getRaftState()
        parentStonePlace = curr_node.getStonePlaced().copy()

        # for each legal child for current parent,
        for childPosition, actionCost, itemRequired, element in graph.getChildren(
                position, curr_available, raftState, parentStonePlace):
            copyStonePlaced = parentStonePlace.copy()

            # if illegal edges were given
            # and current one is illegal, ignore current child.
            pos1 = list(position).copy()
            pos2 = childPosition
            if illegalEdges and ([pos1, pos2] in illegalEdges
                                 or [pos2, pos1] in illegalEdges):
                continue

            # Only add to the open list if it's not expanded yet
            if not tuple(childPosition) in closedList:

                # copyAvailableItem
                copy_available_item = curr_available.copy()

                # deduct from item list if it was required
                if itemRequired:
                    copy_available_item = deductItem(copy_available_item,
                                                     itemRequired)

                childRaftSate = raftState

                # updating child raftstate based on where current child is
                # and the item required to get to the child.
                if itemRequired == 'r':
                    childRaftSate = 1

                elif childRaftSate == 1 and element != '~':
                    childRaftSate = 0

                # updating the stone coordinate that was used for child.
                # append to the parent ones.
                stoneCoord = []
                if itemRequired == 'o':
                    stoneCoord = [childPosition]
                    #print(stoneCoord)
                    copyStonePlaced += stoneCoord

                # creating new child node and push to the openlist
                childNode = PathNode(tuple(childPosition), copy_available_item,
                                     cost + actionCost, curr_node,
                                     childRaftSate)
                childNode.addStonePlaced(copyStonePlaced)
                openList.push(
                    childNode,
                    childNode.cost + graph.getHCost(childPosition, goal))

    # intialize the returning variables
    path = []
    totalItemUsed = []
    totalNewItemCollected = []
    itemUsedState = False
    finalItemList = itemsAvailable
    finalRaftState = 1
    finalStonePlace = []

    # if we arrive goal, we are updating those variables.
    if position == goal_tuple:
        finalItemList = goalNode.getItemAvailable()
        itemUsedState = confirmItemUsed(finalItemList, itemsAvailable)
        finalRaftState = goalNode.getRaftState()
        finalStonePlace = goalNode.getStonePlaced()

        # Ensure a path has been found
        position_list = list(position)

        path.insert(0, position_list)
        while position and position != start_tuple:
            position = closedList[position]
            position_list = list(position)
            path.insert(0, position_list)

    return [
        path, itemUsedState, finalItemList, finalRaftState, finalStonePlace,
        nodeTable
    ]  #finalItemList, ]
Пример #23
0
def solve_cube():
    def expand_node(node):
        # expands node to generate all possible moves
        if len(node.children) == 0:
            for i in range(6):
                m = deepcopy(node.data)
                m.rotate_face(list(Facing)[i])
                if not root.find_item(m):
                    # makes sure there are no duplicates
                    Node(m, node, list(Facing)[i])

    def increment(button, button1):
        gui.mainFrame.update()
        nxt = pq.pop()  # gets next thing in PQ
        expand_node(nxt)
        # print(nxt.data)

        if len(pq) > 0:
            gui.draw_cube(pq.data.data[0][0].data, gui.rightFrame1, 10)
        if len(pq) > 1:
            gui.draw_cube(pq.data.data[1][0].data, gui.rightFrame2, 10)
        if len(pq) > 2:
            gui.draw_cube(pq.data.data[2][0].data, gui.rightFrame3, 10)
        if len(pq) > 3:
            gui.draw_cube(pq.data.data[3][0].data, gui.rightFrame4, 10)
        if len(pq) > 4:
            gui.draw_cube(pq.data.data[4][0].data, gui.rightFrame5, 10)

        for child in nxt.children:
            # adds children to PQ with h(n) + g(n)
            # gui.draw_grid(child.data, gui.mainFrame, 40)
            if child.data.h_score() < best.data.data.h_score():
                best.data = child
                gui.draw_grid(best.data.data, gui.mainFrame, 40)
            pq.push(child, child.data.h_score() + 4 * child.level)
            if child.data.h_score() == 0:
                button.destroy()
                button1.destroy()
                # print(child.data)
                # print(child.moves)
                # print("done idiot")

                gui.draw_moves(child.moves)
                return True
            # pq.print()
        return False

    def loop_to_end(button, button1):
        for i in range(999):
            if increment(button, button1):
                return

    pq = PriorityQueue()
    root = Node(Cube(), 0, -1)
    root.data.scramble(6)
    # print(root.data)

    gui = EightPuzzleGUI()

    pq.push(root, 0)
    best = B(root)

    start = tk.Button(gui.root,
                      text="Increment",
                      command=lambda: increment(start, loop),
                      width=5,
                      height=5)
    start.grid(column=0, row=4, sticky=tk.N + tk.S + tk.E + tk.W)

    loop = tk.Button(gui.root,
                     text="Loop",
                     command=lambda: loop_to_end(start, loop),
                     width=5,
                     height=5)
    loop.grid(column=1, row=4, sticky=tk.N + tk.S + tk.E + tk.W)

    gui.root.mainloop()