コード例 #1
0
def ExecuteAllPossibileNodesInDG(executable_vertex,
                                 executed_vertex,
                                 G,
                                 DG,
                                 mapping,
                                 draw,
                                 DiG,
                                 edges_DiG,
                                 cir_phy=None,
                                 q_phy=None):
    '''check whether this window already has appliable vertexes, if has, then execute them'''
    temp = True
    while temp == True:
        temp = False
        removed_nodes = []
        for vertex in executable_vertex:
            if ct.IsVertexInDGOperatiable(vertex, DG, G, mapping) == True:
                '''check whether this CNOT needs 4 H gates to convert direction'''
                if DiG != None:
                    flag_4H = ct.CheckCNOTNeedConvertDirection2(
                        vertex, DG, mapping, edges_DiG)
                    if flag_4H == False:
                        '''if no need 4 extra H, then execute it'''
                        if draw == True:
                            ct.ConductCNOTOperationInVertex(
                                DG,
                                vertex,
                                mapping,
                                cir_phy,
                                q_phy,
                                reverse_drection=flag_4H,
                                remove_node=False)
                            cir_phy.barrier()
                        removed_nodes.append(vertex)
                        temp = True
                else:
                    '''if architecture graph is undirected, execute it'''
                    if draw == True:
                        ct.ConductCNOTOperationInVertex(DG,
                                                        vertex,
                                                        mapping,
                                                        cir_phy,
                                                        q_phy,
                                                        reverse_drection=False,
                                                        remove_node=False)
                        cir_phy.barrier()
                    removed_nodes.append(vertex)
                    temp = True
        if temp == True:
            executable_vertex = FindExecutableNode(DG, executed_vertex,
                                                   executable_vertex,
                                                   removed_nodes)
    return executed_vertex, executable_vertex
