Example #1
0
 def test_empty_coupling_class(self):
     coupling = CouplingMap()
     self.assertEqual(0, coupling.size())
     self.assertEqual([], coupling.physical_qubits)
     self.assertEqual([], coupling.get_edges())
     self.assertFalse(coupling.is_connected())
     self.assertEqual("", str(coupling))
Example #2
0
 def setUp(self):
     coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
     coupling_map = CouplingMap(couplinglist=coupling)
     qr = QuantumRegister(7, 'q')
     layout = Layout({qr[i]: i for i in range(coupling_map.size())})
     self.config = TranspileConfig(optimization_level=1,
                                   basis_gates=['u1', 'u3', 'u2', 'cx'],
                                   initial_layout=layout,
                                   coupling_map=coupling_map,
                                   seed_transpiler=987,
                                   backend_properties=None)
Example #3
0
def _parse_coupling_map(coupling_map, backend, num_circuits):
    # try getting coupling_map from user, else backend
    if coupling_map is None:
        backend_version = getattr(backend, "version", 0)
        if not isinstance(backend_version, int):
            backend_version = 0
        if backend_version <= 1:
            if getattr(backend, "configuration", None):
                configuration = backend.configuration()
                if hasattr(configuration,
                           "coupling_map") and configuration.coupling_map:
                    faulty_map = _create_faulty_qubits_map(backend)
                    if faulty_map:
                        faulty_edges = [
                            gate.qubits
                            for gate in backend.properties().faulty_gates()
                        ]
                        functional_gates = [
                            edge for edge in configuration.coupling_map
                            if edge not in faulty_edges
                        ]
                        coupling_map = CouplingMap()
                        for qubit1, qubit2 in functional_gates:
                            if faulty_map[qubit1] is not None and faulty_map[
                                    qubit2] is not None:
                                coupling_map.add_edge(faulty_map[qubit1],
                                                      faulty_map[qubit2])
                        if configuration.n_qubits != coupling_map.size():
                            warnings.warn(
                                "The backend has currently some qubits/edges out of service."
                                " This temporarily reduces the backend size from "
                                f"{configuration.n_qubits} to {coupling_map.size()}",
                                UserWarning,
                            )
                    else:
                        coupling_map = CouplingMap(configuration.coupling_map)
        else:
            coupling_map = backend.coupling_map

    # coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]]
    if coupling_map is None or isinstance(coupling_map, CouplingMap):
        coupling_map = [coupling_map] * num_circuits
    elif isinstance(coupling_map, list) and all(
            isinstance(i, list) and len(i) == 2 for i in coupling_map):
        coupling_map = [coupling_map] * num_circuits

    coupling_map = [
        CouplingMap(cm) if isinstance(cm, list) else cm for cm in coupling_map
    ]

    return coupling_map
Example #4
0
def create_direction_only_pass_manager(device):
    # type: (BaseBackend) -> PassManager

    LOG.info("Creating direction-only PassManager for {}".format(device))

    cp = CouplingMap(couplinglist=device.configuration().coupling_map)
    basis = device.configuration().basis_gates

    pm = PassManager()
    pm.append(Unroller(basis=basis))
    # noinspection PyTypeChecker
    if cp.size() > 0:
        pm.append(CXDirection(coupling_map=cp))
    pm.append(Optimize1qGates())
    return pm
Example #5
0
    def setUp(self):
        coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
        coupling_map = CouplingMap(couplinglist=coupling)
        basis_gates = ['u1', 'u3', 'u2', 'cx']
        qr = QuantumRegister(7, 'q')
        layout = Layout({qr[i]: i for i in range(coupling_map.size())})

        # Create a pass manager with a variety of passes and flow control structures
        self.pass_manager = PassManager()
        self.pass_manager.append(SetLayout(layout))
        self.pass_manager.append(TrivialLayout(coupling_map), condition=lambda x: True)
        self.pass_manager.append(FullAncillaAllocation(coupling_map))
        self.pass_manager.append(EnlargeWithAncilla())
        self.pass_manager.append(Unroller(basis_gates))
        self.pass_manager.append(CheckMap(coupling_map))
        self.pass_manager.append(BarrierBeforeFinalMeasurements(), do_while=lambda x: False)
        self.pass_manager.append(CXDirection(coupling_map))
        self.pass_manager.append(RemoveResetInZeroState())
