def test_dag_to_json(self): """Test DagUnroller with JSON backend.""" ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend()).execute() dag_unroller = DagUnroller(dag_circuit, JsonBackend()) json_circuit = dag_unroller.execute() expected_result = { 'operations': [ {'qubits': [5], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [5, 2]}, {'clbits': [2], 'name': 'measure', 'qubits': [2]}, {'qubits': [4], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [4, 1]}, {'clbits': [1], 'name': 'measure', 'qubits': [1]}, {'qubits': [3], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [3, 0]}, {'name': 'barrier', 'qubits': [3, 4, 5]}, {'clbits': [5], 'name': 'measure', 'qubits': [5]}, {'clbits': [4], 'name': 'measure', 'qubits': [4]}, {'clbits': [3], 'name': 'measure', 'qubits': [3]}, {'clbits': [0], 'name': 'measure', 'qubits': [0]} ], 'header': { 'memory_slots': 6, 'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]], 'n_qubits': 6, 'clbit_labels': [['d', 3], ['c', 3]] } } self.assertEqual(json_circuit, expected_result)
def test_execute(self): ast = qasm.Qasm( filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend()).execute() dag_unroller = DagUnroller(dag_circuit, DAGBackend()) unroller_dag_circuit = dag_unroller.execute() expected_result = """\ OPENQASM 2.0; qreg q[3]; qreg r[3]; creg c[3]; creg d[3]; U(0.5*pi,0,pi) q[2]; CX q[2],r[2]; measure r[2] -> d[2]; U(0.5*pi,0,pi) q[1]; CX q[1],r[1]; measure r[1] -> d[1]; U(0.5*pi,0,pi) q[0]; CX q[0],r[0]; measure r[0] -> d[0]; barrier q[0],q[1],q[2]; measure q[2] -> c[2]; measure q[1] -> c[1]; measure q[0] -> c[0]; """ self.assertEqual(unroller_dag_circuit.qasm(), expected_result)
def test_execute(self): ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend()).execute() dag_unroller = DagUnroller(dag_circuit, DAGBackend()) unroller_dag_circuit = dag_unroller.execute() expected_result = """\ OPENQASM 2.0; qreg q[3]; qreg r[3]; creg c[3]; creg d[3]; U(0.5*pi,0,pi) q[2]; CX q[2],r[2]; measure r[2] -> d[2]; U(0.5*pi,0,pi) q[1]; CX q[1],r[1]; measure r[1] -> d[1]; U(0.5*pi,0,pi) q[0]; CX q[0],r[0]; measure r[0] -> d[0]; barrier q[0],q[1],q[2]; measure q[2] -> c[2]; measure q[1] -> c[1]; measure q[0] -> c[0]; """ self.assertEqual(unroller_dag_circuit.qasm(), expected_result)
def test_execute_with_basis(self): ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend(["cx", "u1", "u2", "u3"])).execute() dag_unroller = DagUnroller(dag_circuit, DAGBackend(["cx", "u1", "u2", "u3"])) unroller_dag_circuit = dag_unroller.execute() expected_result = """\ OPENQASM 2.0; qreg q[3]; qreg r[3]; creg c[3]; creg d[3]; gate u2(phi,lambda) q { U((pi/2),phi,lambda) q; } gate cx c,t { CX c,t; } u2(0,pi) q[2]; cx q[2],r[2]; measure r[2] -> d[2]; u2(0,pi) q[1]; cx q[1],r[1]; measure r[1] -> d[1]; u2(0,pi) q[0]; cx q[0],r[0]; measure r[0] -> d[0]; barrier q[0],q[1],q[2]; measure q[2] -> c[2]; measure q[1] -> c[1]; measure q[0] -> c[0]; """ self.assertEqual(unroller_dag_circuit.qasm(), expected_result)
def test_from_dag_to_json_with_basis(self): ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend(["cx", "u1", "u2", "u3"])).execute() dag_unroller = DagUnroller(dag_circuit, JsonBackend(["cx", "u1", "u2", "u3"])) json_circuit = dag_unroller.execute() expected_result = { 'operations': [ {'qubits': [5], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [5, 2], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [2], 'clbits': [2], 'name': 'measure'}, {'qubits': [4], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [4, 1], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [1], 'clbits': [1], 'name': 'measure'}, {'qubits': [3], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [3, 0], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [3, 4, 5], 'name': 'barrier'}, {'qubits': [5], 'clbits': [5], 'name': 'measure'}, {'qubits': [4], 'clbits': [4], 'name': 'measure'}, {'qubits': [3], 'clbits': [3], 'name': 'measure'}, {'qubits': [0], 'clbits': [0], 'name': 'measure'} ], 'header': { 'clbit_labels': [['d', 3], ['c', 3]], 'number_of_qubits': 6, 'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]], 'number_of_clbits': 6 } } self.assertEqual(json_circuit, expected_result)
def test_from_dag_to_json(self): ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend()).execute() dag_unroller = DagUnroller(dag_circuit, JsonBackend()) json_circuit = dag_unroller.execute() expected_result = { 'operations': [ {'qubits': [5], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [5, 2]}, {'clbits': [2], 'name': 'measure', 'qubits': [2]}, {'qubits': [4], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [4, 1]}, {'clbits': [1], 'name': 'measure', 'qubits': [1]}, {'qubits': [3], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]}, {'name': 'CX', 'qubits': [3, 0]}, {'name': 'barrier', 'qubits': [3, 4, 5]}, {'clbits': [5], 'name': 'measure', 'qubits': [5]}, {'clbits': [4], 'name': 'measure', 'qubits': [4]}, {'clbits': [3], 'name': 'measure', 'qubits': [3]}, {'clbits': [0], 'name': 'measure', 'qubits': [0]} ], 'header': { 'number_of_clbits': 6, 'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]], 'number_of_qubits': 6, 'clbit_labels': [['d', 3], ['c', 3]] } } self.assertEqual(json_circuit, expected_result)
def test_from_dag_to_json_with_basis(self): ast = qasm.Qasm( filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend(["cx", "u1", "u2", "u3"])).execute() dag_unroller = DagUnroller(dag_circuit, JsonBackend(["cx", "u1", "u2", "u3"])) json_circuit = dag_unroller.execute() expected_result = \ {'operations': [{'qubits': [5], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [5, 2], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [2], 'clbits': [2], 'name': 'measure'}, {'qubits': [4], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [4, 1], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [1], 'clbits': [1], 'name': 'measure'}, {'qubits': [3], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793], 'name': 'u2'}, {'qubits': [3, 0], 'texparams': [], 'params': [], 'name': 'cx'}, {'qubits': [3, 4, 5], 'name': 'barrier'}, {'qubits': [5], 'clbits': [5], 'name': 'measure'}, {'qubits': [4], 'clbits': [4], 'name': 'measure'}, {'qubits': [3], 'clbits': [3], 'name': 'measure'}, {'qubits': [0], 'clbits': [0], 'name': 'measure'}], 'header': {'clbit_labels': [['d', 3], ['c', 3]], 'number_of_qubits': 6, 'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]], 'number_of_clbits': 6 } } self.assertEqual(json_circuit, expected_result)
def test_execute_with_basis(self): """Test unroller.execute() to a gate basis.""" ast = qasm.Qasm( filename=self._get_resource_path('qasm/example.qasm')).parse() dag_circuit = Unroller(ast, DAGBackend(["cx", "u1", "u2", "u3"])).execute() dag_unroller = DagUnroller(dag_circuit, DAGBackend(["cx", "u1", "u2", "u3"])) unroller_dag_circuit = dag_unroller.execute() expected_result = """\ OPENQASM 2.0; qreg q[3]; qreg r[3]; creg c[3]; creg d[3]; gate u2(phi,lambda) q { U((pi/2),phi,lambda) q; } gate cx c,t { CX c,t; } u2(0,pi) q[2]; cx q[2],r[2]; measure r[2] -> d[2]; u2(0,pi) q[1]; cx q[1],r[1]; measure r[1] -> d[1]; u2(0,pi) q[0]; cx q[0],r[0]; measure r[0] -> d[0]; barrier q[0],q[1],q[2]; measure q[2] -> c[2]; measure q[1] -> c[1]; measure q[0] -> c[0]; """ self.assertEqual(unroller_dag_circuit.qasm(), expected_result)
def transpile(dag, basis_gates='u1,u2,u3,cx,id', coupling_map=None, initial_layout=None, get_layout=False, format='dag', seed=None, pass_manager=None): """Transform a dag circuit into another dag circuit (transpile), through consecutive passes on the dag. Args: dag (DAGCircuit): dag circuit to transform via transpilation basis_gates (str): a comma separated string for the target basis gates coupling_map (list): A graph of coupling:: [ [control0(int), target0(int)], [control1(int), target1(int)], ] eg. [[0, 2], [1, 2], [1, 3], [3, 4]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", start(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } get_layout (bool): flag for returning the final layout after mapping format (str): The target format of the compilation: {'dag', 'json', 'qasm'} seed (int): random seed for the swap mapper pass_manager (PassManager): pass manager instance for the transpilation process If None, a default set of passes are run. Otherwise, the passes defined in it will run. If contains no passes in it, no dag transformations occur. Returns: DAGCircuit: transformed dag DAGCircuit, dict: transformed dag along with the final layout on backend qubits Raises: TranspilerError: if the format is not valid. """ # TODO: `basis_gates` will be removed after we have the unroller pass. # TODO: `coupling_map`, `initial_layout`, `get_layout`, `seed` removed after mapper pass. # TODO: move this to the mapper pass num_qubits = sum(dag.qregs.values()) if num_qubits == 1 or coupling_map == "all-to-all": coupling_map = None final_layout = None if pass_manager: # run the passes specified by the pass manager # TODO return the property set too. See #1086 dag = pass_manager.run_passes(dag) else: # default set of passes # TODO: move each step here to a pass, and use a default passmanager below basis = basis_gates.split(',') if basis_gates else [] dag_unroller = DagUnroller(dag, DAGBackend(basis)) dag = dag_unroller.expand_gates() # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", dag.property_summary()) # Insert swap gates coupling = Coupling(coupling_list2dict(coupling_map)) removed_meas = remove_last_measurements(dag) logger.info("measurements moved: %s", removed_meas) logger.info("initial layout: %s", initial_layout) dag, final_layout, last_layout = swap_mapper(dag, coupling, initial_layout, trials=20, seed=seed) logger.info("final layout: %s", final_layout) # Expand swaps dag_unroller = DagUnroller(dag, DAGBackend(basis)) dag = dag_unroller.expand_gates() # Change cx directions dag = direction_mapper(dag, coupling) # Simplify cx gates cx_cancellation(dag) # Simplify single qubit gates dag = optimize_1q_gates(dag) return_last_measurements(dag, removed_meas, last_layout) logger.info("post-mapping properties: %s", dag.property_summary()) # choose output format # TODO: do we need all of these formats, or just the dag? if format == 'dag': compiled_circuit = dag elif format == 'json': # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list dag_unroller = DagUnroller(dag, JsonBackend(dag.basis)) compiled_circuit = dag_unroller.execute() elif format == 'qasm': compiled_circuit = dag.qasm() else: raise TranspilerError('unrecognized circuit format') if get_layout: return compiled_circuit, final_layout return compiled_circuit
def transpile(dag_circuit, basis_gates='u1,u2,u3,cx,id', coupling_map=None, initial_layout=None, get_layout=False, format='dag', seed=None, pass_manager=None): """Transform a dag circuit into another dag circuit (transpile), through consecutive passes on the dag. Args: dag_circuit (DAGCircuit): dag circuit to transform via transpilation basis_gates (str): a comma seperated string for the target basis gates coupling_map (list): A graph of coupling:: [ [control0(int), target0(int)], [control1(int), target1(int)], ] eg. [[0, 2], [1, 2], [1, 3], [3, 4]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", start(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } get_layout (bool): flag for returning the layout format (str): The target format of the compilation: {'dag', 'json', 'qasm'} seed (int): random seed for simulators pass_manager (PassManager): pass manager instance for the tranpilation process If None, a default set of passes are run. Otherwise, the passes defined in it will run. If contains no passes in it, no dag transformations occur. Returns: object: If get_layout == False, the compiled circuit in the specified format. If get_layout == True, a tuple is returned, with the second element being the layout. Raises: TranspilerError: if the format is not valid. """ final_layout = None if pass_manager: # run the passes specified by the pass manager for pass_ in pass_manager.passes(): pass_.run(dag_circuit) else: # default set of passes # TODO: move each step here to a pass, and use a default passmanager below basis = basis_gates.split(',') if basis_gates else [] dag_unroller = DagUnroller(dag_circuit, DAGBackend(basis)) dag_circuit = dag_unroller.expand_gates() # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", dag_circuit.property_summary()) # Insert swap gates coupling = Coupling(coupling_list2dict(coupling_map)) logger.info("initial layout: %s", initial_layout) dag_circuit, final_layout = swap_mapper(dag_circuit, coupling, initial_layout, trials=20, seed=seed) logger.info("final layout: %s", final_layout) # Expand swaps dag_unroller = DagUnroller(dag_circuit, DAGBackend(basis)) dag_circuit = dag_unroller.expand_gates() # Change cx directions dag_circuit = direction_mapper(dag_circuit, coupling) # Simplify cx gates cx_cancellation(dag_circuit) # Simplify single qubit gates dag_circuit = optimize_1q_gates(dag_circuit) logger.info("post-mapping properties: %s", dag_circuit.property_summary()) # choose output format # TODO: do we need all of these formats, or just the dag? if format == 'dag': compiled_circuit = dag_circuit elif format == 'json': # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list dag_unroller = DagUnroller(dag_circuit, JsonBackend(dag_circuit.basis)) compiled_circuit = dag_unroller.execute() elif format == 'qasm': compiled_circuit = dag_circuit.qasm() else: raise TranspilerError('unrecognized circuit format') if get_layout: return compiled_circuit, final_layout return compiled_circuit
def compile(quantum_circuit, basis_gates='u1,u2,u3,cx,id', coupling_map=None, initial_layout=None, get_layout=False, format='dag'): """Compile the circuit. This builds the internal "to execute" list which is list of quantum circuits to run on different backends. Args: quantum_circuit (QuantumCircuit): circuit to compile basis_gates (str): a comma seperated string and are the base gates, which by default are: u1,u2,u3,cx,id coupling_map (list): A graph of coupling:: [ [control0(int), target0(int)], [control1(int), target1(int)], ] eg. [[0, 2], [1, 2], [1, 3], [3, 4]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", start(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } get_layout (bool): flag for returning the layout. format (str): The target format of the compilation: {'dag', 'json', 'qasm'} Returns: object: If get_layout == False, the compiled circuit in the specified format. If get_layout == True, a tuple is returned, with the second element being the layout. Raises: QISKitCompilerError: if the format is not valid. """ compiled_dag_circuit = DAGCircuit.fromQuantumCircuit(quantum_circuit) basis = basis_gates.split(',') if basis_gates else [] dag_unroller = DagUnroller(compiled_dag_circuit, DAGBackend(basis)) compiled_dag_circuit = dag_unroller.expand_gates() final_layout = None # if a coupling map is given compile to the map if coupling_map: logger.info("pre-mapping properties: %s", compiled_dag_circuit.property_summary()) # Insert swap gates coupling = mapper.Coupling(mapper.coupling_list2dict(coupling_map)) logger.info("initial layout: %s", initial_layout) compiled_dag_circuit, final_layout = mapper.swap_mapper( compiled_dag_circuit, coupling, initial_layout, trials=20, seed=13) logger.info("final layout: %s", final_layout) # Expand swaps dag_unroller = DagUnroller(compiled_dag_circuit, DAGBackend(basis)) compiled_dag_circuit = dag_unroller.expand_gates() # Change cx directions compiled_dag_circuit = mapper.direction_mapper(compiled_dag_circuit, coupling) # Simplify cx gates mapper.cx_cancellation(compiled_dag_circuit) # Simplify single qubit gates compiled_dag_circuit = mapper.optimize_1q_gates(compiled_dag_circuit) logger.info("post-mapping properties: %s", compiled_dag_circuit.property_summary()) # choose output format if format == 'dag': compiled_circuit = compiled_dag_circuit elif format == 'json': dag_unroller = DagUnroller(compiled_dag_circuit, JsonBackend(list(compiled_dag_circuit.basis.keys()))) compiled_circuit = dag_unroller.execute() elif format == 'qasm': compiled_circuit = compiled_dag_circuit.qasm() else: raise QISKitCompilerError('unrecognized circuit format') if get_layout: return compiled_circuit, final_layout return compiled_circuit