コード例 #2
0
def ExpandTreeForNextStep(G, DG, search_tree, leaf_nodes,
                          possible_swap_combination, SWAP_cost,
                          shortest_length_G, shortest_path_G, next_node_list,
                          max_shortest_length_G, min_remoteCNOT_hop,
                          level_lookahead, q_phy, draw, DiG):
    best_cost_total = None
    flag_4H = 0
    finished_nodes = []
    added_nodes = []
    cir_phy_next = None
    num_all_vertex = len(DG.nodes())
    if DiG != None:
        edges_DiG = list(DiG.edges)
    else:
        edges_DiG = None
    '''find all possible operation for next step and expand the search tree accordingly'''
    #print('number of leaf nodes is', len(leaf_nodes))
    for leaf_node in leaf_nodes:
        #print('current leaf node is', leaf_node)
        '''get attributes from current leaf node'''
        current_map = search_tree.nodes[leaf_node]['mapping']
        cost_g_current = search_tree.nodes[leaf_node]['cost_g']
        executed_vertex_current = search_tree.nodes[leaf_node][
            'executed_vertex']
        executable_vertex_current = search_tree.nodes[leaf_node][
            'executable_vertex']
        if draw == True:
            cir_phy_current = search_tree.nodes[leaf_node]['phy_circuit']
        '''add successor nodes to current node'''
        '''SWAP'''
        for swaps in possible_swap_combination:
            '''judge whether the swap in trivial to avoid unnecessary state'''
            flag_nontrivial = ct.CheckSWAPInvolved(swaps,
                                                   executable_vertex_current,
                                                   DG, current_map)
            print('FL is ', executable_vertex_current)
            print('SWAP ', swaps)
            print(flag_nontrivial)
            if flag_nontrivial == False:
                #print('trivival swap')
                continue

            #print(swaps)
            #start = time()
            #elapsed = (time() - start)
            #print("deep copy Time used:", elapsed, 's')
            if draw == True: cir_phy_next = copy.deepcopy(cir_phy_current)
            executable_vertex_next = executable_vertex_current.copy()
            executed_vertex_next = executed_vertex_current.copy()
            cost_g_next = cost_g_current + len(swaps) * SWAP_cost
            next_map = current_map.Copy()
            for current_swap in swaps:
                '''conduct each swap'''
                v0 = current_swap[0]
                v1 = current_swap[1]
                next_map.RenewMapViaExchangeCod(v0, v1)
                if draw == True: cir_phy_next.swap(q_phy[v0], q_phy[v1])
            '''check whether this window already has appliable vertexes, if has, then execute them'''
            res = ct.ExecuteAllPossibileNodesInDG(executable_vertex_next,
                                                  executed_vertex_next, G, DG,
                                                  next_map, draw, DiG,
                                                  edges_DiG, cir_phy_next,
                                                  q_phy)
            executed_vertex_next = res[0]
            executable_vertex_next = res[1]
            '''calculate cost for the new node'''
            #print('executable_vertex_next is', executable_vertex_next)
            cost_h_next = CalculateHeuristicCost(
                next_map, DG, executable_vertex_next, executed_vertex_next,
                shortest_length_G, shortest_path_G, SWAP_cost,
                max_shortest_length_G, level_lookahead, DiG)
            cost_total_next = CalculateTotalCost(cost_h_next, cost_g_next)
            '''generate next node'''
            next_node = next_node_list[0]
            next_node_list[0] = next_node_list[0] + 1
            added_nodes.append(next_node)
            AddNewNodeToSearchTree(next_node, search_tree, next_map,
                                   cost_g_next, cost_h_next, cost_total_next,
                                   executed_vertex_next,
                                   executable_vertex_next, current_swap)
            search_tree.add_edge(leaf_node, next_node)
            ST_file = open('ST_file.txt', 'a')
            ST_file.write('added edge is ' + str((leaf_node, next_node)) +
                          '\n' + '\n')
            ST_file.close()
            if draw == True:
                search_tree.nodes[next_node]['phy_circuit'] = cir_phy_next
                fig = (cir_phy_next.draw(scale=0.7,
                                         filename=None,
                                         style=None,
                                         output='mpl',
                                         interactive=False,
                                         line_length=None,
                                         plot_barriers=True,
                                         reverse_bits=False))
                fig.savefig(str(next_node) + '.pdf',
                            format='pdf',
                            papertype='a4')
            '''renew best expanded node in search tree'''
            num_remaining_vertex_next = num_all_vertex - len(
                executed_vertex_next)
            if num_remaining_vertex_next == 0: finished_nodes.append(next_node)
            if best_cost_total == None:
                best_cost_total = cost_total_next
                best_node = next_node
            else:
                if cost_total_next < best_cost_total:
                    best_cost_total = cost_total_next
                    best_node = next_node
        '''execute possible CNOT needing 4 extra 4 H'''
        if DiG != None:
            for vertex in executable_vertex_current:
                if ct.IsVertexInDGOperatiable(vertex, DG, G,
                                              current_map) == True:
                    '''check whether this CNOT needs 4 H gates to convert direction'''
                    flag_4H = ct.CheckCNOTNeedConvertDirection2(
                        vertex, DG, current_map, edges_DiG)
                    if flag_4H == False:
                        raise Exception(
                            'unexpected operatible CNOT without 4 H gates')
                    if flag_4H == True:
                        '''if need 4 extra H, then execute it and add to the new node'''
                        next_map = current_map.Copy()
                        cost_g_next = cost_g_current + flag_4H * 4
                        executed_vertex_next = executed_vertex_current.copy()
                        if draw == True:
                            cir_phy_next = copy.deepcopy(cir_phy_current)
                            ct.ConductCNOTOperationInVertex(
                                DG,
                                vertex,
                                current_map,
                                cir_phy_next,
                                q_phy,
                                reverse_drection=flag_4H,
                                remove_node=False)
                            cir_phy_next.barrier()
                        executable_vertex_next = executable_vertex_current.copy(
                        )
                        executable_vertex_next = ct.FindExecutableNode(
                            DG, executed_vertex_next, executable_vertex_next,
                            [vertex])
                        '''check whether this window already has appliable vertexes, if has, then execute them'''
                        res = ct.ExecuteAllPossibileNodesInDG(
                            executable_vertex_next, executed_vertex_next, G,
                            DG, next_map, draw, DiG, edges_DiG, cir_phy_next,
                            q_phy)
                        executed_vertex_next = res[0]
                        executable_vertex_next = res[1]
                        '''calculate cost for the new node'''
                        #print('executable_vertex_next is', executable_vertex_next)
                        cost_h_next = CalculateHeuristicCost(
                            next_map, DG, executable_vertex_next,
                            executed_vertex_next, shortest_length_G,
                            shortest_path_G, SWAP_cost, max_shortest_length_G,
                            level_lookahead, DiG)
                        cost_total_next = CalculateTotalCost(
                            cost_h_next, cost_g_next)
                        '''generate next node'''
                        next_node = next_node_list[0]
                        next_node_list[0] = next_node_list[0] + 1
                        added_nodes.append(next_node)
                        qbits = DG.node[vertex]['operation'].involve_qubits
                        AddNewNodeToSearchTree(next_node, search_tree,
                                               next_map, cost_g_next,
                                               cost_h_next, cost_total_next,
                                               executed_vertex_next,
                                               executable_vertex_next,
                                               '4H' + str(qbits))
                        search_tree.add_edge(leaf_node, next_node)
                        print('add 4H ', next_node)
                        ST_file = open('ST_file.txt', 'a')
                        ST_file.write('added edge is ' +
                                      str((leaf_node, next_node)) + '\n' +
                                      '\n')
                        ST_file.close()
                        if draw == True:
                            search_tree.nodes[next_node][
                                'phy_circuit'] = cir_phy_next
                            fig = (cir_phy_next.draw(scale=0.7,
                                                     filename=None,
                                                     style=None,
                                                     output='mpl',
                                                     interactive=False,
                                                     line_length=None,
                                                     plot_barriers=True,
                                                     reverse_bits=False))
                            fig.savefig(str(next_node) + '.pdf',
                                        format='pdf',
                                        papertype='a4')
                        '''renew best expanded node in search tree'''
                        num_remaining_vertex_next = num_all_vertex - len(
                            executed_vertex_next)
                        if num_remaining_vertex_next == 0:
                            finished_nodes.append(next_node)
                        if best_cost_total == None:
                            best_cost_total = cost_total_next
                            best_node = next_node
                        else:
                            if cost_total_next < best_cost_total:
                                best_cost_total = cost_total_next
                                best_node = next_node
        '''remote CNOT'''
        #f use_remoteCNOT == True and DiG == None:
        if use_remoteCNOT == True:
            '''judge whether remote CNOT is applicable'''
            for current_vertex in executable_vertex_current:
                '''calculate distance between two input qubits'''
                current_operation = DG.node[current_vertex]['operation']
                q0 = current_operation.involve_qubits[0]
                q1 = current_operation.involve_qubits[1]
                v0 = current_map.DomToCod(q0)
                v1 = current_map.DomToCod(q1)
                current_hop = shortest_length_G[v0][v1]
                '''if a remote CNOT can be done, then execute it'''
                if (current_hop <= min_remoteCNOT_hop) and (current_hop >= 2):
                    next_map = current_map.Copy()
                    executable_vertex_next = executable_vertex_current.copy()
                    executed_vertex_next = executed_vertex_current.copy()
                    #print('current_hop is ', current_hop)
                    current_path = shortest_path_G[v0][v1]
                    # number of additional CNOTs in this remote CNOT operation
                    cost_CNOT_remoteCNOT = ct.CalRemoteCNOTCostinArchitectureGraph(
                        current_path, DiG) - 1  #这里减1是因为要去除本身的CNOT
                    cost_g_next = cost_g_current + cost_CNOT_remoteCNOT
                    if draw == True:
                        cir_phy_next = copy.deepcopy(cir_phy_current)
                        ct.RemoteCNOTinArchitectureGraph(
                            current_path, cir_phy_next, q_phy, DiG)
                        cir_phy_next.barrier()
                    executable_vertex_next = ct.FindExecutableNode(
                        DG, executed_vertex_next, executable_vertex_next,
                        [current_vertex])
                    '''check whether this window already has appliable vertexes, if has, then execute them'''
                    '''old version without considering the direction of CNOT gate'''
                    # =============================================================================
                    #                     temp = True
                    #                     while temp == True:
                    #                         temp = False
                    #                         for vertex in executable_vertex_next:
                    #                             if ct.IsVertexInDGOperatiable(vertex, DG_next, G, next_map) == True:
                    #                                 if draw == True:
                    #                                     ct.ConductOperationInVertex(DG_next, vertex, next_map, cir_phy_next, q_phy)
                    #                                     cir_phy_next.barrier()
                    #                                 else:
                    #                                     DG_next.remove_node(vertex)
                    #                                 num_executed_vertex_next += 1
                    #                                 temp = True
                    #                         if temp == True: executable_vertex_next = ct.FindExecutableNode(DG_next)
                    # =============================================================================
                    '''check whether this window already has appliable vertexes, if has, then execute them'''
                    '''new version considering the direction of CNOT gate'''
                    res = ct.ExecuteAllPossibileNodesInDG(
                        executable_vertex_next, executed_vertex_next, G, DG,
                        next_map, draw, DiG, edges_DiG, cir_phy_next, q_phy)
                    executed_vertex_next = res[0]
                    executable_vertex_next = res[1]
                    '''calculate cost for the new node'''
                    cost_h_next = CalculateHeuristicCost(
                        next_map, DG, executable_vertex_next,
                        executed_vertex_next, shortest_length_G,
                        shortest_path_G, SWAP_cost, max_shortest_length_G,
                        level_lookahead, DiG)
                    # =============================================================================
                    #                     cost_h_next = search_tree.nodes[leaf_node]['cost_h'].copy()
                    #                     cost_h_next[0] = cost_h_next[0] - ct.OperationCost(current_operation, next_map, G, shortest_length_G, edges_DiG, shortest_path_G)
                    # =============================================================================
                    cost_total_next = CalculateTotalCost(
                        cost_h_next, cost_g_next)
                    '''generate next node'''
                    next_node = next_node_list[0]
                    next_node_list[0] = next_node_list[0] + 1
                    added_nodes.append(next_node)
                    AddNewNodeToSearchTree(next_node, search_tree, next_map,
                                           cost_g_next, cost_h_next,
                                           cost_total_next,
                                           executed_vertex_next,
                                           executable_vertex_next)
                    search_tree.add_edge(leaf_node, next_node)
                    ST_file = open('ST_file.txt', 'a')
                    ST_file.write('added edge is ' +
                                  str((leaf_node, next_node)) + '\n' + '\n')
                    ST_file.close()
                    if draw == True:
                        search_tree.nodes[next_node][
                            'phy_circuit'] = cir_phy_next
                    '''renew best expanded node in search tree'''
                    num_remaining_vertex_next = num_all_vertex - len(
                        executed_vertex_next)
                    if num_remaining_vertex_next == 0:
                        finished_nodes.append(next_node)
                    if best_cost_total == None:
                        best_cost_total = cost_total_next
                        best_node = next_node
                    else:
                        if cost_total_next < best_cost_total:
                            best_cost_total = cost_total_next
                            best_node = next_node

    ST_file = open('ST_file.txt', 'a')
    ST_file.write('chosen node is ' + str(best_node) + '\n')
    ST_file.close()
    return best_node, finished_nodes, added_nodes