Example #6
0
def benchmark(depth, trail, parameters):

    if gdv_name == "TFL":
        folder = "BNTF"
        depth_string = "{:02}".format(depth)
        name_end = "TFL"
        if nr_qubits == 54:
            name_end = "QSE"

    elif gdv_name == "QSE":
        folder = "BSS"
        depth_string = "{:03}".format(depth)
        name_end = "QSE"

    # if nr_qubits==54:
    #     gdv_name = "QSE"

    qasm_file_name = "_private_benchmark/{}/{}QBT_{}CYC_{}_{}.qasm".format(
        folder, nr_qubits, depth_string, name_end, trail)

    solution_file_name = "_private_benchmark/meta/{}QBT_{}CYC_{}_{}_solution.csv".format(
        nr_qubits, depth_string, name_end, trail)

    # print("qiskit", depth)
    # input qasm file as circuit
    test_circuit = qiskit.QuantumCircuit.from_qasm_file(qasm_file_name)
    """
        Construct the optimal initial mapping
    """
    qiskit_layout_dict = dict()
    original_nodes = list()
    with open(solution_file_name, 'r') as csvfile:
        for original_node in csv.reader(csvfile, delimiter=','):
            original_nodes.append(literal_eval(original_node[0]))
    csvfile.close()
    # print(original_nodes)

    for i in range(len(original_nodes)):
        qiskit_layout_dict[test_circuit.qregs[0][i]] = original_nodes[i]
    # construct passes that use the optimal initial mapping and BasicSwap
    # however, no swapping gates should be ever necessary
    original_pm = PassManager()
    # print(original_nodes)
    qiskit_coupling_map = CouplingMap(
        couplinglist=connection_list[qubits[nr_qubits]])
    optimal_layout = Layout()
    optimal_layout.from_dict(qiskit_layout_dict)
    original_pm.append([
        SetLayout(optimal_layout),
        ApplyLayout(),
        BasicSwap(qiskit_coupling_map)
    ])
    map_original_circuit = original_pm.run(test_circuit)
    optimal_depth = map_original_circuit.depth()
    # print("optimal mapping: the circuit has", optimal_depth, "cycles")
    # print(map_original_circuit.draw(style="text"))
    # construct passes that use the DenseLayout+StochasticSwap without initial mapping
    """
       K7M 
    """
    gate_costs = {
        'id': 0,
        'u1': 0,
        'measure': 0,
        'reset': 0,
        'barrier': 0,
        'u2': 1,
        'u3': 1,
        'U': 1,
        "ok": 0,
        # update the costs
        "rev_cnot": 4 * 1 + 10,  # 4 u2/hadamard + 1 cnot
        "swap": 3 * 10 + 4,  # 4 u2/hadamard + 3 cnot
        'seed': 19
    }  # pass the seed through gate costs

    # parameters_string = str(parameters)

    # the number of qubits in the device
    parameters["nisq_qubits"] = qiskit_coupling_map.size()
    # Add the gate costs
    parameters["gate_costs"] = gate_costs
    # Should the initial mapping be chosen random?
    parameters["initial_map"] = K7MInitialMapping.HEURISTIC
    parameters["unidirectional_coupling"] = False
    parameters["dry_run"] = False

    k7mcomp = K7MCompiler(connection_list[qubits[nr_qubits]], parameters)

    execution_time = time.time()
    map_test_circuit, init_time, init_map = k7mcomp.run(test_circuit)
    execution_time = time.time() - execution_time

    if (map_test_circuit is None) and (init_map is None):
        # this happens when the execution was interrupted
        return optimal_depth, -1, execution_time, init_time, -1, -1

    # print(map_test_circuit.draw(output="text", fold=-1))
    # tmp_circuit = map_test_circuit.decompose()
    tmp_circuit = map_test_circuit
    # print(tmp_circuit.draw(output="text", fold=-1))
    # tmp_circuit = qiskit_to_tk(map_test_circuit)
    # Transform.RebaseToQiskit().DecomposeSWAPtoCX().apply(tmp_circuit)
    depth_result = tmp_circuit.depth()

    # print("k7m mapping: the circuit has", depth_result, "cycles")
    # print(map_test_circuit.draw(style="text"))
    # accumulate result
    # print("----")

    nr_t1 = noOfTranspositions(list(range(nr_qubits)), original_nodes,
                               nr_qubits)
    nr_t2 = noOfTranspositions(original_nodes, init_map, nr_qubits)

    return optimal_depth, depth_result, execution_time, init_time, nr_t1, nr_t2