コード例 #3
0
def AStarSearchLookAhead(q_phy, cir_phy, G, DG, initial_map, shortest_length_G, shortest_path_G=None, possible_swap_combination=None, draw=False, DiG=None):
    # only set True when debugging
    debug_model = False
    display_complete_state = 1
    flag_4H = 0
    if DiG != None:
        edges_DiG = list(DiG.edges)
        #print('egdes are', edges_DiG)
        SWAP_cost = 7
    else:
        SWAP_cost = 3
    '''initial level and map'''
    executable_vertex = ct.FindExecutableNode(DG)
    finished_map = initial_map
    #executable_operation = ct.FindExecutableOperation(DG, executable_vertex)
    '''find all possible SWAP combinations for search in level'''
    if possible_swap_combination == None:
        possible_swap_combination = ct.FindAllPossibleSWAPParallel(G)
    
    '''search in all levels'''
    next_node_list = [1]
    swap_count = 0
    while executable_vertex != []:
        if debug_model == True:
            jjj = 5
        if display_complete_state == True: print(len(list(DG.node)), 'gates remaining')
        
        '''initial search tree for current level'''
        search_tree = nx.DiGraph()
        search_tree.add_node(0)
        next_node_list = [1]
        search_tree.nodes[0]['mapping'] = finished_map.Copy()
        search_tree.nodes[0]['cost_g'] = 0
        search_tree.nodes[0]['exist_swaps'] = []
        search_tree.nodes[0]['identity'] = search_tree.nodes[0]['mapping'].MapToTuple()
        
        '''initial nodes set for current level'''        
        leaf_nodes_identity = search_tree.nodes[0]['identity']
        leaf_nodes = {str(leaf_nodes_identity): 0}
        none_leaf_nodes = {}
        
        '''calculate heuristic cost for initial node'''
        cost_h_total = ct.HeuristicCostZulehnerLookAhead(finished_map, DG, executable_vertex, shortest_length_G, shortest_path_G, DiG)
        cost_h = cost_h_total[0]
        cost_h_current_level = cost_h_total[1]
        flag_finished = cost_h_total[2]
        search_tree.nodes[0]['cost_h'] = cost_h
        search_tree.nodes[0]['cost_h_current_level'] = cost_h_current_level
        search_tree.nodes[0]['flag_finished'] = flag_finished
        search_tree.nodes[0]['cost_total'] = search_tree.nodes[0]['cost_g'] + search_tree.nodes[0]['cost_h']
        
        if flag_finished == True:
            finished_node = 0
            finished_map = search_tree.nodes[finished_node]['mapping']
        else:
            finished_node = None
        
        '''search til find the finished node'''
        flag_finished = False
        '''expand tree for the first time, set father node 0'''
        finished_node = ExpandSearchTree(DG, search_tree, next_node_list, 0, none_leaf_nodes, leaf_nodes, finished_node, executable_vertex, shortest_length_G, possible_swap_combination, shortest_path_G, DiG)
        while flag_finished == False:
            if debug_model == True:
                jjj -= 1
                if jjj == 0:
                    break
            
            '''set best leaf node as current node to be expanded'''    
            father_node = None
            for node in leaf_nodes.values():
                if father_node == None:
                    father_node = node
                    father_cost = search_tree.nodes[father_node]['cost_total']
                else:
                    if search_tree.nodes[node]['cost_total'] < father_cost:
                        father_node = node
                        father_cost = search_tree.nodes[father_node]['cost_total']
            '''judge whether the search has finished'''
            if finished_node != None:
                finishe_node_cost = search_tree.nodes[finished_node]['cost_total']
                if father_cost > finishe_node_cost:
                    flag_finished = True
                    break            
            '''expand search tree based on current father node'''
            finished_node = ExpandSearchTree(DG, search_tree, next_node_list, father_node, none_leaf_nodes, leaf_nodes, finished_node, executable_vertex, shortest_length_G, possible_swap_combination, shortest_path_G, DiG)
        
        '''conduct SWAP operations before each level'''
        if draw == True:
            swaps = search_tree.nodes[finished_node]['exist_swaps']
            for current_swap in swaps:
                cir_phy.swap(q_phy[current_swap[0]], q_phy[current_swap[1]])
        
        '''conduct CNOT operations in current level'''
        #print('finished node is', finished_node)
        #print(search_tree.nodes[finished_node]['exist_swaps'])
        swap_count += len(search_tree.nodes[finished_node]['exist_swaps'])
        finished_map = search_tree.nodes[finished_node]['mapping']
        for vertex in executable_vertex:
            '''check whether this CNOT needs 4 H gates to convert direction'''
            if DiG != None:
                flag_4H = ct.CheckCNOTNeedConvertDirection2(vertex, DG, finished_map, edges_DiG)
                swap_count += flag_4H*4/7   
            ct.ConductCNOTOperationInVertex(DG, vertex, finished_map, cir_phy, q_phy, flag_4H)
        cir_phy.barrier()
        if debug_model == True: print(cir_phy.draw())
        '''refresh executable operations and go to the next level'''
        executable_vertex = ct.FindExecutableNode(DG)
    
    if draw == True:
        print(cir_phy.draw())
        fig = (cir_phy.draw(scale=0.7, filename=None, style=None, output='mpl', interactive=False, line_length=None, plot_barriers=True, reverse_bits=False))
        fig.savefig('circuit_Astarlookahead.eps', format='eps', dpi=1000)

    '''number of traversed states'''
    num_total_state = next_node_list[0] - 1
    additional_gates = swap_count * SWAP_cost
    #nx.draw(search_tree, with_labels=True)
    return swap_count, num_total_state, additional_gates