Example #7
0
def benchmark(depth, trail, varying_param):

    # qasm_file_name = "_private_benchmark/BNTF/16QBT_{:02}CYC_{}_{}.qasm".format(
    #     depth, gdv_name, trail)
    #
    # solution_file_name = "_private_benchmark/meta/16QBT_{:02}CYC_{}_{}_solution.csv".format(
    #     depth, gdv_name, trail)

    if gdv_name == "TFL":
        folder = "BNTF"
        depth_string = "{:02}".format(depth)
        name_end = "TFL"
        if nr_qubits == 54:
            name_end = "QSE"

    elif gdv_name == "QSE":
        folder = "BSS"
        depth_string = "{:03}".format(depth)
        name_end = "QSE"

    # if nr_qubits==54:
    #     gdv_name = "QSE"

    qasm_file_name = "_private_benchmark/{}/{}QBT_{}CYC_{}_{}.qasm".format(
        folder, nr_qubits, depth_string, name_end, trail)

    solution_file_name = "_private_benchmark/meta/{}QBT_{}CYC_{}_{}_solution.csv".format(
        nr_qubits, depth_string, name_end, trail)

    # print("qiskit", depth)
    # input qasm file as circuit
    test_circuit = qiskit.QuantumCircuit.from_qasm_file(qasm_file_name)


    """
        Construct the optimal initial mapping
    """
    qiskit_layout_dict = dict()
    original_nodes = list()
    with open(solution_file_name, 'r') as csvfile:
        for original_node in csv.reader(csvfile, delimiter=','):
            original_nodes.append(literal_eval(original_node[0]))
    csvfile.close()
    print(original_nodes)

    for i in range(len(original_nodes)):
        qiskit_layout_dict[test_circuit.qregs[0][i]] = original_nodes[i]
    # construct passes that use the optimal initial mapping and BasicSwap
    # however, no swapping gates should be ever necessary
    original_pm = PassManager()
    # print(original_nodes)
    qiskit_coupling_map = CouplingMap(couplinglist=connection_list[qubits[nr_qubits]])
    optimal_layout = Layout()
    optimal_layout.from_dict(qiskit_layout_dict)
    original_pm.append([SetLayout(optimal_layout),
                        ApplyLayout(),
                        BasicSwap(qiskit_coupling_map)])
    map_original_circuit = original_pm.run(test_circuit)
    optimal_depth = map_original_circuit.depth()
    print("optimal mapping: the circuit has", optimal_depth, "cycles")
    # print(map_original_circuit.draw(style="text"))
    # construct passes that use the DenseLayout+StochasticSwap without initial mapping


    """
       K7M 
    """
    gate_costs = {'id': 0, 'u1': 0, 'measure': 0,
                  'reset': 0, 'barrier': 0,
                  'u2': 1, 'u3': 1, 'U': 1,

                  "ok": 0,
                  # update the costs
                  "rev_cnot": 4 * 1 + 10,  # 4 u2/hadamard + 1 cnot
                  "swap": 3 * 10 + 4,  # 4 u2/hadamard + 3 cnot

                  'seed': 19}  # pass the seed through gate costs

    """
    20 secunde
    4.093154 :: attr_b=5.00,attr_c=0.61,edge_cost=0.20,max_breadth=4,max_depth=9,movement_factor=2
    
    5 secunde
    4.138454 :: attr_b=17.30,attr_c=0.25,edge_cost=0.20,max_breadth=3,max_depth=9,movement_factor=4
    
    0.5 secunde
    4.322774 :: attr_b=8.00,attr_c=0.02,edge_cost=0.20,max_breadth=2,max_depth=9,movement_factor=2
    
    0.05 secunde
    4.464655 :: attr_b=3.50,attr_c=0.31,edge_cost=0.90,max_breadth=2,max_depth=6,movement_factor=6
    
    # Lucian
    2.424873 for [-w9 -d9 -b1.50 -c0.32 -e0.80 -m10]
    """

    parameters = {
        "att_b": 15,
        "att_c": 0,

        "cx": 0.8,

        "max_children": 2,
        "max_depth": 9,

        "div_dist": 10,

        # UNUSED
        "opt_att": True,
        "opt_max_t_min": False,
        "qubit_increase_factor": 3,
        "option_skip_cx": False,
        "penalty_skip_cx": 20,
        "opt_div_by_act": False,

        "TIME_LIMIT": 600  # seconds
    }

    parameters_string = str(parameters)

    # the number of qubits in the device
    parameters["nisq_qubits"] = qiskit_coupling_map.size()
    # Add the gate costs
    parameters["gate_costs"] = gate_costs
    # Should the initial mapping be chosen random?
    parameters["initial_map"] = K7MInitialMapping.HEURISTIC
    parameters["unidirectional_coupling"]=False
    parameters["dry_run"] = False

    k7mcomp = K7MCompiler(connection_list[qubits[nr_qubits]], parameters)

    execution_time = time.time()
    map_test_circuit, init_time, init_map = k7mcomp.run(test_circuit)
    execution_time = time.time() - execution_time

    if (map_test_circuit is None) and (init_map is None):
        # this happens when the execution was interrupted
        # Will not write to file of results. So the averages are not affected
        # by the interrupted experiments
        return optimal_depth, -1, execution_time, init_time, -1, -1

    depth_result = map_test_circuit.depth()

    print("k7m mapping: the circuit has", depth_result, "cycles")
    # print(map_test_circuit.draw(style="text"))
    # accumulate result
    print("----")

    file_op_type = "a"
    global first_run
    if first_run:
        file_op_type = "w"
    first_run = False

    with open(
            "_private_data/BNTF/_{}_{}.csv".format(name_end,
                                                   qubits[nr_qubits],
                                                   ),
            file_op_type) as csvFile:
        writer = csv.writer(csvFile)
        writer.writerow([trail, "k7m", optimal_depth, depth_result, execution_time])

    return optimal_depth, depth_result, execution_time, init_time
Example #8
0
class ChainLayout(AnalysisPass):
    """
    Maps the qubits in the coupling map to a nearest-neighbor sequence of qubits,
    called *chain*, to be used as an initial layout.
    Sometimes not all qubits in a device can be arranged in a chain.
    If necessary, such outliers will be inserted in the chain after one of their neighbors.
    """
    def __init__(self, coupling_map, backend_prop=None, readout=False):
        """ChainLayout initializer.

        Args:
            coupling_map (CouplingMap or list): directed graph representing a coupling chain.
            backend_prop (BackendProperties): backend properties object.
        Raises:
            TranspilerError: if invalid options.
        """
        super().__init__()
        if isinstance(coupling_map, list):
            self.coupling_map = CouplingMap(coupling_map)
        elif isinstance(coupling_map, CouplingMap):
            self.coupling_map = coupling_map
        else:
            raise TranspilerError('Coupling map of type %s is not valid' %
                                  coupling_map.__class__)

        self.coupling_graph = self.coupling_map.graph.to_undirected()

        self.backend_prop = backend_prop
        # collect cx reliability data
        if self.backend_prop is not None:
            if readout:
                self.readout_reliability = dict()
                i = 0
                for q in backend_prop.qubits:
                    for info in q:
                        if info.name == 'readout_error':
                            self.readout_reliability[i] = 1.0 - info.value
                            i += 1

            self.cx_reliab = dict()
            for ginfo in self.backend_prop.gates:
                if ginfo.gate == 'cx':
                    for item in ginfo.parameters:
                        if item.name == 'gate_error':
                            g_reliab = max(1.0 - item.value, 10**(-10))
                            break
                        else:
                            g_reliab = 1.0
                    self.cx_reliab[(ginfo.qubits[0],
                                    ginfo.qubits[1])] = g_reliab
                    self.cx_reliab[(ginfo.qubits[1],
                                    ginfo.qubits[0])] = g_reliab
                    if readout:
                        qubits_readout_reliab = self.readout_reliability[
                            ginfo.qubits[0]] * self.readout_reliability[
                                ginfo.qubits[1]]
                        self.cx_reliab[(
                            ginfo.qubits[0],
                            ginfo.qubits[1])] *= qubits_readout_reliab
                        self.cx_reliab[(
                            ginfo.qubits[1],
                            ginfo.qubits[0])] *= qubits_readout_reliab

    def run(self, dag):
        """Sets the layout property set.

        Args:
            dag (DAGCircuit): DAG to find layout for.
        Raises:
            TranspilerError: if dag wider than the coupling_map.
        """

        num_dag_qubits = sum([qreg.size for qreg in dag.qregs.values()])
        if num_dag_qubits > self.coupling_map.size():
            raise TranspilerError('Number of qubits greater than device.')
        # get the chain of qubits as list of integers
        chain = self.chain(num_dag_qubits)
        logger.info('Chain: %s' % str(chain))
        layout = Layout()
        chain_iter = 0
        # produce a layout from the chain
        for qreg in dag.qregs.values():
            for i in range(qreg.size):
                layout[qreg[i]] = chain[chain_iter]
                chain_iter += 1
        self.property_set['layout'] = layout
        logger.info(self.property_set['layout'])

    def chain(self, num_qubits=None):
        """Finds a chain  of qubits such that qubit *i* has a connection
        with qubits *(i-1)* and *(i+1)* in the coupling chain.
        Relies on best_subset() to select a subset of qubits with high cx reliability.
        Sometimes not all qubits in a device can be arranged in a chain.
        If necessary, such outliers will be inserted in the chain after one of their neighbors.

        Args:
            num_qubits (int): number of virtual qubits,
                defaults to the number of qubits of the coupling chain.
        Raises:
            TranspilerError: if invalid options
        """

        if num_qubits is None:
            num_qubits = self.coupling_map.size()
        if num_qubits > self.coupling_map.size():
            raise TranspilerError('Number of qubits greater than device.')

        current = 0
        full_map = [current]
        isolated = []
        isolated_with_data = []
        explored = set()
        explored.add(current)

        last_back_step = None
        # loop over the coupling map until all qubits no more qubits
        # can be connected to the chain
        while True:
            neighbors = []
            no_neighbors = True
            for n in self.coupling_graph[current].keys():
                if n not in explored:
                    if self.check_isolated_not_last(n, explored):
                        if self.backend_prop is None:
                            isolated_with_data.append((current, n))
                        else:
                            isolated_with_data.append(
                                (current, n, self.cx_reliab[(current, n)]))
                        isolated.append(n)
                        explored.add(n)
                    no_neighbors = False
                    neighbors.append(n)
            logger.debug('Neighbors: %s' % str(neighbors))
            # try to select next qubit from neighbors of last connected qubit
            if no_neighbors is False:
                if current + 1 in neighbors:
                    next = current + 1
                else:
                    next = min(neighbors)
            else:
                # if no neighbors are found, go back the chain until a new neighbor is found
                # and restart the loop from there
                if self.backend_prop is None:
                    isolated_with_data.append((full_map[-2], current))
                else:
                    isolated_with_data.append(
                        (full_map[-2], current, self.cx_reliab[(full_map[-2],
                                                                current)]))
                isolated.append(current)
                full_map.remove(current)
                current = full_map[-1]
                logger.debug('last back step: %s' % str(last_back_step))
                if current != last_back_step:
                    last_back_step = current
                else:
                    break
                continue

            explored.add(next)
            current = next
            full_map.append(next)

            logger.debug('Full chain: %s' % str(full_map))
            logger.debug('Explored: %s' % str(explored))
            logger.debug('Isolated: %s' % str(isolated_with_data))

            # check that there are still qubits to explore
            if len(explored) < self.coupling_map.size() - 1:
                neighbors1 = []
                for n1 in self.coupling_graph[next].keys():
                    if n1 not in explored:
                        neighbors1.append(n1)

                # check that the selected qubit does not lead to a dead end
                for n1 in neighbors1:
                    to_remove = True
                    for n2 in self.coupling_graph[n1].keys():
                        if n2 not in explored or n2 == next:
                            to_remove = False
                    if to_remove is True:
                        explored.add(n1)
                        if self.backend_prop is None:
                            isolated_with_data.append((next, n1))
                        else:
                            isolated_with_data.append(
                                (next, n1, self.cx_reliab[(next, n1)]))
                        isolated.append(n1)

            # break the loop when all qubits have been explored
            if len(explored) == self.coupling_map.size():
                # if enough qubits have been connected,
                # return a subset with high cx reliability
                if len(full_map) >= num_qubits:
                    return self.best_subset(full_map, num_qubits)
                break

        # check for isolated qubits
        for q in range(self.coupling_map.size()):
            if q not in explored and q not in isolated:
                for i in isolated:
                    if q in self.coupling_graph[i].keys():
                        if self.backend_prop is None:
                            isolated_with_data.append((i, q))
                        else:
                            isolated_with_data.append(
                                (i, q, self.cx_reliab[(i, q)]))
                        isolated.append(q)
                        explored.add(q)
                        break
                if q not in isolated:
                    for n in self.coupling_graph[q].keys():
                        if n in full_map:
                            if self.backend_prop is None:
                                isolated_with_data.append((n, q))
                            else:
                                isolated_with_data.append(
                                    (n, q, self.cx_reliab[(n, q)]))
                            isolated.append(q)
                            explored.add(q)
                            break

        # if the chain is not long enough, add the isolated qubits
        logger.debug('Searching for isolated')
        remaining = num_qubits - len(full_map)
        if remaining > 0:
            if self.backend_prop is not None:
                isolated_with_data = sorted(isolated_with_data,
                                            key=lambda x: x[2],
                                            reverse=True)
            while remaining > 0:
                for next in isolated_with_data:
                    if next[0] in full_map:
                        logger.debug(next)
                        full_map.insert(full_map.index(next[0]) + 1, next[1])
                        isolated_with_data.remove(next)
                        isolated.remove(next[1])
                        remaining -= 1
                        break
        return full_map

    def check_isolated_not_last(self, q, explored):
        isolated = True
        for n in self.coupling_graph[q].keys():
            if n not in explored:
                isolated = False
        return (len(explored) >= self.coupling_map.size() - 2
                and isolated) or not isolated

    def best_subset(self, chain, num_qubits):
        """Selects from the chain a subset of qubits with high cx reliability.

        Args:
            chain (list): a chain of qubits.
            num_qubits (int): dimension of the subset.

        Returns:
            best_subset (list): subset with high cx reliability.
        """
        if self.backend_prop is None:
            best_reliab = float('inf')
        else:
            best_reliab = 0
        best = None
        if len(chain) - num_qubits == 0:
            return chain
        # use a moving window over the chain to select a subset with high cx reliability
        # if no backend information are provided, use the distance between qubits as a metric
        for offset in range(len(chain) - num_qubits):
            sub_set = chain[offset:offset + num_qubits]
            if self.backend_prop is None:
                tot_reliab = 0
            else:
                tot_reliab = 1
            for q in range(len(sub_set) - 1):
                if sub_set[q + 1] not in self.coupling_graph[q].keys():
                    path = shortest_path(self.coupling_graph,
                                         source=sub_set[q],
                                         target=sub_set[q + 1])
                    for p in range(len(path) - 1):
                        if self.backend_prop is None:
                            tot_reliab += 1
                        else:
                            tot_reliab *= self.cx_reliab[(path[p],
                                                          path[p + 1])]**3
                else:
                    if self.backend_prop is None:
                        tot_reliab += 1
                    else:
                        tot_reliab *= self.cx_reliab[(sub_set[q],
                                                      sub_set[q + 1])]
            if self.backend_prop is None:
                if tot_reliab < best_reliab:
                    best_reliab = tot_reliab
                    best = sub_set
            else:
                if tot_reliab > best_reliab:
                    best_reliab = tot_reliab
                    best = sub_set
        return best
Example #9
0
def benchmark(depth, trail, varying_param):

    # qasm_file_name = "_private_benchmark/BNTF/16QBT_{:02}CYC_{}_{}.qasm".format(
    #     depth, gdv_name, trail)
    #
    # solution_file_name = "_private_benchmark/meta/16QBT_{:02}CYC_{}_{}_solution.csv".format(
    #     depth, gdv_name, trail)

    if gdv_name == "TFL":
        folder = "BNTF"
        depth_string = "{:02}".format(depth)
        name_end = "TFL"
        if nr_qubits == 54:
            name_end = "QSE"

    elif gdv_name == "QSE":
        folder = "BSS"
        depth_string = "{:03}".format(depth)
        name_end = "QSE"

    # if nr_qubits==54:
    #     gdv_name = "QSE"

    qasm_file_name = "_private_benchmark/{}/{}QBT_{}CYC_{}_{}.qasm".format(
        folder, nr_qubits, depth_string, name_end, trail)

    solution_file_name = "_private_benchmark/meta/{}QBT_{}CYC_{}_{}_solution.csv".format(
        nr_qubits, depth_string, name_end, trail)

    # print("qiskit", depth)
    # input qasm file as circuit
    test_circuit = qiskit.QuantumCircuit.from_qasm_file(qasm_file_name)
    """
        Construct the optimal initial mapping
    """
    qiskit_layout_dict = dict()
    original_nodes = list()
    with open(solution_file_name, 'r') as csvfile:
        for original_node in csv.reader(csvfile, delimiter=','):
            original_nodes.append(literal_eval(original_node[0]))
    csvfile.close()
    print(original_nodes)

    for i in range(len(original_nodes)):
        qiskit_layout_dict[test_circuit.qregs[0][i]] = original_nodes[i]
    # construct passes that use the optimal initial mapping and BasicSwap
    # however, no swapping gates should be ever necessary
    original_pm = PassManager()
    # print(original_nodes)
    qiskit_coupling_map = CouplingMap(
        couplinglist=connection_list[qubits[nr_qubits]])
    optimal_layout = Layout()
    optimal_layout.from_dict(qiskit_layout_dict)
    original_pm.append([
        SetLayout(optimal_layout),
        ApplyLayout(),
        BasicSwap(qiskit_coupling_map)
    ])
    map_original_circuit = original_pm.run(test_circuit)
    optimal_depth = map_original_circuit.depth()
    print("optimal mapping: the circuit has", optimal_depth, "cycles")
    # print(map_original_circuit.draw(style="text"))
    # construct passes that use the DenseLayout+StochasticSwap without initial mapping
    """
       K7M 
    """
    gate_costs = {
        'id': 0,
        'u1': 0,
        'measure': 0,
        'reset': 0,
        'barrier': 0,
        'u2': 1,
        'u3': 1,
        'U': 1,
        "ok": 0,
        # update the costs
        "rev_cnot": 4 * 1 + 10,  # 4 u2/hadamard + 1 cnot
        "swap": 3 * 10 + 4,  # 4 u2/hadamard + 3 cnot
        'seed': 19
    }  # pass the seed through gate costs

    parameters = {
        # maximum depth of the search tree
        # after this depth, the leafs are evaluated
        # and only the path with minimum cost is kept in the tree
        # thus, the tree is pruned
        "max_depth": test_circuit.n_qubits // 2,
        # "max_depth": test_circuit.n_qubits/4,

        # maximum number of children of a node
        # "max_children": qiskit_coupling_map.size(),
        "max_children": 2,

        # the first number_of_qubits * this factor the search maximises the cost
        # afterwards it minimises it
        "opt_max_t_min": False,
        "qubit_increase_factor": 3,
        "option_skip_cx": False,
        "penalty_skip_cx": 20,
        "opt_div_by_act": False,

        # later changes in the mapping should not affect
        # the initial mapping of the circuit
        "opt_att": True,
        # b \in [0, 10]
        "att_b": -10,
        # c \in [0, 1]
        "att_c": 1,
        "div_dist": 2,
        "cx": 0.01
    }

    parameters_string = str(parameters)

    # the number of qubits in the device
    parameters["nisq_qubits"] = qiskit_coupling_map.size()
    # Add the gate costs
    parameters["gate_costs"] = gate_costs
    # Should the initial mapping be chosen random?
    parameters["initial_map"] = K7MInitialMapping.HEURISTIC
    parameters["unidirectional_coupling"] = False
    parameters["dry_run"] = False

    k7mcomp = K7MCompiler(connection_list[qubits[nr_qubits]], parameters)

    execution_time = time.time()
    map_test_circuit, init_time = k7mcomp.run(test_circuit)
    execution_time = time.time() - execution_time

    # print(map_test_circuit.draw(output="text", fold=-1))
    # tmp_circuit = map_test_circuit.decompose()
    tmp_circuit = map_test_circuit
    # print(tmp_circuit.draw(output="text", fold=-1))
    # tmp_circuit = qiskit_to_tk(map_test_circuit)
    # Transform.RebaseToQiskit().DecomposeSWAPtoCX().apply(tmp_circuit)
    depth_result = tmp_circuit.depth()

    print("k7m mapping: the circuit has", depth_result, "cycles")
    # print(map_test_circuit.draw(style="text"))
    # accumulate result
    print("----")

    file_op_type = "a"
    global first_run
    if first_run:
        file_op_type = "w"
    first_run = False

    with open(
            "_private_data/BNTF/_{}_{}_{}.csv".format(name_end,
                                                      qubits[nr_qubits],
                                                      parameters_string),
            file_op_type) as csvFile:
        writer = csv.writer(csvFile)
        writer.writerow(
            [trail, "k7m", optimal_depth, depth_result, execution_time])

    return optimal_depth, depth_result, execution_time, init_time