mirror of https://github.com/Qiskit/qiskit.git
Linter, PEP8 and license header fixes
Fix the warnings raised by pylint and pycodestyle, and add missing license headers.
This commit is contained in:
parent
02496b5155
commit
2c39096cac
|
@ -1,23 +1,43 @@
|
|||
from IBMQuantumExperience import RegisterSizeError
|
||||
|
||||
from ._qiskiterror import QISKitError
|
||||
from ._classicalregister import ClassicalRegister
|
||||
from ._quantumregister import QuantumRegister
|
||||
from ._quantumcircuit import QuantumCircuit
|
||||
from ._gate import Gate
|
||||
from ._compositegate import CompositeGate
|
||||
from ._instruction import Instruction
|
||||
from ._instructionset import InstructionSet
|
||||
from ._reset import Reset
|
||||
from ._measure import Measure
|
||||
import qiskit.extensions.standard
|
||||
import qiskit.extensions.quantum_initializer
|
||||
from ._jobprocessor import JobProcessor
|
||||
from ._quantumjob import QuantumJob
|
||||
from ._quantumprogram import QuantumProgram
|
||||
from ._result import Result
|
||||
from ._util import _check_ibmqe_version
|
||||
|
||||
__version__ = '0.4.0'
|
||||
|
||||
_check_ibmqe_version()
|
||||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=wrong-import-order
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Main QISKit public functionality."""
|
||||
from IBMQuantumExperience import RegisterSizeError
|
||||
|
||||
from ._qiskiterror import QISKitError
|
||||
from ._classicalregister import ClassicalRegister
|
||||
from ._quantumregister import QuantumRegister
|
||||
from ._quantumcircuit import QuantumCircuit
|
||||
from ._gate import Gate
|
||||
from ._compositegate import CompositeGate
|
||||
from ._instruction import Instruction
|
||||
from ._instructionset import InstructionSet
|
||||
from ._reset import Reset
|
||||
from ._measure import Measure
|
||||
# These two qiskit.extensions imports needs to be placed here.
|
||||
import qiskit.extensions.standard
|
||||
import qiskit.extensions.quantum_initializer
|
||||
from ._jobprocessor import JobProcessor
|
||||
from ._quantumjob import QuantumJob
|
||||
from ._quantumprogram import QuantumProgram
|
||||
from ._result import Result
|
||||
from ._util import _check_ibmqe_version
|
||||
|
||||
__version__ = '0.4.0'
|
||||
|
||||
_check_ibmqe_version()
|
||||
|
|
|
@ -102,7 +102,7 @@ class CompositeGate(Gate):
|
|||
self.data = [gate.q_if(qregs) for gate in self.data]
|
||||
return self
|
||||
|
||||
def c_if(self, c, val):
|
||||
def c_if(self, classical, val):
|
||||
"""Add classical control register."""
|
||||
self.data = [gate.c_if(c, val) for gate in self.data]
|
||||
self.data = [gate.c_if(classical, val) for gate in self.data]
|
||||
return self
|
||||
|
|
|
@ -46,4 +46,5 @@ class Gate(Instruction):
|
|||
|
||||
def q_if(self, *qregs):
|
||||
"""Add controls to this gate."""
|
||||
# pylint: disable=unused-argument
|
||||
raise QISKitError("control not implemented")
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
"""
|
||||
Quantum computer instruction.
|
||||
"""
|
||||
from ._register import Register
|
||||
from ._qiskiterror import QISKitError
|
||||
from sympy import Number, Basic
|
||||
|
||||
from ._qiskiterror import QISKitError
|
||||
from ._register import Register
|
||||
|
||||
|
||||
class Instruction(object):
|
||||
"""Generic quantum computer instruction."""
|
||||
|
@ -39,13 +40,13 @@ class Instruction(object):
|
|||
raise QISKitError("argument not (Register, int) tuple")
|
||||
self.name = name
|
||||
self.param = []
|
||||
for p in param:
|
||||
if not isinstance(p, (Basic, complex)):
|
||||
for single_param in param:
|
||||
if not isinstance(single_param, (Basic, complex)):
|
||||
# If the item in param is not symbolic and not complex (used
|
||||
# by InitializeGate), make it symbolic.
|
||||
self.param.append(Number(p))
|
||||
self.param.append(Number(single_param))
|
||||
else:
|
||||
self.param.append(p)
|
||||
self.param.append(single_param)
|
||||
self.arg = arg
|
||||
self.control = None # tuple (ClassicalRegister, int) for "if"
|
||||
self.circuit = circuit
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=redefined-builtin
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Tools for compiling Quantum Programs."""
|
||||
import logging
|
||||
|
||||
import qiskit.qasm as qasm
|
||||
|
@ -47,11 +66,17 @@ def compile(qasm_circuit, basis_gates='u1,u2,u3,cx,id', coupling_map=None,
|
|||
("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:
|
||||
Compiled circuit
|
||||
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 = _unroller_code(qasm_circuit,
|
||||
basis_gates=basis_gates)
|
||||
|
@ -84,7 +109,7 @@ def compile(qasm_circuit, basis_gates='u1,u2,u3,cx,id', coupling_map=None,
|
|||
elif format == 'qasm':
|
||||
compiled_circuit = compiled_dag_circuit.qasm()
|
||||
else:
|
||||
raise QiskitCompilerError('unrecognized circuit format')
|
||||
raise QISKitCompilerError('unrecognized circuit format')
|
||||
|
||||
if get_layout:
|
||||
return compiled_circuit, final_layout
|
||||
|
@ -98,12 +123,11 @@ def _unroller_code(qasm_circuit, basis_gates=None):
|
|||
This is an internal function.
|
||||
|
||||
Args:
|
||||
qasm_circuit: a circuit representation as qasm text.
|
||||
qasm_circuit (str): a circuit representation as qasm text.
|
||||
basis_gates (str): a comma seperated string and are the base gates,
|
||||
which by default are: u1,u2,u3,cx,id
|
||||
Return:
|
||||
dag_ciruit (dag object): a dag representation of the circuit
|
||||
unrolled to basis gates
|
||||
object: a dag representation of the circuit unrolled to basis gates
|
||||
"""
|
||||
if not basis_gates:
|
||||
basis_gates = "u1,u2,u3,cx,id" # QE target basis
|
||||
|
@ -122,7 +146,7 @@ def load_unroll_qasm_file(filename, basis_gates='u1,u2,u3,cx,id'):
|
|||
filename (str): a string for the filename including its location.
|
||||
basis_gates (str): basis to unroll circuit to.
|
||||
Returns:
|
||||
Returns a unrolled QuantumCircuit object
|
||||
object: Returns a unrolled QuantumCircuit object
|
||||
"""
|
||||
# create Program object Node (AST)
|
||||
program_node_circuit = qasm.Qasm(filename=filename).parse()
|
||||
|
@ -140,12 +164,12 @@ def dag2json(dag_circuit, basis_gates='u1,u2,u3,cx,id'):
|
|||
function.
|
||||
|
||||
Args:
|
||||
dag_ciruit (dag object): a dag representation of the circuit.
|
||||
dag_circuit (QuantumCircuit): a dag representation of the circuit.
|
||||
basis_gates (str): a comma seperated string and are the base gates,
|
||||
which by default are: u1,u2,u3,cx,id
|
||||
|
||||
Returns:
|
||||
the json version of the dag
|
||||
json: the json version of the dag
|
||||
"""
|
||||
# TODO: Jay: I think this needs to become a method like .qasm() for the DAG.
|
||||
try:
|
||||
|
@ -158,6 +182,7 @@ def dag2json(dag_circuit, basis_gates='u1,u2,u3,cx,id'):
|
|||
json_circuit = unroller.execute()
|
||||
return json_circuit
|
||||
|
||||
class QiskitCompilerError(QISKitError):
|
||||
|
||||
class QISKitCompilerError(QISKitError):
|
||||
"""Exceptions raised during compilation"""
|
||||
pass
|
||||
|
|
|
@ -176,6 +176,9 @@ class QuantumCircuit(object):
|
|||
def measure(self, qubit, cbit):
|
||||
"""Measure quantum bit into classical bit (tuples).
|
||||
|
||||
Returns:
|
||||
Gate: the attached measure gate.
|
||||
|
||||
Raises:
|
||||
QISKitError: if qubit is not in this circuit or bad format;
|
||||
if cbit is not in this circuit or not creg.
|
||||
|
|
|
@ -1,9 +1,27 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Quantum Job class"""
|
||||
import random
|
||||
import string
|
||||
from qiskit import _openquantumcompiler as openquantumcompiler
|
||||
import qiskit.backends as backends
|
||||
|
||||
|
||||
class QuantumJob():
|
||||
"""Creates a quantum circuit job
|
||||
|
||||
|
@ -14,54 +32,27 @@ class QuantumJob():
|
|||
# TODO We need to create more tests for checking all possible inputs.
|
||||
def __init__(self, circuits, backend='local_qasm_simulator',
|
||||
circuit_config=None, seed=None,
|
||||
resources={'max_credits':10, 'wait':5, 'timeout':120},
|
||||
resources=None,
|
||||
shots=1024, names=None,
|
||||
do_compile=False, preformatted=False):
|
||||
"""
|
||||
Args:
|
||||
circuits (QuantumCircuit | list(QuantumCircuit) | qobj):
|
||||
circuits (QuantumCircuit or list(QuantumCircuit)):
|
||||
QuantumCircuit or list of QuantumCircuit. If preformatted=True,
|
||||
this is a raw qobj.
|
||||
backend (str): The backend to run the circuit on.
|
||||
timeout (float): Timeout for job in seconds.
|
||||
circuit_config (dict): Circuit configuration.
|
||||
seed (int): The intial seed the simulatros use.
|
||||
resources (dict): Resource requirements of job.
|
||||
coupling_map (dict): A directed graph of coupling::
|
||||
|
||||
{
|
||||
control(int):
|
||||
[
|
||||
target1(int),
|
||||
target2(int),
|
||||
, ...
|
||||
],
|
||||
...
|
||||
}
|
||||
|
||||
eg. {0: [2], 1: [2], 3: [2]}
|
||||
|
||||
initial_layout (dict): A mapping of qubit to qubit::
|
||||
|
||||
{
|
||||
("q", strart(int)): ("q", final(int)),
|
||||
...
|
||||
}
|
||||
eg.
|
||||
{
|
||||
("q", 0): ("q", 0),
|
||||
("q", 1): ("q", 1),
|
||||
("q", 2): ("q", 2),
|
||||
("q", 3): ("q", 3)
|
||||
}
|
||||
shots (int): the number of shots
|
||||
circuit_type (str): "compiled_dag" or "uncompiled_dag" or
|
||||
"quantum_circuit"
|
||||
names (str | list(str)): names/ids for circuits
|
||||
preformated (bool): the objects in circuits are already compiled
|
||||
names (str or list(str)): names/ids for circuits
|
||||
do_compile (boolean): compile flag.
|
||||
preformatted (bool): the objects in circuits are already compiled
|
||||
and formatted (qasm for online, json for local). If true the
|
||||
parameters "names" and "circuit_config" must also be defined
|
||||
of the same length as "circuits".
|
||||
"""
|
||||
resources = resources or {'max_credits': 10, 'wait': 5, 'timeout': 120}
|
||||
if isinstance(circuits, list):
|
||||
self.circuits = circuits
|
||||
else:
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
@ -11,10 +14,11 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""
|
||||
Qasm Program Class
|
||||
"""
|
||||
# pylint: disable=line-too-long
|
||||
|
||||
import random
|
||||
import json
|
||||
import logging
|
||||
|
@ -193,7 +197,8 @@ class QuantumProgram(object):
|
|||
size (int): the size of the quantum register
|
||||
|
||||
Returns:
|
||||
QuantumRegister: internal reference to a quantum register in __quantum_registers
|
||||
QuantumRegister: internal reference to a quantum register in
|
||||
__quantum_registers
|
||||
|
||||
Raises:
|
||||
QISKitError: if the register already exists in the program.
|
||||
|
@ -272,7 +277,8 @@ class QuantumProgram(object):
|
|||
name (str): the name of the classical register
|
||||
size (int): the size of the classical register
|
||||
Returns:
|
||||
ClassicalRegister: internal reference to a classical register in __classical_registers
|
||||
ClassicalRegister: internal reference to a classical register
|
||||
in __classical_registers
|
||||
|
||||
Raises:
|
||||
QISKitError: if the register already exists in the program.
|
||||
|
@ -348,13 +354,14 @@ class QuantumProgram(object):
|
|||
|
||||
Args:
|
||||
name (str): the name of the circuit.
|
||||
qregisters (list(QuantumRegister)): is an Array of Quantum Registers by object
|
||||
reference
|
||||
cregisters (list(ClassicalRegister)): is an Array of Classical Registers by
|
||||
object reference
|
||||
qregisters (list(QuantumRegister)): is an Array of Quantum
|
||||
Registers by object reference
|
||||
cregisters (list(ClassicalRegister)): is an Array of Classical
|
||||
Registers by object reference
|
||||
|
||||
Returns:
|
||||
QuantumCircuit: A quantum circuit is created and added to the Quantum Program
|
||||
QuantumCircuit: A quantum circuit is created and added to the
|
||||
Quantum Program
|
||||
"""
|
||||
if not qregisters:
|
||||
qregisters = []
|
||||
|
@ -389,7 +396,8 @@ class QuantumProgram(object):
|
|||
|
||||
Args:
|
||||
name (str): the name of the circuit to add.
|
||||
quantum_circuit (QuantumCircuit): a quantum circuit to add to the program-name
|
||||
quantum_circuit (QuantumCircuit): a quantum circuit to add to the
|
||||
program-name
|
||||
"""
|
||||
for qname, qreg in quantum_circuit.get_qregs().items():
|
||||
self.create_quantum_register(qname, len(qreg))
|
||||
|
@ -418,7 +426,7 @@ class QuantumProgram(object):
|
|||
if not name:
|
||||
name = os.path.splitext(os.path.basename(qasm_file))[0]
|
||||
node_circuit = qasm.Qasm(filename=qasm_file).parse() # Node (AST)
|
||||
logger.info("circuit name: " + name)
|
||||
logger.info("circuit name: %s", name)
|
||||
logger.info("******************************")
|
||||
logger.info(node_circuit.qasm())
|
||||
# current method to turn it a DAG quantum circuit.
|
||||
|
@ -446,7 +454,7 @@ class QuantumProgram(object):
|
|||
# Get a random name if none is given
|
||||
name = "".join([random.choice(string.ascii_letters+string.digits)
|
||||
for n in range(10)])
|
||||
logger.info("circuit name: " + name)
|
||||
logger.info("circuit name: %s", name)
|
||||
logger.info("******************************")
|
||||
logger.info(node_circuit.qasm())
|
||||
# current method to turn it a DAG quantum circuit.
|
||||
|
@ -608,9 +616,9 @@ class QuantumProgram(object):
|
|||
'project': project
|
||||
}
|
||||
|
||||
for k, v in config_dict.items():
|
||||
self.__api.config[k] = v
|
||||
self.__api_config['config'][k] = v
|
||||
for key, value in config_dict.items():
|
||||
self.__api.config[key] = value
|
||||
self.__api_config['config'][key] = value
|
||||
|
||||
def get_api_config(self):
|
||||
"""Return the program specs."""
|
||||
|
@ -829,6 +837,8 @@ class QuantumProgram(object):
|
|||
cmap = configuration[key]
|
||||
configuration_edit[new_key] = cmap
|
||||
return configuration_edit
|
||||
raise LookupError('Configuration for %s could not be found.' %
|
||||
backend)
|
||||
else:
|
||||
return qiskit.backends.get_backend_configuration(backend)
|
||||
|
||||
|
@ -1010,20 +1020,20 @@ class QuantumProgram(object):
|
|||
if backend == 'ibmqx_hpc_qasm_simulator':
|
||||
if hpc is None:
|
||||
logger.info('ibmqx_hpc_qasm_simulator backend needs HPC '
|
||||
'parameter. Setting defaults to hpc.multi_shot_optimization '
|
||||
'= true and hpc.omp_num_threads = 16')
|
||||
'parameter. Setting defaults to hpc.multi_shot_optimization '
|
||||
'= true and hpc.omp_num_threads = 16')
|
||||
hpc = {'multi_shot_optimization': True, 'omp_num_threads': 16}
|
||||
|
||||
if not all (key in hpc for key in
|
||||
('multi_shot_optimization','omp_num_threads')):
|
||||
if not all(key in hpc for key in
|
||||
('multi_shot_optimization', 'omp_num_threads')):
|
||||
raise QISKitError('Unknown HPC parameter format!')
|
||||
|
||||
qobj['config']['hpc'] = hpc
|
||||
elif hpc is not None:
|
||||
logger.info('HPC paramter is only available for '
|
||||
'ibmqx_hpc_qasm_simulator. You are passing an HPC parameter '
|
||||
'but you are not using ibmqx_hpc_qasm_simulator, so we will '
|
||||
'ignore it.')
|
||||
'ibmqx_hpc_qasm_simulator. You are passing an HPC parameter '
|
||||
'but you are not using ibmqx_hpc_qasm_simulator, so we will '
|
||||
'ignore it.')
|
||||
hpc = None
|
||||
|
||||
qobj['circuits'] = []
|
||||
|
@ -1033,8 +1043,8 @@ class QuantumProgram(object):
|
|||
basis_gates = backend_conf['basis_gates']
|
||||
elif len(basis_gates.split(',')) < 2:
|
||||
# catches deprecated basis specification like 'SU2+CNOT'
|
||||
logger.warn('encountered deprecated basis specification: '
|
||||
'"{}" substituting u1,u2,u3,cx,id'.format(basis_gates))
|
||||
logger.warning('encountered deprecated basis specification: '
|
||||
'"%s" substituting u1,u2,u3,cx,id', str(basis_gates))
|
||||
basis_gates = 'u1,u2,u3,cx,id'
|
||||
if not coupling_map:
|
||||
coupling_map = backend_conf['coupling_map']
|
||||
|
@ -1171,7 +1181,8 @@ class QuantumProgram(object):
|
|||
if qobj["circuits"][index]['name'] == name:
|
||||
return qobj["circuits"][index]["config"]
|
||||
except KeyError:
|
||||
raise QISKitError('No compiled configurations for circuit "{0}"'.format(name))
|
||||
pass
|
||||
raise QISKitError('No compiled configurations for circuit "{0}"'.format(name))
|
||||
|
||||
def get_compiled_qasm(self, qobj, name):
|
||||
"""Return the compiled cricuit in qasm format.
|
||||
|
@ -1191,7 +1202,8 @@ class QuantumProgram(object):
|
|||
if qobj["circuits"][index]['name'] == name:
|
||||
return qobj["circuits"][index]["compiled_circuit_qasm"]
|
||||
except KeyError:
|
||||
raise QISKitError('No compiled qasm for circuit "{0}"'.format(name))
|
||||
pass
|
||||
raise QISKitError('No compiled qasm for circuit "{0}"'.format(name))
|
||||
|
||||
###############################################################
|
||||
# methods to run quantum programs
|
||||
|
@ -1291,8 +1303,8 @@ class QuantumProgram(object):
|
|||
q_job_list = []
|
||||
for qobj in qobj_list:
|
||||
q_job = QuantumJob(qobj, preformatted=True, resources={
|
||||
'max_credits':qobj['config']['max_credits'], 'wait':wait,
|
||||
'timeout':timeout})
|
||||
'max_credits': qobj['config']['max_credits'], 'wait': wait,
|
||||
'timeout': timeout})
|
||||
q_job_list.append(q_job)
|
||||
|
||||
job_processor = JobProcessor(q_job_list, max_workers=5,
|
||||
|
|
|
@ -1,7 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Module for working with Results."""
|
||||
|
||||
import copy
|
||||
import numpy
|
||||
from qiskit._qiskiterror import QISKitError
|
||||
from qiskit import RegisterSizeError
|
||||
|
||||
|
||||
class Result(object):
|
||||
""" Result Class.
|
||||
|
@ -41,7 +60,7 @@ class Result(object):
|
|||
"""Get the status of the run.
|
||||
|
||||
Returns:
|
||||
the status of the results.
|
||||
string: the status of the results.
|
||||
"""
|
||||
return self._result['status']
|
||||
|
||||
|
@ -57,7 +76,9 @@ class Result(object):
|
|||
Arg:
|
||||
other (Result): a Result object to append.
|
||||
Returns:
|
||||
The current object with appended results.
|
||||
Result: The current object with appended results.
|
||||
Raises:
|
||||
QISKitError: if the Results cannot be combined.
|
||||
"""
|
||||
if self._qobj['config'] == other._qobj['config']:
|
||||
if isinstance(self._qobj['id'], str):
|
||||
|
@ -78,7 +99,7 @@ class Result(object):
|
|||
Arg:
|
||||
other (Result): a Result object to combine.
|
||||
Returns:
|
||||
A new Result object consisting of combined objects.
|
||||
Result: A new Result object consisting of combined objects.
|
||||
"""
|
||||
ret = copy.deepcopy(self)
|
||||
ret += other
|
||||
|
@ -94,8 +115,8 @@ class Result(object):
|
|||
def circuit_statuses(self):
|
||||
"""Return statuses of all circuits
|
||||
|
||||
Return:
|
||||
List of status result strings.
|
||||
Returns:
|
||||
list(str): List of status result strings.
|
||||
"""
|
||||
return [circuit_result['status']
|
||||
for circuit_result in self._result['result']]
|
||||
|
@ -105,6 +126,8 @@ class Result(object):
|
|||
|
||||
Args:
|
||||
icircuit (int): index of circuit
|
||||
Returns:
|
||||
string: the status of the circuit.
|
||||
"""
|
||||
return self._result['result'][icircuit]['status']
|
||||
|
||||
|
@ -112,7 +135,7 @@ class Result(object):
|
|||
"""Return the job id assigned by the api if this is a remote job.
|
||||
|
||||
Returns:
|
||||
a string containing the job id.
|
||||
string: a string containing the job id.
|
||||
"""
|
||||
return self._result['job_id']
|
||||
|
||||
|
@ -123,7 +146,9 @@ class Result(object):
|
|||
name (str): the name of the quantum circuit.
|
||||
|
||||
Returns:
|
||||
A text version of the qasm file that has been run.
|
||||
string: A text version of the qasm file that has been run.
|
||||
Raises:
|
||||
QISKitError: if the circuit was not found.
|
||||
"""
|
||||
try:
|
||||
qobj = self._qobj
|
||||
|
@ -131,7 +156,8 @@ class Result(object):
|
|||
if qobj["circuits"][index]['name'] == name:
|
||||
return qobj["circuits"][index]["compiled_circuit_qasm"]
|
||||
except KeyError:
|
||||
raise QISKitError('No qasm for circuit "{0}"'.format(name))
|
||||
pass
|
||||
raise QISKitError('No qasm for circuit "{0}"'.format(name))
|
||||
|
||||
def get_data(self, name):
|
||||
"""Get the data of circuit name.
|
||||
|
@ -165,11 +191,12 @@ class Result(object):
|
|||
name (str): the name of the quantum circuit.
|
||||
|
||||
Returns:
|
||||
A dictionary of data for the different backends.
|
||||
dict: A dictionary of data for the different backends.
|
||||
|
||||
Raises:
|
||||
If there's an error the function will throw a QISKitError or a
|
||||
RegisterSizeError.
|
||||
QISKitError: if there is no data for the circuit, or an unhandled
|
||||
error occurred while fetching the data.
|
||||
Exception: if a handled error occurred while fetching the data.
|
||||
"""
|
||||
if self._is_error():
|
||||
exception = self._result['result']
|
||||
|
@ -184,7 +211,8 @@ class Result(object):
|
|||
if qobj['circuits'][index]['name'] == name:
|
||||
return self._result['result'][index]['data']
|
||||
except (KeyError, TypeError):
|
||||
raise QISKitError('No data for circuit "{0}"'.format(name))
|
||||
pass
|
||||
raise QISKitError('No data for circuit "{0}"'.format(name))
|
||||
|
||||
def get_counts(self, name):
|
||||
"""Get the histogram data of circuit name.
|
||||
|
@ -197,6 +225,9 @@ class Result(object):
|
|||
|
||||
Returns:
|
||||
Dictionary: Counts {’00000’: XXXX, ’00001’: XXXXX}.
|
||||
|
||||
Raises:
|
||||
QISKitError: if there are no counts for the circuit.
|
||||
"""
|
||||
try:
|
||||
return self.get_data(name)['counts']
|
||||
|
@ -248,12 +279,12 @@ class Result(object):
|
|||
xvals: mx1 array of the circuit xvals
|
||||
"""
|
||||
ncircuits = len(self._qobj['circuits'])
|
||||
#Is this the best way to get the number of qubits?
|
||||
# Is this the best way to get the number of qubits?
|
||||
nqubits = self._qobj['circuits'][0]['compiled_circuit']['header']['number_of_qubits']
|
||||
qubitpol = numpy.zeros([ncircuits, nqubits], dtype=float)
|
||||
xvals = numpy.zeros([ncircuits], dtype=float)
|
||||
|
||||
#build Z operators for each qubit
|
||||
# build Z operators for each qubit
|
||||
z_dicts = []
|
||||
for qubit_ind in range(nqubits):
|
||||
z_dicts.append(dict())
|
||||
|
@ -263,11 +294,12 @@ class Result(object):
|
|||
if new_key[nqubits-qubit_ind-1] == '1':
|
||||
z_dicts[-1][new_key] = 1
|
||||
|
||||
#go through each circuit and for eqch qubit and apply the operators using "average_data"
|
||||
# go through each circuit and for eqch qubit and apply the operators using "average_data"
|
||||
for circuit_ind in range(ncircuits):
|
||||
if not xvals_dict is None:
|
||||
if xvals_dict:
|
||||
xvals[circuit_ind] = xvals_dict[self._qobj['circuits'][circuit_ind]['name']]
|
||||
for qubit_ind in range(nqubits):
|
||||
qubitpol[circuit_ind, qubit_ind] = self.average_data(self._qobj['circuits'][circuit_ind]['name'], z_dicts[qubit_ind])
|
||||
qubitpol[circuit_ind, qubit_ind] = self.average_data(
|
||||
self._qobj['circuits'][circuit_ind]['name'], z_dicts[qubit_ind])
|
||||
|
||||
return qubitpol, xvals
|
||||
|
|
|
@ -22,6 +22,7 @@ from unittest.mock import patch
|
|||
API_NAME = 'IBMQuantumExperience'
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _check_ibmqe_version():
|
||||
"""Check if the available IBMQuantumExperience version is the required one.
|
||||
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Utilities for using backends."""
|
||||
from ._basebackend import BaseBackend
|
||||
from ._backendutils import (get_backend_class,
|
||||
get_backend_instance,
|
||||
|
|
|
@ -1,15 +1,33 @@
|
|||
"""backend functions for registration, information, etc."""
|
||||
from collections import namedtuple
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Backend functions for registration, information, etc."""
|
||||
|
||||
import importlib
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import pkgutil
|
||||
import logging
|
||||
import re
|
||||
from collections import namedtuple
|
||||
|
||||
from .. import QISKitError
|
||||
from ._basebackend import BaseBackend
|
||||
from qiskit import mapper
|
||||
from ._basebackend import BaseBackend
|
||||
from .. import QISKitError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -33,6 +51,7 @@ as its contents are a combination of:
|
|||
FIRST_CAP_RE = re.compile('(.)([A-Z][a-z]+)')
|
||||
ALL_CAP_RE = re.compile('([a-z0-9])([A-Z])')
|
||||
|
||||
|
||||
def discover_local_backends(directory=os.path.dirname(__file__)):
|
||||
"""This function attempts to discover all backend modules.
|
||||
|
||||
|
@ -65,10 +84,10 @@ def discover_local_backends(directory=os.path.dirname(__file__)):
|
|||
except QISKitError:
|
||||
# Ignore backends that could not be initialized.
|
||||
logger.info(
|
||||
'backend {} could not be initialized'.format(
|
||||
fullname))
|
||||
'backend %s could not be initialized', fullname)
|
||||
return backend_name_list
|
||||
|
||||
|
||||
def discover_remote_backends(api):
|
||||
"""Discover backends available on the Quantum Experience
|
||||
|
||||
|
@ -108,11 +127,13 @@ def discover_remote_backends(api):
|
|||
_REGISTERED_BACKENDS[backend_name] = registered_backend
|
||||
return backend_name_list
|
||||
|
||||
|
||||
def _snake_case_to_camel_case(name):
|
||||
"""Return a snake case string from a camelcase string."""
|
||||
string_1 = FIRST_CAP_RE.sub(r'\1_\2', name)
|
||||
return ALL_CAP_RE.sub(r'\1_\2', string_1).lower()
|
||||
|
||||
|
||||
def update_backends(api=None):
|
||||
"""Update registered backends.
|
||||
|
||||
|
@ -131,6 +152,7 @@ def update_backends(api=None):
|
|||
backend_name_list += discover_remote_backends(api)
|
||||
return backend_name_list
|
||||
|
||||
|
||||
def register_backend(cls, configuration=None):
|
||||
"""Register a backend in the list of available backends.
|
||||
|
||||
|
@ -141,7 +163,7 @@ def register_backend(cls, configuration=None):
|
|||
* the backend is not already registered.
|
||||
|
||||
Args:
|
||||
cls (BaseBackend): a subclass of BaseBackend that contains a backend
|
||||
cls (class): a subclass of BaseBackend that contains a backend
|
||||
configuration (dict): backend configuration to use instead of class'
|
||||
default.
|
||||
|
||||
|
@ -180,6 +202,7 @@ def register_backend(cls, configuration=None):
|
|||
|
||||
return backend_name
|
||||
|
||||
|
||||
def deregister_backend(backend_name):
|
||||
"""Remove backend from list of available backens
|
||||
|
||||
|
@ -209,6 +232,7 @@ def get_backend_class(backend_name):
|
|||
except KeyError:
|
||||
raise LookupError('backend "{}" is not available'.format(backend_name))
|
||||
|
||||
|
||||
def get_backend_instance(backend_name):
|
||||
"""Return a backend instance for the named backend.
|
||||
|
||||
|
@ -228,6 +252,7 @@ def get_backend_instance(backend_name):
|
|||
return registered_backend.cls(
|
||||
configuration=registered_backend.configuration)
|
||||
|
||||
|
||||
def get_backend_configuration(backend_name):
|
||||
"""Return the configuration for the named backend.
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""This module implements the abstract base class for backend modules.
|
||||
|
||||
To create add-on backend modules subclass the Backend class in this module.
|
||||
|
@ -7,6 +24,7 @@ from abc import ABC, abstractmethod
|
|||
|
||||
|
||||
class BaseBackend(ABC):
|
||||
"""Base class for backends."""
|
||||
@abstractmethod
|
||||
def __init__(self, configuration=None):
|
||||
"""Base class for backends.
|
||||
|
@ -25,6 +43,7 @@ class BaseBackend(ABC):
|
|||
|
||||
@abstractmethod
|
||||
def run(self, q_job):
|
||||
"""Run a QuantumJob on the the backend."""
|
||||
pass
|
||||
|
||||
@property
|
||||
|
|
|
@ -1,3 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=unused-import
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Backend for the Project Q C++ simulator."""
|
||||
|
||||
|
||||
import itertools
|
||||
import operator
|
||||
import random
|
||||
|
@ -42,7 +63,10 @@ class ProjectQSimulator(BaseBackend):
|
|||
"""
|
||||
Args:
|
||||
configuration (dict): backend configuration
|
||||
Raises:
|
||||
ImportError: if the Project Q simulator is not available.
|
||||
"""
|
||||
super(ProjectQSimulator, self).__init__(configuration)
|
||||
if CppSim is None:
|
||||
logger.info('Project Q C++ simulator unavailable.')
|
||||
raise ImportError('Project Q C++ simulator unavailable.')
|
||||
|
@ -59,6 +83,15 @@ class ProjectQSimulator(BaseBackend):
|
|||
else:
|
||||
self._configuration = configuration
|
||||
|
||||
# Define the attributes inside __init__.
|
||||
self._number_of_qubits = 0
|
||||
self._number_of_clbits = 0
|
||||
self._quantum_state = 0
|
||||
self._classical_state = 0
|
||||
self._seed = None
|
||||
self._shots = 0
|
||||
self._sim = None
|
||||
|
||||
def run(self, q_job):
|
||||
"""Run circuits in q_job"""
|
||||
# Generating a string id for the job
|
||||
|
@ -85,7 +118,7 @@ class ProjectQSimulator(BaseBackend):
|
|||
circuit (dict): JSON circuit from qobj circuits list
|
||||
|
||||
Returns:
|
||||
A dictionary of results which looks something like::
|
||||
dict: A dictionary of results which looks something like::
|
||||
|
||||
{
|
||||
"data":
|
||||
|
@ -95,14 +128,17 @@ class ProjectQSimulator(BaseBackend):
|
|||
},
|
||||
"status": --status (string)--
|
||||
}
|
||||
Raises:
|
||||
SimulatorError: if an error occurred.
|
||||
"""
|
||||
# pylint: disable=expression-not-assigned,pointless-statement
|
||||
ccircuit = circuit['compiled_circuit']
|
||||
self._number_of_qubits = ccircuit['header']['number_of_qubits']
|
||||
self._number_of_clbits = ccircuit['header']['number_of_clbits']
|
||||
self._quantum_state = 0
|
||||
self._classical_state = 0
|
||||
cl_reg_index = [] # starting bit index of classical register
|
||||
cl_reg_nbits = [] # number of bits in classical register
|
||||
cl_reg_index = [] # starting bit index of classical register
|
||||
cl_reg_nbits = [] # number of bits in classical register
|
||||
clbit_index = 0
|
||||
qobj_quregs = OrderedDict(_get_register_specs(
|
||||
ccircuit['header']['qubit_labels']))
|
||||
|
@ -117,14 +153,14 @@ class ProjectQSimulator(BaseBackend):
|
|||
if circuit['config']['seed'] is not None:
|
||||
self._sim._simulator = CppSim(circuit['config']['seed'])
|
||||
outcomes = []
|
||||
for shot in range(self._shots):
|
||||
for _ in range(self._shots):
|
||||
self._quantum_state = np.zeros(1 << self._number_of_qubits,
|
||||
dtype=complex)
|
||||
self._quantum_state[0] = 1
|
||||
# initialize starting state
|
||||
self._classical_state = 0
|
||||
unmeasured_qubits = list(range(self._number_of_qubits))
|
||||
projq_qureg_dict = OrderedDict(((key,eng.allocate_qureg(size))
|
||||
projq_qureg_dict = OrderedDict(((key, eng.allocate_qureg(size))
|
||||
for key, size in
|
||||
qobj_quregs.items()))
|
||||
qureg = [qubit for sublist in projq_qureg_dict.values()
|
||||
|
@ -148,11 +184,11 @@ class ProjectQSimulator(BaseBackend):
|
|||
Ry(params[0]) | qubit
|
||||
Rz(params[1]) | qubit
|
||||
elif operation['name'] in ['u1']:
|
||||
params = operation['params']
|
||||
params = operation['params']
|
||||
qubit = qureg[operation['qubits'][0]]
|
||||
Rz(params[0]) | qubit
|
||||
elif operation['name'] in ['u2']:
|
||||
params = operation['params']
|
||||
params = operation['params']
|
||||
qubit = qureg[operation['qubits'][0]]
|
||||
Rz(params[1] - np.pi/2) | qubit
|
||||
Rx(np.pi/2) | qubit
|
||||
|
@ -188,7 +224,7 @@ class ProjectQSimulator(BaseBackend):
|
|||
# Check if reset
|
||||
elif operation['name'] == 'reset':
|
||||
qubit = operation['qubits'][0]
|
||||
raise SimulatorError('Reset operation not yet implemented '+
|
||||
raise SimulatorError('Reset operation not yet implemented '
|
||||
'for ProjectQ C++ backend')
|
||||
elif operation['name'] == 'barrier':
|
||||
pass
|
||||
|
@ -201,7 +237,7 @@ class ProjectQSimulator(BaseBackend):
|
|||
qubit = qureg[ind]
|
||||
Measure | qubit
|
||||
eng.flush()
|
||||
# Turn classical_state (int) into bit string
|
||||
# Turn classical_state (int) into bit string
|
||||
state = format(self._classical_state, 'b')
|
||||
outcomes.append(state.zfill(self._number_of_clbits))
|
||||
# Return the results
|
||||
|
@ -210,12 +246,14 @@ class ProjectQSimulator(BaseBackend):
|
|||
counts, cl_reg_index, cl_reg_nbits)}
|
||||
if self._shots == 1:
|
||||
data['quantum_state'] = self._quantum_state
|
||||
data['classical_state'] = self._classical_state,
|
||||
data['classical_state'] = self._classical_state
|
||||
return {'data': data, 'status': 'DONE'}
|
||||
|
||||
|
||||
def _get_register_specs(bit_labels):
|
||||
"""
|
||||
Get the number and size of unique registers from bit_labels list.
|
||||
Get the number and size of unique registers from bit_labels list with an
|
||||
iterator of register_name:size pairs.
|
||||
|
||||
Args:
|
||||
bit_labels (list): this list is of the form::
|
||||
|
@ -224,16 +262,16 @@ def _get_register_specs(bit_labels):
|
|||
|
||||
which indicates a register named "reg1" of size 2
|
||||
and a register named "reg2" of size 1. This is the
|
||||
format of classic and quantum bit labels in qobj
|
||||
format of classic and quantum bit labels in qobj
|
||||
header.
|
||||
|
||||
Returns:
|
||||
iterator of register_name:size pairs.
|
||||
Yields:
|
||||
tuple: pairs of (register_name, size)
|
||||
"""
|
||||
it = itertools.groupby(bit_labels, operator.itemgetter(0))
|
||||
for register_name, sub_it in it:
|
||||
iterator = itertools.groupby(bit_labels, operator.itemgetter(0))
|
||||
for register_name, sub_it in iterator:
|
||||
yield register_name, max(ind[1] for ind in sub_it) + 1
|
||||
|
||||
|
||||
def _format_result(counts, cl_reg_index, cl_reg_nbits):
|
||||
"""Format the result bit string.
|
||||
|
||||
|
@ -241,11 +279,11 @@ def _format_result(counts, cl_reg_index, cl_reg_nbits):
|
|||
at register divisions.
|
||||
|
||||
Args:
|
||||
counts : dictionary of counts e.g. {'1111': 1000, '0000':5}
|
||||
cl_reg_index: starting bit index of classical register
|
||||
cl_reg_nbits: total amount of bits in classical register
|
||||
counts (dict): dictionary of counts e.g. {'1111': 1000, '0000':5}
|
||||
cl_reg_index (list): starting bit index of classical register
|
||||
cl_reg_nbits (list): total amount of bits in classical register
|
||||
Returns:
|
||||
spaces inserted into dictionary keys at register boundries.
|
||||
dict: spaces inserted into dictionary keys at register boundaries.
|
||||
"""
|
||||
fcounts = {}
|
||||
for key, value in counts.items():
|
||||
|
@ -255,4 +293,3 @@ def _format_result(counts, cl_reg_index, cl_reg_nbits):
|
|||
new_key.insert(0, key[-(index+nbits):-index])
|
||||
fcounts[' '.join(new_key)] = value
|
||||
return fcounts
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Interface to a fast C++ QASM simulator.
|
||||
|
||||
Authors: Erick Winston <ewinston@us.ibm.com>
|
||||
|
@ -28,6 +45,7 @@ class QasmCppSimulator(BaseBackend):
|
|||
Raises:
|
||||
FileNotFoundError: if executable, 'qasm_simulator', is not on path
|
||||
"""
|
||||
super(QasmCppSimulator, self).__init__(configuration)
|
||||
if configuration is None:
|
||||
self._configuration = {'name': 'local_qasm_cpp_simulator',
|
||||
'url': 'https://github.com/IBM/qiskit-sdk-py',
|
||||
|
@ -36,8 +54,7 @@ class QasmCppSimulator(BaseBackend):
|
|||
'local': True,
|
||||
'description': 'A c++ simulator for qasm files',
|
||||
'coupling_map': 'all-to-all',
|
||||
'basis_gates': 'u1,u2,u3,cx,id'
|
||||
}
|
||||
'basis_gates': 'u1,u2,u3,cx,id'}
|
||||
else:
|
||||
self._configuration = configuration
|
||||
self._is_simulator = self._configuration['simulator']
|
||||
|
@ -62,6 +79,15 @@ class QasmCppSimulator(BaseBackend):
|
|||
cmd = '"{0}" or "{1}" '.format(self._exe, './' + self._exe)
|
||||
raise FileNotFoundError(cmd)
|
||||
|
||||
# Define attributes in __init__.
|
||||
self._threads = 0
|
||||
self._default_shots = 0
|
||||
self.result = None
|
||||
self._cpp_backend = None
|
||||
self.cin_dict = None
|
||||
self.config = None
|
||||
self._default_seed = 0
|
||||
|
||||
def run(self, q_job):
|
||||
"""
|
||||
Run simulation on C++ simulator.
|
||||
|
@ -114,7 +140,7 @@ class QasmCppSimulator(BaseBackend):
|
|||
stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
|
||||
cin = json.dumps(qobj).encode()
|
||||
cout, cerr = proc.communicate(cin)
|
||||
if len(cerr) == 0:
|
||||
if not cerr:
|
||||
# no error messages, load std::cout
|
||||
cresult = json.loads(cout.decode())
|
||||
cresult['job_id'] = job_id
|
||||
|
@ -134,6 +160,11 @@ class QasmCppSimulator(BaseBackend):
|
|||
|
||||
Args:
|
||||
circuit (dict): JSON circuit from qobj circuits list
|
||||
Raises:
|
||||
TypeError: if the seed is not valid.
|
||||
SimulatorError: if the cpp simulator failed.
|
||||
Returns:
|
||||
Result: Result object.
|
||||
"""
|
||||
self.cin_dict = {'qasm': circuit['compiled_circuit'],
|
||||
'config': self.config}
|
||||
|
@ -170,7 +201,7 @@ class QasmCppSimulator(BaseBackend):
|
|||
stdin=PIPE, stdout=PIPE, stderr=PIPE) as proc:
|
||||
cin = json.dumps(self.cin_dict).encode()
|
||||
cout, cerr = proc.communicate(cin)
|
||||
if len(cerr) == 0:
|
||||
if not cerr:
|
||||
# no error messages, load std::cout
|
||||
cresult = json.loads(cout.decode())
|
||||
# convert possible complex valued result fields
|
||||
|
|
|
@ -35,9 +35,9 @@ and
|
|||
|
||||
results['data']['classical_state']
|
||||
|
||||
where 'quantum_state' is a 2\ :sup:`n` complex numpy array representing the
|
||||
where 'quantum_state' is a 2 :sup:`n` complex numpy array representing the
|
||||
quantum state vector and 'classical_state' is an integer representing
|
||||
the state of the classical registors.
|
||||
the state of the classical registers.
|
||||
|
||||
if shots > 1
|
||||
|
||||
|
@ -105,15 +105,17 @@ if shots > 1
|
|||
}
|
||||
|
||||
"""
|
||||
import uuid
|
||||
import numpy as np
|
||||
import random
|
||||
import uuid
|
||||
from collections import Counter
|
||||
import json
|
||||
from ._simulatortools import single_gate_matrix
|
||||
from ._simulatorerror import SimulatorError
|
||||
|
||||
import numpy as np
|
||||
|
||||
from qiskit._result import Result
|
||||
from qiskit.backends._basebackend import BaseBackend
|
||||
from ._simulatorerror import SimulatorError
|
||||
from ._simulatortools import single_gate_matrix
|
||||
|
||||
|
||||
# TODO add ["status"] = 'DONE', 'ERROR' especitally for empty circuit error
|
||||
# does not show up
|
||||
|
@ -126,6 +128,7 @@ class QasmSimulator(BaseBackend):
|
|||
Args:
|
||||
configuration (dict): backend configuration
|
||||
"""
|
||||
super(QasmSimulator, self).__init__(configuration)
|
||||
if configuration is None:
|
||||
self._configuration = {
|
||||
'name': 'local_qasm_simulator',
|
||||
|
@ -138,9 +141,16 @@ class QasmSimulator(BaseBackend):
|
|||
}
|
||||
else:
|
||||
self._configuration = configuration
|
||||
|
||||
|
||||
self._local_random = random.Random()
|
||||
|
||||
# Define attributes in __init__.
|
||||
self._classical_state = 0
|
||||
self._quantum_state = 0
|
||||
self._number_of_cbits = 0
|
||||
self._number_of_qubits = 0
|
||||
self._shots = 0
|
||||
|
||||
@staticmethod
|
||||
def _index1(b, i, k):
|
||||
"""Magic index1 function.
|
||||
|
@ -293,7 +303,7 @@ class QasmSimulator(BaseBackend):
|
|||
circuit (dict): JSON circuit from qobj circuits list
|
||||
|
||||
Returns:
|
||||
A dictionary of results which looks something like::
|
||||
dict: A dictionary of results which looks something like::
|
||||
|
||||
{
|
||||
"data":
|
||||
|
@ -303,14 +313,16 @@ class QasmSimulator(BaseBackend):
|
|||
},
|
||||
"status": --status (string)--
|
||||
}
|
||||
Raises:
|
||||
SimulatorError: if an error occurred.
|
||||
"""
|
||||
ccircuit = circuit['compiled_circuit']
|
||||
self._number_of_qubits = ccircuit['header']['number_of_qubits']
|
||||
self._number_of_cbits = ccircuit['header']['number_of_clbits']
|
||||
self._quantum_state = 0
|
||||
self._classical_state = 0
|
||||
cl_reg_index = [] # starting bit index of classical register
|
||||
cl_reg_nbits = [] # number of bits in classical register
|
||||
cl_reg_index = [] # starting bit index of classical register
|
||||
cl_reg_nbits = [] # number of bits in classical register
|
||||
cbit_index = 0
|
||||
for cl_reg in ccircuit['header']['clbit_labels']:
|
||||
cl_reg_nbits.append(cl_reg[1])
|
||||
|
@ -321,7 +333,7 @@ class QasmSimulator(BaseBackend):
|
|||
else:
|
||||
self._local_random.seed(circuit['config']['seed'])
|
||||
outcomes = []
|
||||
for shot in range(self._shots):
|
||||
for _ in range(self._shots):
|
||||
self._quantum_state = np.zeros(1 << self._number_of_qubits,
|
||||
dtype=complex)
|
||||
self._quantum_state[0] = 1
|
||||
|
@ -377,7 +389,7 @@ class QasmSimulator(BaseBackend):
|
|||
counts, cl_reg_index, cl_reg_nbits)}
|
||||
if self._shots == 1:
|
||||
data['quantum_state'] = self._quantum_state
|
||||
data['classical_state'] = self._classical_state,
|
||||
data['classical_state'] = self._classical_state
|
||||
return {'data': data, 'status': 'DONE'}
|
||||
|
||||
def _format_result(self, counts, cl_reg_index, cl_reg_nbits):
|
||||
|
@ -387,9 +399,11 @@ class QasmSimulator(BaseBackend):
|
|||
at register divisions.
|
||||
|
||||
Args:
|
||||
counts : dictionary of counts e.g. {'1111': 1000, '0000':5}
|
||||
counts (dict): dictionary of counts e.g. {'1111': 1000, '0000':5}
|
||||
cl_reg_index (list): starting bit index of classical register
|
||||
cl_reg_nbits (list): total amount of bits in classical register
|
||||
Returns:
|
||||
spaces inserted into dictionary keys at register boundries.
|
||||
dict: spaces inserted into dictionary keys at register boundaries.
|
||||
"""
|
||||
fcounts = {}
|
||||
for key, value in counts.items():
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
"""QeRemote module
|
||||
|
||||
This module is used for connecting to the Quantum Experience.
|
||||
|
@ -29,6 +45,7 @@ class QeRemote(BaseBackend):
|
|||
Args:
|
||||
configuration (dict, optional): configuration of backend
|
||||
"""
|
||||
super(QeRemote, self).__init__(configuration)
|
||||
self._configuration = configuration
|
||||
self._configuration['local'] = False
|
||||
|
||||
|
@ -39,7 +56,7 @@ class QeRemote(BaseBackend):
|
|||
q_job (QuantumJob): job to run
|
||||
|
||||
Returns:
|
||||
Result object.
|
||||
Result: Result object.
|
||||
|
||||
Raises:
|
||||
ResultError: if the api put 'error' in its output
|
||||
|
@ -62,7 +79,7 @@ class QeRemote(BaseBackend):
|
|||
seed0 = qobj['circuits'][0]['config']['seed']
|
||||
hpc = None
|
||||
if (qobj['config']['backend'] == 'ibmqx_hpc_qasm_simulator' and
|
||||
'hpc' in qobj['config']):
|
||||
'hpc' in qobj['config']):
|
||||
try:
|
||||
# Use CamelCase when passing the hpc parameters to the API.
|
||||
hpc = {
|
||||
|
@ -71,7 +88,7 @@ class QeRemote(BaseBackend):
|
|||
'ompNumThreads':
|
||||
qobj['config']['hpc']['omp_num_threads']
|
||||
}
|
||||
except:
|
||||
except (KeyError, TypeError):
|
||||
hpc = None
|
||||
|
||||
output = self._api.run_job(api_jobs, qobj['config']['backend'],
|
||||
|
@ -107,7 +124,7 @@ def _wait_for_job(jobid, api, wait=5, timeout=60):
|
|||
timeout (int): is how long we wait before failing, in seconds
|
||||
|
||||
Returns:
|
||||
A list of results that correspond to the jobids.
|
||||
list: A list of results that correspond to the jobids.
|
||||
|
||||
Raises:
|
||||
QISKitError: job didn't return status or reported error in status
|
||||
|
|
|
@ -23,11 +23,13 @@ Author: Juan Gomez
|
|||
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class SimulatorError(QISKitError):
|
||||
"""Base class for errors raised by simulators."""
|
||||
|
||||
def __init__(self, *message):
|
||||
"""Set the error message."""
|
||||
super(SimulatorError, self).__init__(*message)
|
||||
self.message = ' '.join(message)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -31,6 +31,8 @@ Functions
|
|||
"""
|
||||
import numpy as np
|
||||
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
def index1(b, i, k):
|
||||
"""Magic index1 function.
|
||||
|
@ -58,7 +60,7 @@ def index2(b1, i1, b2, i2, k):
|
|||
Takes a bitstring k and inserts bits b1 as the i1th bit
|
||||
and b2 as the i2th bit
|
||||
"""
|
||||
assert(i1 != i2)
|
||||
assert i1 != i2
|
||||
|
||||
if i1 > i2:
|
||||
# insert as (i1-1)th bit, will be shifted left 1 by next line
|
||||
|
@ -77,13 +79,16 @@ def enlarge_single_opt(opt, qubit, number_of_qubits):
|
|||
It is exponential in the number of qubits.
|
||||
|
||||
Args:
|
||||
opt: the single-qubit opt.
|
||||
qubit: the qubit to apply it on counts from 0 and order
|
||||
opt (array): the single-qubit opt.
|
||||
qubit (int): the qubit to apply it on counts from 0 and order
|
||||
is q_{n-1} ... otimes q_1 otimes q_0.
|
||||
number_of_qubits: the number of qubits in the system.
|
||||
number_of_qubits (int): the number of qubits in the system.
|
||||
|
||||
Returns:
|
||||
array: enlarge single operator to n qubits
|
||||
"""
|
||||
temp_1 = np.identity(2**(number_of_qubits-qubit-1), dtype=complex)
|
||||
temp_2 = np.identity(2**(qubit), dtype=complex)
|
||||
temp_2 = np.identity(2**qubit, dtype=complex)
|
||||
enlarge_opt = np.kron(temp_1, np.kron(opt, temp_2))
|
||||
return enlarge_opt
|
||||
|
||||
|
@ -104,7 +109,9 @@ def enlarge_two_opt(opt, q0, q1, num):
|
|||
for k in range(2):
|
||||
for jj in range(2):
|
||||
for kk in range(2):
|
||||
enlarge_opt[index2(j, q0, k, q1, i), index2(jj, q0, kk, q1, i)] = opt[j+2*k, jj+2*kk]
|
||||
enlarge_opt[index2(j, q0, k, q1, i),
|
||||
index2(jj, q0, kk, q1, i)] = opt[j+2*k,
|
||||
jj+2*kk]
|
||||
return enlarge_opt
|
||||
|
||||
|
||||
|
@ -115,25 +122,29 @@ def single_gate_params(gate, params=None):
|
|||
gate(str): the single qubit gate name
|
||||
params(list): the operation parameters op['params']
|
||||
Returns:
|
||||
a tuple of U gate parameters (theta, phi, lam)
|
||||
tuple: a tuple of U gate parameters (theta, phi, lam)
|
||||
Raises:
|
||||
QISKitError: if the gate name is not valid
|
||||
"""
|
||||
if gate == 'U' or gate == 'u3':
|
||||
return (params[0], params[1], params[2])
|
||||
return params[0], params[1], params[2]
|
||||
elif gate == 'u2':
|
||||
return (np.pi/2, params[0], params[1])
|
||||
return np.pi/2, params[0], params[1]
|
||||
elif gate == 'u1':
|
||||
return (0, 0, params[0])
|
||||
return 0, 0, params[0]
|
||||
elif gate == 'id':
|
||||
return (0, 0, 0)
|
||||
return 0, 0, 0
|
||||
raise QISKitError('Gate is not among the valid types: %s' % gate)
|
||||
|
||||
|
||||
def single_gate_matrix(gate, params=None):
|
||||
"""Get the matrix for a single qubit.
|
||||
|
||||
Args:
|
||||
gate(str): the single qubit gate name
|
||||
params(list): the operation parameters op['params']
|
||||
Returns:
|
||||
A numpy array representing the matrix
|
||||
array: A numpy array representing the matrix
|
||||
"""
|
||||
|
||||
# Converting sym to floats improves the performance of the simulator 10x.
|
||||
|
|
|
@ -57,8 +57,8 @@ Internal circuit_object::
|
|||
"conditional": // optional -- map
|
||||
{
|
||||
"type": , // string
|
||||
"mask": , // hex string
|
||||
"val": , // bhex string
|
||||
"mask": , // hex string
|
||||
"val": , // bhex string
|
||||
}
|
||||
},
|
||||
]
|
||||
|
@ -90,14 +90,14 @@ returned results object::
|
|||
'state': 'DONE'
|
||||
}
|
||||
"""
|
||||
import uuid
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
import numpy as np
|
||||
import json
|
||||
from ._simulatortools import enlarge_single_opt, enlarge_two_opt, single_gate_matrix
|
||||
|
||||
from qiskit._result import Result
|
||||
from qiskit.backends._basebackend import BaseBackend
|
||||
|
||||
from ._simulatortools import enlarge_single_opt, enlarge_two_opt, single_gate_matrix
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -111,6 +111,7 @@ class UnitarySimulator(BaseBackend):
|
|||
|
||||
def __init__(self, configuration=None):
|
||||
"""Initial the UnitarySimulator object."""
|
||||
super(UnitarySimulator, self).__init__(configuration)
|
||||
if configuration is None:
|
||||
self._configuration = {'name': 'local_unitary_simulator',
|
||||
'url': 'https://github.com/IBM/qiskit-sdk-py',
|
||||
|
@ -122,6 +123,10 @@ class UnitarySimulator(BaseBackend):
|
|||
else:
|
||||
self._configuration = configuration
|
||||
|
||||
# Define attributes inside __init__.
|
||||
self._unitary_state = None
|
||||
self._number_of_qubits = 0
|
||||
|
||||
def _add_unitary_single(self, gate, qubit):
|
||||
"""Apply the single-qubit gate.
|
||||
|
||||
|
@ -133,7 +138,7 @@ class UnitarySimulator(BaseBackend):
|
|||
unitaty_add = enlarge_single_opt(gate, qubit, self._number_of_qubits)
|
||||
self._unitary_state = np.dot(unitaty_add, self._unitary_state)
|
||||
|
||||
def _add_unitary_two(self, gate, q0, q1):
|
||||
def _add_unitary_two(self, gate, q_0, q_1):
|
||||
"""Apply the two-qubit gate.
|
||||
|
||||
gate is the two-qubit gate
|
||||
|
@ -141,23 +146,26 @@ class UnitarySimulator(BaseBackend):
|
|||
q1 is the second qubit (target)
|
||||
returns a complex numpy array
|
||||
"""
|
||||
unitaty_add = enlarge_two_opt(gate, q0, q1, self._number_of_qubits)
|
||||
unitaty_add = enlarge_two_opt(gate, q_0, q_1, self._number_of_qubits)
|
||||
self._unitary_state = np.dot(unitaty_add, self._unitary_state)
|
||||
|
||||
def run(self, q_job):
|
||||
"""Run q_job
|
||||
|
||||
Args:
|
||||
q_job (QuantumJob): job to run
|
||||
q_job (QuantumJob): job to run
|
||||
Returns:
|
||||
Result: Result object
|
||||
"""
|
||||
# Generating a string id for the job
|
||||
job_id = str(uuid.uuid4())
|
||||
qobj = q_job.qobj
|
||||
result_list = []
|
||||
for circuit in qobj['circuits']:
|
||||
result_list.append( self.run_circuit(circuit) )
|
||||
return Result({'job_id': job_id, 'result': result_list, 'status': 'COMPLETED'},
|
||||
qobj)
|
||||
result_list.append(self.run_circuit(circuit))
|
||||
return Result(
|
||||
{'job_id': job_id, 'result': result_list, 'status': 'COMPLETED'},
|
||||
qobj)
|
||||
|
||||
def run_circuit(self, circuit):
|
||||
"""Apply the single-qubit gate."""
|
||||
|
|
|
@ -1 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Module for DAG Circuits."""
|
||||
from ._dagcircuit import DAGCircuit
|
||||
|
|
|
@ -120,7 +120,7 @@ class DAGCircuit:
|
|||
self.output_map[(newname, i)] = self.output_map[(regname, i)]
|
||||
self.output_map.pop((regname, i), None)
|
||||
# n node d = data
|
||||
for n, d in self.multi_graph.nodes_iter(data=True):
|
||||
for _, d in self.multi_graph.nodes_iter(data=True):
|
||||
if d["type"] == "in" or d["type"] == "out":
|
||||
if d["name"][0] == regname:
|
||||
d["name"] = (newname, d["name"][1])
|
||||
|
@ -141,7 +141,7 @@ class DAGCircuit:
|
|||
if d["condition"][0] == regname:
|
||||
d["condition"] = (newname, d["condition"][1])
|
||||
# eX = edge, d= data
|
||||
for e1, e2, d in self.multi_graph.edges_iter(data=True):
|
||||
for _, _, d in self.multi_graph.edges_iter(data=True):
|
||||
if d["name"][0] == regname:
|
||||
d["name"] = (newname, d["name"][1])
|
||||
|
||||
|
@ -269,13 +269,13 @@ class DAGCircuit:
|
|||
% name)
|
||||
else:
|
||||
# "barrier" is a special case
|
||||
if len(qargs) == 0:
|
||||
if not qargs:
|
||||
raise DAGCircuitError("incorrect number of qubits for %s"
|
||||
% name)
|
||||
if len(cargs) != 0:
|
||||
if cargs:
|
||||
raise DAGCircuitError("incorrect number of bits for %s"
|
||||
% name)
|
||||
if len(params) != 0:
|
||||
if params:
|
||||
raise DAGCircuitError("incorrect number of parameters for %s"
|
||||
% name)
|
||||
|
||||
|
@ -337,7 +337,7 @@ class DAGCircuit:
|
|||
self.multi_graph.node[self.node_counter]["params"] = nparams
|
||||
self.multi_graph.node[self.node_counter]["condition"] = ncondition
|
||||
|
||||
def apply_operation_back(self, name, qargs, cargs=[], params=[],
|
||||
def apply_operation_back(self, name, qargs, cargs=None, params=None,
|
||||
condition=None):
|
||||
"""Apply an operation to the output of the circuit.
|
||||
|
||||
|
@ -347,6 +347,8 @@ class DAGCircuit:
|
|||
params is a list of symbols that represent numbers
|
||||
condition is either None or a tuple (string,int) giving (creg,value)
|
||||
"""
|
||||
cargs = cargs or []
|
||||
params = params or []
|
||||
all_cbits = self._bits_in_condition(condition)
|
||||
all_cbits.extend(cargs)
|
||||
|
||||
|
@ -359,7 +361,7 @@ class DAGCircuit:
|
|||
# will return Python expressions. To get the correct
|
||||
# OpenQASM expression, we need to replace "**" with "^".
|
||||
node_params = list(map(lambda x: x.replace("**", "^"),
|
||||
map(str, params)))
|
||||
map(str, params)))
|
||||
self._add_op_node(name, qargs, cargs, node_params,
|
||||
condition)
|
||||
# Add new in-edges from predecessors of the output nodes to the
|
||||
|
@ -374,7 +376,7 @@ class DAGCircuit:
|
|||
self.multi_graph.add_edge(
|
||||
self.node_counter, self.output_map[q], name=q)
|
||||
|
||||
def apply_operation_front(self, name, qargs, cargs=[], params=[],
|
||||
def apply_operation_front(self, name, qargs, cargs=None, params=None,
|
||||
condition=None):
|
||||
"""Apply an operation to the input of the circuit.
|
||||
|
||||
|
@ -384,6 +386,8 @@ class DAGCircuit:
|
|||
params is a list of strings that represent floats
|
||||
condition is either None or a tuple (string,int) giving (creg,value)
|
||||
"""
|
||||
cargs = cargs or []
|
||||
params = params or []
|
||||
all_cbits = self._bits_in_condition(condition)
|
||||
all_cbits.extend(cargs)
|
||||
|
||||
|
@ -396,8 +400,8 @@ class DAGCircuit:
|
|||
# will return Python expressions. To get the correct
|
||||
# OpenQASM expression, we need to replace "**" with "^".
|
||||
node_params = list(map(lambda x: x.replace("**", "^"),
|
||||
map(str, params)))
|
||||
self._add_op_node(name, qargs, cargs, node_params,
|
||||
map(str, params)))
|
||||
self._add_op_node(name, qargs, cargs, node_params,
|
||||
condition)
|
||||
# Add new out-edges to successors of the input nodes from the
|
||||
# operation node while deleting the old out-edges of the input nodes
|
||||
|
@ -543,7 +547,7 @@ class DAGCircuit:
|
|||
n_condition = (wire_map.get(bit0, bit0)[0], condition[1])
|
||||
return n_condition
|
||||
|
||||
def compose_back(self, input_circuit, wire_map={}):
|
||||
def compose_back(self, input_circuit, wire_map=None):
|
||||
"""Apply the input circuit to the output of this circuit.
|
||||
|
||||
The two bases must be "compatible" or an exception occurs.
|
||||
|
@ -551,6 +555,7 @@ class DAGCircuit:
|
|||
to a subset of output qubits of this circuit.
|
||||
wire_map[input_qubit_to_input_circuit] = output_qubit_of_self
|
||||
"""
|
||||
wire_map = wire_map or {}
|
||||
union_basis = self._make_union_basis(input_circuit)
|
||||
union_gates = self._make_union_gates(input_circuit)
|
||||
|
||||
|
@ -601,7 +606,7 @@ class DAGCircuit:
|
|||
else:
|
||||
assert False, "bad node type %s" % nd["type"]
|
||||
|
||||
def compose_front(self, input_circuit, wire_map={}):
|
||||
def compose_front(self, input_circuit, wire_map=None):
|
||||
"""Apply the input circuit to the input of this circuit.
|
||||
|
||||
The two bases must be "compatible" or an exception occurs.
|
||||
|
@ -609,6 +614,7 @@ class DAGCircuit:
|
|||
to a subset of input qubits of
|
||||
this circuit.
|
||||
"""
|
||||
wire_map = wire_map or {}
|
||||
union_basis = self._make_union_basis(input_circuit)
|
||||
union_gates = self._make_union_gates(input_circuit)
|
||||
|
||||
|
@ -770,7 +776,7 @@ class DAGCircuit:
|
|||
if nd["condition"] is not None:
|
||||
out += "if(%s==%d) " \
|
||||
% (nd["condition"][0], nd["condition"][1])
|
||||
if len(nd["cargs"]) == 0:
|
||||
if not nd["cargs"]:
|
||||
nm = nd["name"]
|
||||
if aliases:
|
||||
qarglist = map(lambda x: aliases[x], nd["qargs"])
|
||||
|
@ -778,7 +784,7 @@ class DAGCircuit:
|
|||
qarglist = nd["qargs"]
|
||||
qarg = ",".join(map(lambda x: "%s[%d]" % (x[0], x[1]),
|
||||
qarglist))
|
||||
if len(nd["params"]) > 0:
|
||||
if nd["params"]:
|
||||
if eval_symbols:
|
||||
param = ",".join(map(lambda x: str(sympy.N(x)),
|
||||
nd["params"]))
|
||||
|
@ -791,7 +797,7 @@ class DAGCircuit:
|
|||
if nd["name"] == "measure":
|
||||
assert len(nd["cargs"]) == 1 and \
|
||||
len(nd["qargs"]) == 1 and \
|
||||
len(nd["params"]) == 0, "bad node data"
|
||||
not nd["params"], "bad node data"
|
||||
qname = nd["qargs"][0][0]
|
||||
qindex = nd["qargs"][0][1]
|
||||
if aliases:
|
||||
|
@ -866,15 +872,16 @@ class DAGCircuit:
|
|||
# Otherwise, use the corresponding output nodes of self
|
||||
# and compute the predecessor.
|
||||
full_succ_map[w] = self.output_map[w]
|
||||
full_pred_map[w] = self.multi_graph.predecessors(self.output_map[w])[
|
||||
0]
|
||||
full_pred_map[w] = self.multi_graph.predecessors(
|
||||
self.output_map[w])[0]
|
||||
assert len(self.multi_graph.predecessors(self.output_map[w])) == 1,\
|
||||
"too many predecessors for (%s,%d) output node" % (
|
||||
w[0], w[1])
|
||||
return full_pred_map, full_succ_map
|
||||
|
||||
def substitute_circuit_all(self, name, input_circuit, wires=[]):
|
||||
def substitute_circuit_all(self, name, input_circuit, wires=None):
|
||||
"""Replace every occurrence of named operation with input_circuit."""
|
||||
wires = wires or None
|
||||
if name not in self.basis:
|
||||
raise DAGCircuitError("%s is not in the list of basis operations"
|
||||
% name)
|
||||
|
@ -930,10 +937,8 @@ class DAGCircuit:
|
|||
# Insert a new node
|
||||
condition = self._map_condition(wire_map,
|
||||
md["condition"])
|
||||
m_qargs = list(map(lambda x: wire_map.get(x, x),
|
||||
md["qargs"]))
|
||||
m_cargs = list(map(lambda x: wire_map.get(x, x),
|
||||
md["cargs"]))
|
||||
m_qargs = [wire_map.get(x, x) for x in md["qargs0"]]
|
||||
m_cargs = [wire_map.get(x, x) for x in md["cargs0"]]
|
||||
self._add_op_node(md["name"], m_qargs, m_cargs,
|
||||
md["params"], condition)
|
||||
# Add edges from predecessor nodes to new node
|
||||
|
@ -947,7 +952,7 @@ class DAGCircuit:
|
|||
full_pred_map[q] = copy.copy(self.node_counter)
|
||||
# Connect all predecessors and successors, and remove
|
||||
# residual edges between input and output nodes
|
||||
for w in full_pred_map.keys():
|
||||
for w in full_pred_map:
|
||||
self.multi_graph.add_edge(full_pred_map[w], full_succ_map[w],
|
||||
name=w)
|
||||
o_pred = self.multi_graph.predecessors(
|
||||
|
@ -955,19 +960,19 @@ class DAGCircuit:
|
|||
if len(o_pred) > 1:
|
||||
assert len(o_pred) == 2, \
|
||||
"expected 2 predecessors here"
|
||||
p = list(filter(lambda x: x != full_pred_map[w],
|
||||
o_pred))
|
||||
p = [x for x in o_pred if x != full_pred_map[w]]
|
||||
assert len(p) == 1, \
|
||||
"expected 1 predecessor to pass filter"
|
||||
self.multi_graph.remove_edge(
|
||||
p[0], self.output_map[w])
|
||||
|
||||
def substitute_circuit_one(self, node, input_circuit, wires=[]):
|
||||
def substitute_circuit_one(self, node, input_circuit, wires=None):
|
||||
"""Replace one node with input_circuit.
|
||||
|
||||
node is a reference to a node of self.multi_graph of type "op"
|
||||
input_circuit is a DAGCircuit
|
||||
"""
|
||||
wires = wires or None
|
||||
nd = self.multi_graph.node[node]
|
||||
|
||||
# TODO: reuse common code in substitute_circuit_one and _all
|
||||
|
@ -1041,13 +1046,13 @@ class DAGCircuit:
|
|||
full_pred_map[q] = copy.copy(self.node_counter)
|
||||
# Connect all predecessors and successors, and remove
|
||||
# residual edges between input and output nodes
|
||||
for w in full_pred_map.keys():
|
||||
for w in full_pred_map:
|
||||
self.multi_graph.add_edge(
|
||||
full_pred_map[w], full_succ_map[w], name=w)
|
||||
o_pred = self.multi_graph.predecessors(self.output_map[w])
|
||||
if len(o_pred) > 1:
|
||||
assert len(o_pred) == 2, "expected 2 predecessors here"
|
||||
p = list(filter(lambda x: x != full_pred_map[w], o_pred))
|
||||
p = [x for x in o_pred if x != full_pred_map[w]]
|
||||
assert len(p) == 1, "expected 1 predecessor to pass filter"
|
||||
self.multi_graph.remove_edge(p[0], self.output_map[w])
|
||||
|
||||
|
@ -1154,9 +1159,9 @@ class DAGCircuit:
|
|||
wires_loop = list(wires_with_ops_remaining)
|
||||
emit = False
|
||||
for w in wires_loop:
|
||||
oe = list(filter(lambda x: x[2]["name"] == w,
|
||||
self.multi_graph.out_edges(nbunch=[node_map[w]],
|
||||
data=True)))
|
||||
oe = [x for x in self.multi_graph.out_edges(nbunch=[node_map[w]],
|
||||
data=True) if
|
||||
x[2]["name"] == w]
|
||||
assert len(oe) == 1, "should only be one out-edge per (qu)bit"
|
||||
nxt_nd_idx = oe[0][1]
|
||||
nxt_nd = self.multi_graph.node[nxt_nd_idx]
|
||||
|
@ -1226,7 +1231,7 @@ class DAGCircuit:
|
|||
ca = copy.copy(nxt_nd["cargs"])
|
||||
pa = copy.copy(nxt_nd["params"])
|
||||
co = copy.copy(nxt_nd["condition"])
|
||||
cob = self._bits_in_condition(co)
|
||||
_ = self._bits_in_condition(co)
|
||||
# Add node to new_layer
|
||||
new_layer.apply_operation_back(nxt_nd["name"],
|
||||
qa, ca, pa, co)
|
||||
|
|
|
@ -20,11 +20,13 @@ Exception for errors raised by the DAGCircuit object.
|
|||
"""
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class DAGCircuitError(QISKitError):
|
||||
"""Base class for errors raised by the DAGCircuit object."""
|
||||
|
||||
def __init__(self, *msg):
|
||||
"""Set the error message."""
|
||||
super(DAGCircuitError, self).__init__(*msg)
|
||||
self.msg = ' '.join(msg)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
|
@ -26,6 +26,7 @@ class ExtensionError(QISKitError):
|
|||
|
||||
def __init__(self, *message):
|
||||
"""Set the error message."""
|
||||
super(ExtensionError, self).__init__(*message)
|
||||
self.message = ' '.join(message)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -1 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Initialize qubit registers to desired arbitrary state."""
|
||||
from ._initializer import InitializeGate
|
||||
|
|
|
@ -115,9 +115,9 @@ class InitializeGate(CompositeGate):
|
|||
for i in range(self.num_qubits):
|
||||
# work out which rotations must be done to disentangle the LSB
|
||||
# qubit (we peel away one qubit at a time)
|
||||
remaining_param, \
|
||||
thetas, \
|
||||
phis = InitializeGate._rotations_to_disentangle(remaining_param)
|
||||
(remaining_param,
|
||||
thetas,
|
||||
phis) = InitializeGate._rotations_to_disentangle(remaining_param)
|
||||
|
||||
# perform the required rotations to decouple the LSB qubit (so that
|
||||
# it can be "factored" out, leaving a
|
||||
|
@ -151,10 +151,10 @@ class InitializeGate(CompositeGate):
|
|||
# (imagine a qubit state signified by the amplitudes at index 2*i
|
||||
# and 2*(i+1), corresponding to the select qubits of the
|
||||
# multiplexor being in state |i>)
|
||||
remains,\
|
||||
add_theta,\
|
||||
add_phi = InitializeGate._bloch_angles(
|
||||
local_param[2*i : 2*(i + 1)])
|
||||
(remains,
|
||||
add_theta,
|
||||
add_phi) = InitializeGate._bloch_angles(
|
||||
local_param[2*i: 2*(i + 1)])
|
||||
|
||||
remaining_vector.append(remains)
|
||||
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Standard gates."""
|
||||
from .barrier import barrier
|
||||
from .ccx import ccx
|
||||
from .cswap import cswap
|
||||
|
|
|
@ -23,6 +23,7 @@ from qiskit import QuantumCircuit
|
|||
from qiskit import CompositeGate
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions._extensionerror import ExtensionError
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class Barrier(Instruction):
|
||||
|
@ -57,12 +58,12 @@ class Barrier(Instruction):
|
|||
def barrier(self, *tuples):
|
||||
"""Apply barrier to tuples (reg, idx)."""
|
||||
tuples = list(tuples)
|
||||
if len(tuples) == 0: # TODO: implement this for all single qubit gates
|
||||
if not tuples: # TODO: implement this for all single qubit gates
|
||||
if isinstance(self, QuantumCircuit):
|
||||
for register in self.regs.values():
|
||||
if isinstance(register, QuantumRegister):
|
||||
tuples.append(register)
|
||||
if len(tuples) == 0:
|
||||
if not tuples:
|
||||
raise ExtensionError("no arguments passed")
|
||||
qubits = []
|
||||
for tuple_element in tuples:
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
"""
|
||||
Toffoli gate. Controlled-Controlled-X.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class ToffoliGate(Gate):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,13 @@
|
|||
"""
|
||||
controlled-H gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CHGate(Gate):
|
||||
"""controlled-H gate."""
|
||||
|
@ -57,11 +59,11 @@ def ch(self, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.ch((ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CHGate(ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CHGate(ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.ch = ch
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
"""
|
||||
controlled-rz gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CrzGate(Gate):
|
||||
"""controlled-rz gate."""
|
||||
|
@ -38,7 +39,7 @@ class CrzGate(Gate):
|
|||
tgt = self.arg[1]
|
||||
theta = self.param[0]
|
||||
return self._qasmif("crz(%s) %s[%d],%s[%d];" % (theta, ctl[0].name, ctl[1],
|
||||
tgt[0].name, tgt[1]))
|
||||
tgt[0].name, tgt[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate."""
|
||||
|
@ -59,11 +60,11 @@ def crz(self, theta, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.crz(theta, (ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CrzGate(theta, ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CrzGate(theta, ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.crz = crz
|
||||
|
|
|
@ -18,10 +18,9 @@
|
|||
"""
|
||||
Fredkin gate. Controlled-SWAP.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import cx, ccx
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class FredkinGate(CompositeGate):
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
"""
|
||||
controlled-u1 gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class Cu1Gate(Gate):
|
||||
|
@ -39,7 +39,7 @@ class Cu1Gate(Gate):
|
|||
tgt = self.arg[1]
|
||||
theta = self.param[0]
|
||||
return self._qasmif("cu1(%s) %s[%d],%s[%d];" % (theta, ctl[0].name, ctl[1],
|
||||
tgt[0].name, tgt[1]))
|
||||
tgt[0].name, tgt[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate."""
|
||||
|
@ -60,11 +60,11 @@ def cu1(self, theta, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.cu1(theta, (ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(Cu1Gate(theta, ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(Cu1Gate(theta, ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.cu1 = cu1
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
"""
|
||||
controlled-u3 gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class Cu3Gate(Gate):
|
||||
|
@ -41,8 +41,8 @@ class Cu3Gate(Gate):
|
|||
phi = self.param[1]
|
||||
lam = self.param[2]
|
||||
return self._qasmif("cu3(%s,%s,%s) %s[%d],%s[%d];" % (theta, phi, lam,
|
||||
ctl[0].name, ctl[1],
|
||||
tgt[0].name, tgt[1]))
|
||||
ctl[0].name, ctl[1],
|
||||
tgt[0].name, tgt[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate."""
|
||||
|
@ -54,7 +54,8 @@ class Cu3Gate(Gate):
|
|||
|
||||
def reapply(self, circ):
|
||||
"""Reapply this gate to corresponding qubits in circ."""
|
||||
self._modifiers(circ.cu3(self.param[0], self.param[1], self.param[2], self.arg[0], self.arg[1]))
|
||||
self._modifiers(circ.cu3(self.param[0], self.param[1],
|
||||
self.param[2], self.arg[0], self.arg[1]))
|
||||
|
||||
|
||||
def cu3(self, theta, phi, lam, ctl, tgt):
|
||||
|
@ -66,11 +67,11 @@ def cu3(self, theta, phi, lam, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.cu3(theta, phi, lam, (ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(Cu3Gate(theta, phi, lam, ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(Cu3Gate(theta, phi, lam, ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.cu3 = cu3
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
controlled-NOT gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CnotGate(Gate):
|
||||
|
@ -58,11 +59,11 @@ def cx(self, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.cx((ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CnotGate(ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CnotGate(ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.cx = cx
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
"""
|
||||
Fundamental controlled-NOT gate.
|
||||
"""
|
||||
from qiskit import Instruction
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CXBase(Gate):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,13 @@
|
|||
"""
|
||||
controlled-Y gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CyGate(Gate):
|
||||
"""controlled-Y gate."""
|
||||
|
@ -57,11 +59,11 @@ def cy(self, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.cy((ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CyGate(ctl, tgt, self))
|
||||
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CyGate(ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.cy = cy
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -17,12 +18,13 @@
|
|||
"""
|
||||
controlled-Phase gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit._instructionset import InstructionSet
|
||||
from qiskit._quantumregister import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class CzGate(Gate):
|
||||
"""controlled-Z gate."""
|
||||
|
@ -56,11 +58,10 @@ def cz(self, ctl, tgt):
|
|||
for i in range(ctl.size):
|
||||
instructions.add(self.cz((ctl, i), (tgt, i)))
|
||||
return instructions
|
||||
else:
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CzGate(ctl, tgt, self))
|
||||
self._check_qubit(ctl)
|
||||
self._check_qubit(tgt)
|
||||
self._check_dups([ctl, tgt])
|
||||
return self._attach(CzGate(ctl, tgt, self))
|
||||
|
||||
|
||||
QuantumCircuit.cz = cz
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -14,17 +15,20 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
"""Gates tools."""
|
||||
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
def attach_gate(element, quantum_register, gate, gate_class):
|
||||
"""Attach a gate."""
|
||||
if isinstance(quantum_register, QuantumRegister):
|
||||
gs = InstructionSet()
|
||||
for register in range(quantum_register.size):
|
||||
for _ in range(quantum_register.size):
|
||||
gs.add(gate)
|
||||
return gs
|
||||
else:
|
||||
element._check_qubit(quantum_register)
|
||||
return element._attach(gate_class)
|
||||
|
||||
element._check_qubit(quantum_register)
|
||||
return element._attach(gate_class)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Hadamard gate.
|
||||
"""
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class HGate(Gate):
|
||||
|
@ -54,9 +55,9 @@ def h(self, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.h((q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(HGate(q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(HGate(q, self))
|
||||
|
||||
|
||||
QuantumCircuit.h = h
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Identity gate.
|
||||
"""
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class IdGate(Gate):
|
||||
|
@ -54,9 +55,9 @@ def iden(self, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.iden((q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(IdGate(q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(IdGate(q, self))
|
||||
|
||||
|
||||
QuantumCircuit.iden = iden
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Rotation around the x-axis.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class RXGate(Gate):
|
||||
|
@ -38,7 +39,7 @@ class RXGate(Gate):
|
|||
qubit = self.arg[0]
|
||||
theta = self.param[0]
|
||||
return self._qasmif("rx(%s) %s[%d];" % (theta, qubit[0].name,
|
||||
qubit[1]))
|
||||
qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -60,9 +61,9 @@ def rx(self, theta, q):
|
|||
for j in range(q.sz):
|
||||
gs.add(self.rx(theta, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(RXGate(theta, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(RXGate(theta, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.rx = rx
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,13 @@
|
|||
"""
|
||||
Rotation around the y-axis.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class RYGate(Gate):
|
||||
"""rotation around the y-axis."""
|
||||
|
@ -37,7 +39,7 @@ class RYGate(Gate):
|
|||
qubit = self.arg[0]
|
||||
theta = self.param[0]
|
||||
return self._qasmif("ry(%s) %s[%d];" % (theta, qubit[0].name,
|
||||
qubit[1]))
|
||||
qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -59,9 +61,9 @@ def ry(self, theta, q):
|
|||
for j in range(q.sz):
|
||||
gs.add(self.ry(theta, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(RYGate(theta, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(RYGate(theta, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.ry = ry
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Rotation around the z-axis.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class RZGate(Gate):
|
||||
|
@ -37,8 +38,7 @@ class RZGate(Gate):
|
|||
"""Return OPENQASM string."""
|
||||
qubit = self.arg[0]
|
||||
phi = self.param[0]
|
||||
return self._qasmif("rz(%s) %s[%d];" % (phi, qubit[0].name,
|
||||
qubit[1]))
|
||||
return self._qasmif("rz(%s) %s[%d];" % (phi, qubit[0].name, qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -60,9 +60,9 @@ def rz(self, phi, q):
|
|||
for j in range(q.sz):
|
||||
gs.add(self.rx(phi, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(RZGate(phi, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(RZGate(phi, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.rz = rz
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,13 +19,12 @@
|
|||
"""
|
||||
S=diag(1,i) Clifford phase gate or its inverse.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.qasm import pi
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import u1
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class SGate(CompositeGate):
|
||||
|
@ -45,8 +45,8 @@ class SGate(CompositeGate):
|
|||
phi = self.data[0].param[0]
|
||||
if phi > 0:
|
||||
return self.data[0]._qasmif("s %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
else:
|
||||
return self.data[0]._qasmif("sdg %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
|
||||
return self.data[0]._qasmif("sdg %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
|
||||
|
||||
def s(self, q):
|
||||
|
@ -56,9 +56,9 @@ def s(self, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.s((q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(SGate(q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(SGate(q, self))
|
||||
|
||||
|
||||
def sdg(self, q):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,10 +19,10 @@
|
|||
"""
|
||||
SWAP gate.
|
||||
"""
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class SwapGate(Gate):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,13 +19,12 @@
|
|||
"""
|
||||
T=sqrt(S) phase gate or its inverse.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.qasm import pi
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import u1
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class TGate(CompositeGate):
|
||||
|
@ -45,8 +45,8 @@ class TGate(CompositeGate):
|
|||
phi = self.data[0].param[0]
|
||||
if phi > 0:
|
||||
return self.data[0]._qasmif("t %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
else:
|
||||
return self.data[0]._qasmif("tdg %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
|
||||
return self.data[0]._qasmif("tdg %s[%d];" % (qubit[0].name, qubit[1]))
|
||||
|
||||
|
||||
def t(self, q):
|
||||
|
@ -56,9 +56,9 @@ def t(self, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.t((q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(TGate(q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(TGate(q, self))
|
||||
|
||||
|
||||
def tdg(self, q):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Diagonal single qubit gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class U1Gate(Gate):
|
||||
|
@ -37,8 +38,8 @@ class U1Gate(Gate):
|
|||
"""Return OPENQASM string."""
|
||||
qubit = self.arg[0]
|
||||
theta = self.param[0]
|
||||
return self._qasmif("u1(%s) %s[%d];" % (theta, qubit[0].name,
|
||||
qubit[1]))
|
||||
return self._qasmif("u1(%s) %s[%d];" % (
|
||||
theta, qubit[0].name, qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate."""
|
||||
|
@ -57,9 +58,9 @@ def u1(self, theta, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.u1(theta, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(U1Gate(theta, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(U1Gate(theta, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.u1 = u1
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,13 +19,13 @@
|
|||
"""
|
||||
One-pulse single-qubit gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.qasm import pi
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class U2Gate(Gate):
|
||||
|
@ -40,8 +41,8 @@ class U2Gate(Gate):
|
|||
phi = self.param[0]
|
||||
lam = self.param[1]
|
||||
return self._qasmif("u2(%s,%s) %s[%d];" % (phi, lam,
|
||||
qubit[0].name,
|
||||
qubit[1]))
|
||||
qubit[0].name,
|
||||
qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -65,9 +66,9 @@ def u2(self, phi, lam, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.u2(phi, lam, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(U2Gate(phi, lam, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(U2Gate(phi, lam, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.u2 = u2
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Two-pulse single-qubit gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit import CompositeGate
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class U3Gate(Gate):
|
||||
|
@ -40,8 +41,8 @@ class U3Gate(Gate):
|
|||
phi = self.param[1]
|
||||
lam = self.param[2]
|
||||
return self._qasmif("u3(%s,%s,%s) %s[%d];" % (theta, phi, lam,
|
||||
qubit[0].name,
|
||||
qubit[1]))
|
||||
qubit[0].name,
|
||||
qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -67,9 +68,9 @@ def u3(self, theta, phi, lam, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.u3(theta, phi, lam, (q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(U3Gate(theta, phi, lam, q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(U3Gate(theta, phi, lam, q, self))
|
||||
|
||||
|
||||
QuantumCircuit.u3 = u3
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,10 +19,11 @@
|
|||
"""
|
||||
Element of SU(2).
|
||||
"""
|
||||
from qiskit import Gate
|
||||
from qiskit.extensions._extensionerror import ExtensionError
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit.extensions._extensionerror import ExtensionError
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class UBase(Gate):
|
||||
|
@ -39,8 +41,8 @@ class UBase(Gate):
|
|||
phi = self.param[1]
|
||||
lamb = self.param[2]
|
||||
qubit = self.arg[0]
|
||||
return self._qasmif("U(%s,%s,%s) %s[%d];" % (theta, phi,
|
||||
lamb, qubit[0].name, qubit[1]))
|
||||
return self._qasmif("U(%s,%s,%s) %s[%d];" % (
|
||||
theta, phi, lamb, qubit[0].name, qubit[1]))
|
||||
|
||||
def inverse(self):
|
||||
"""Invert this gate.
|
||||
|
@ -55,7 +57,7 @@ class UBase(Gate):
|
|||
|
||||
def reapply(self, circ):
|
||||
"""Reapply this gate to corresponding qubits in circ."""
|
||||
self._modifiers(circ.u_base(self.param,self.arg[0]))
|
||||
self._modifiers(circ.u_base(self.param, self.arg[0]))
|
||||
|
||||
|
||||
def u_base(self, tpl, q):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Pauli X (bit-flip) gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class XGate(Gate):
|
||||
|
@ -54,9 +55,9 @@ def x(self, q):
|
|||
for j in range(q.size):
|
||||
gs.add(self.x((q, j)))
|
||||
return gs
|
||||
else:
|
||||
self._check_qubit(q)
|
||||
return self._attach(XGate(q, self))
|
||||
|
||||
self._check_qubit(q)
|
||||
return self._attach(XGate(q, self))
|
||||
|
||||
|
||||
QuantumCircuit.x = x
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Pauli Y (bit-phase-flip) gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class YGate(Gate):
|
||||
|
@ -54,9 +55,9 @@ def y(self, quantum_register):
|
|||
for register in range(quantum_register.size):
|
||||
intructions.add(self.y((quantum_register, register)))
|
||||
return intructions
|
||||
else:
|
||||
self._check_qubit(quantum_register)
|
||||
return self._attach(YGate(quantum_register, self))
|
||||
|
||||
self._check_qubit(quantum_register)
|
||||
return self._attach(YGate(quantum_register, self))
|
||||
|
||||
|
||||
QuantumCircuit.y = y
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -18,12 +19,12 @@
|
|||
"""
|
||||
Pauli Z (phase-flip) gate.
|
||||
"""
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import Gate
|
||||
from qiskit import CompositeGate
|
||||
from qiskit import Gate
|
||||
from qiskit import InstructionSet
|
||||
from qiskit.extensions.standard import header
|
||||
from qiskit import QuantumCircuit
|
||||
from qiskit import QuantumRegister
|
||||
from qiskit.extensions.standard import header # pylint: disable=unused-import
|
||||
|
||||
|
||||
class ZGate(Gate):
|
||||
|
@ -54,9 +55,9 @@ def z(self, quantum_register):
|
|||
for register in range(quantum_register.size):
|
||||
intructions.add(self.z((quantum_register, register)))
|
||||
return intructions
|
||||
else:
|
||||
self._check_qubit(quantum_register)
|
||||
return self._attach(ZGate(quantum_register, self))
|
||||
|
||||
self._check_qubit(quantum_register)
|
||||
return self._attach(ZGate(quantum_register, self))
|
||||
|
||||
|
||||
QuantumCircuit.z = z
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
from ._coupling import Coupling, coupling_dict2list, coupling_list2dict
|
||||
from ._mapping import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Utils for mapping."""
|
||||
|
||||
from ._compiling import two_qubit_kak, euler_angles_1q
|
||||
from ._coupling import Coupling, coupling_dict2list, coupling_list2dict
|
||||
from ._mappererror import MapperError
|
||||
from ._mapping import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
Methods to assist with compiling tasks.
|
||||
"""
|
||||
import math
|
||||
import scipy
|
||||
|
||||
import numpy as np
|
||||
from scipy.linalg import expm
|
||||
|
||||
|
|
|
@ -20,11 +20,13 @@ Exception for errors raised by the Coupling object.
|
|||
"""
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class CouplingError(QISKitError):
|
||||
"""Base class for errors raised by the coupling graph object."""
|
||||
|
||||
def __init__(self, *msg):
|
||||
"""Set the error message."""
|
||||
super(CouplingError, self).__init__(*msg)
|
||||
self.msg = ' '.join(msg)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -21,11 +21,13 @@ Exception for errors raised by mapper module.
|
|||
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class MapperError(QISKitError):
|
||||
"""Base class for errors raised by mapper module."""
|
||||
|
||||
def __init__(self, *message):
|
||||
"""Set the error message."""
|
||||
super(MapperError, self).__init__(*message)
|
||||
self.message = ' '.join(message)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: disable=invalid-name, inconsistent-return-statements
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -19,17 +19,19 @@
|
|||
"""
|
||||
Layout module to assist with mapping circuit qubits onto physical qubits.
|
||||
"""
|
||||
import sys
|
||||
import copy
|
||||
import logging
|
||||
import pprint
|
||||
import sys
|
||||
|
||||
import networkx as nx
|
||||
import numpy as np
|
||||
import sympy
|
||||
from sympy import Number as N
|
||||
import numpy as np
|
||||
import networkx as nx
|
||||
import pprint
|
||||
from ._mappererror import MapperError
|
||||
from qiskit.qasm import Qasm
|
||||
|
||||
import qiskit.unroll as unroll
|
||||
from qiskit.qasm import Qasm
|
||||
from ._mappererror import MapperError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -44,7 +46,8 @@ logger = logging.getLogger(__name__)
|
|||
# because the initial state is zero. We don't do this.
|
||||
|
||||
|
||||
def layer_permutation(layer_partition, layout, qubit_subset, coupling, trials, seed=None):
|
||||
def layer_permutation(layer_partition, layout, qubit_subset, coupling, trials,
|
||||
seed=None):
|
||||
"""Find a swap circuit that implements a permutation for this layer.
|
||||
|
||||
The goal is to swap qubits such that qubits in the same two-qubit gates
|
||||
|
@ -96,7 +99,7 @@ def layer_permutation(layer_partition, layout, qubit_subset, coupling, trials, s
|
|||
if dist == len(gates):
|
||||
logger.debug("layer_permutation: done already")
|
||||
logger.debug("layer_permutation: ----- exit -----")
|
||||
return True, "", 0, layout, len(gates) == 0
|
||||
return True, "", 0, layout, bool(gates)
|
||||
|
||||
# Begin loop over trials of randomized algorithm
|
||||
n = coupling.size()
|
||||
|
@ -203,10 +206,10 @@ def layer_permutation(layer_partition, layout, qubit_subset, coupling, trials, s
|
|||
logger.debug("layer_permutation: failed!")
|
||||
logger.debug("layer_permutation: ----- exit -----")
|
||||
return False, None, None, None, False
|
||||
else:
|
||||
logger.debug("layer_permutation: done")
|
||||
logger.debug("layer_permutation: ----- exit -----")
|
||||
return True, best_circ, best_d, best_layout, False
|
||||
|
||||
logger.debug("layer_permutation: done")
|
||||
logger.debug("layer_permutation: ----- exit -----")
|
||||
return True, best_circ, best_d, best_layout, False
|
||||
|
||||
|
||||
def direction_mapper(circuit_graph, coupling_graph):
|
||||
|
@ -256,7 +259,7 @@ def direction_mapper(circuit_graph, coupling_graph):
|
|||
cxedge[1][0], cxedge[1][1])
|
||||
else:
|
||||
raise MapperError("circuit incompatible with CouplingGraph: "
|
||||
"cx on %s", pprint.pformat(cxedge))
|
||||
"cx on %s" % pprint.pformat(cxedge))
|
||||
return circuit_graph
|
||||
|
||||
|
||||
|
@ -317,16 +320,20 @@ def swap_mapper(circuit_graph, coupling_graph,
|
|||
coupling_graph (CouplingGraph): coupling graph to map onto
|
||||
initial_layout (dict): dict from qubits of circuit_graph to qubits
|
||||
of coupling_graph (optional)
|
||||
basis (str, optional): basis string specifying basis of output
|
||||
DAGCircuit
|
||||
basis (str): basis string specifying basis of output DAGCircuit
|
||||
trials (int): number of trials.
|
||||
seed (int): initial seed.
|
||||
|
||||
Returns:
|
||||
Returns a DAGCircuit object containing a circuit equivalent to
|
||||
DAGCircuit: object containing a circuit equivalent to
|
||||
circuit_graph that respects couplings in coupling_graph, and
|
||||
a layout dict mapping qubits of circuit_graph into qubits
|
||||
of coupling_graph. The layout may differ from the initial_layout
|
||||
if the first layer of gates cannot be executed on the
|
||||
initial_layout.
|
||||
Raises:
|
||||
MapperError: if there was any error during the mapping or with the
|
||||
parameters.
|
||||
"""
|
||||
if circuit_graph.width() > coupling_graph.size():
|
||||
raise MapperError("Not enough qubits in CouplingGraph")
|
||||
|
@ -471,15 +478,16 @@ def test_trig_solution(theta, phi, lamb, xi, theta1, theta2):
|
|||
http://docs.sympy.org/latest/modules/functions/elementary.html?highlight=max
|
||||
"""
|
||||
delta1 = sympy.cos(phi + lamb) * sympy.cos(theta) - \
|
||||
sympy.cos(xi) * sympy.cos(theta1 + theta2)
|
||||
sympy.cos(xi) * sympy.cos(theta1 + theta2)
|
||||
delta2 = sympy.sin(phi + lamb) * sympy.cos(theta) - \
|
||||
sympy.sin(xi) * sympy.cos(theta1 - theta2)
|
||||
sympy.sin(xi) * sympy.cos(theta1 - theta2)
|
||||
delta3 = sympy.cos(phi - lamb) * sympy.sin(theta) - \
|
||||
sympy.cos(xi) * sympy.sin(theta1 + theta2)
|
||||
sympy.cos(xi) * sympy.sin(theta1 + theta2)
|
||||
delta4 = sympy.sin(phi - lamb) * sympy.sin(theta) - \
|
||||
sympy.sin(xi) * sympy.sin(-theta1 + theta2)
|
||||
sympy.sin(xi) * sympy.sin(-theta1 + theta2)
|
||||
|
||||
[delta1, delta2, delta3, delta4] = map(lambda x: sympy.Abs(x.simplify()), [delta1, delta2, delta3, delta4])
|
||||
[delta1, delta2, delta3, delta4] = map(lambda x: sympy.Abs(x.simplify()),
|
||||
[delta1, delta2, delta3, delta4])
|
||||
|
||||
return sympy.Max(delta1, delta2, delta3, delta4)
|
||||
|
||||
|
@ -564,6 +572,7 @@ def yzy_to_zyz(xi, theta1, theta2, eps=1e-9):
|
|||
solutions.append((sympy.acos(sympy.cos(xi) * sympy.cos(theta1 + theta2) /
|
||||
sympy.cos(sphi + slam + sympy.pi)),
|
||||
sphi + sympy.pi, slam))
|
||||
|
||||
# Select the first solution with the required accuracy
|
||||
deltas = list(map(lambda x: test_trig_solution(x[0], x[1], x[2],
|
||||
xi, theta1, theta2),
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Tools for QASM."""
|
||||
|
||||
from sympy import pi
|
||||
|
||||
from ._qasm import Qasm
|
||||
from ._qasmerror import QasmError
|
||||
from sympy import pi
|
|
@ -1,3 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""QASM nodes."""
|
||||
from ._barrier import Barrier
|
||||
from ._binaryop import BinaryOp
|
||||
from ._binaryoperator import BinaryOperator
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
"""
|
||||
Node for an OPENQASM binary operation expression.
|
||||
"""
|
||||
from ._node import Node
|
||||
import sympy
|
||||
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class BinaryOp(Node):
|
||||
"""Node for an OPENQASM binary operation expression.
|
||||
|
@ -41,6 +42,7 @@ class BinaryOp(Node):
|
|||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
"""Return the corresponding math mode latex string."""
|
||||
# pylint: disable=unused-argument
|
||||
# TODO prec ignored
|
||||
return sympy.latex(self.sym(nested_scope))
|
||||
|
||||
|
|
|
@ -54,4 +54,6 @@ class BinaryOperator(Node):
|
|||
self.value)
|
||||
|
||||
def qasm(self, prec=15):
|
||||
"""Return the QASM representation."""
|
||||
# pylint: disable=unused-argument
|
||||
return self.value
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -41,6 +41,7 @@ class External(Node):
|
|||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
"""Return the corresponding math mode latex string."""
|
||||
# pylint: disable=unused-argument
|
||||
# TODO prec ignored
|
||||
return sympy.latex(self.sym(nested_scope))
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
|
|
@ -31,6 +31,7 @@ class Id(Node):
|
|||
|
||||
def __init__(self, id, line, file):
|
||||
"""Create the id node."""
|
||||
# pylint: disable=redefined-builtin
|
||||
Node.__init__(self, "id", None, None)
|
||||
self.name = id
|
||||
self.line = line
|
||||
|
@ -46,6 +47,7 @@ class Id(Node):
|
|||
|
||||
def qasm(self, prec=15):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
# pylint: disable=unused-argument
|
||||
return self.name
|
||||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
|
@ -65,19 +67,17 @@ class Id(Node):
|
|||
def sym(self, nested_scope=None):
|
||||
"""Return the correspond symbolic number."""
|
||||
if not nested_scope or self.name not in nested_scope[-1]:
|
||||
raise NodeException("Expected local parameter name: ",
|
||||
"name=%s, " % self.name,
|
||||
"line=%s, " % self.line,
|
||||
"file=%s" % self.file)
|
||||
raise NodeException("Expected local parameter name: ",
|
||||
"name=%s, line=%s, file=%s" % (
|
||||
self.name, self.line, self.file))
|
||||
else:
|
||||
return nested_scope[-1][self.name].sym(nested_scope[0:-1])
|
||||
|
||||
def real(self, nested_scope=None):
|
||||
"""Return the correspond floating point number."""
|
||||
if not nested_scope or self.name not in nested_scope[-1]:
|
||||
raise NodeException("Expected local parameter name: ",
|
||||
"name=%s, " % self.name,
|
||||
"line=%s, " % self.line,
|
||||
"file=%s" % self.file)
|
||||
raise NodeException("Expected local parameter name: ",
|
||||
"name=%s, line=%s, file=%s" % (
|
||||
self.name, self.line, self.file))
|
||||
else:
|
||||
return nested_scope[-1][self.name].real(nested_scope[0:-1])
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -44,4 +45,5 @@ class IndexedId(Node):
|
|||
|
||||
def qasm(self, prec=15):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
# pylint: disable=unused-argument
|
||||
return self.name + "[%d]" % self.index
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
"""
|
||||
Node for an OPENQASM integer.
|
||||
"""
|
||||
from ._node import Node
|
||||
from sympy import N
|
||||
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Int(Node):
|
||||
"""Node for an OPENQASM integer.
|
||||
|
||||
|
@ -29,6 +31,7 @@ class Int(Node):
|
|||
|
||||
def __init__(self, id):
|
||||
"""Create the integer node."""
|
||||
# pylint: disable=redefined-builtin
|
||||
Node.__init__(self, "int", None, None)
|
||||
self.value = id
|
||||
|
||||
|
@ -39,16 +42,20 @@ class Int(Node):
|
|||
|
||||
def qasm(self, prec=15):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
# pylint: disable=unused-argument
|
||||
return "%d" % self.value
|
||||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
"""Return the corresponding math mode latex string."""
|
||||
# pylint: disable=unused-argument
|
||||
return "%d" % self.value
|
||||
|
||||
def sym(self, nested_scope=None):
|
||||
"""Return the correspond symbolic number."""
|
||||
# pylint: disable=unused-argument
|
||||
return N(self.value)
|
||||
|
||||
def real(self, nested_scope=None):
|
||||
"""Return the correspond floating point number."""
|
||||
# pylint: disable=unused-argument
|
||||
return float(self.value)
|
||||
|
|
|
@ -33,4 +33,5 @@ class Magic(Node):
|
|||
|
||||
def qasm(self, prec=15):
|
||||
"""Return the corresponding OPENQASM string."""
|
||||
# pylint: disable=unused-argument
|
||||
return "OPENQASM %.1f;" % self.children[0].value
|
||||
|
|
|
@ -25,6 +25,7 @@ class Node(object):
|
|||
|
||||
def __init__(self, type, children=None, root=None):
|
||||
"""Construct a new node object."""
|
||||
# pylint: disable=redefined-builtin
|
||||
self.type = type
|
||||
if children:
|
||||
self.children = children
|
||||
|
|
|
@ -25,6 +25,7 @@ class NodeException(Exception):
|
|||
|
||||
def __init__(self, *msg):
|
||||
"""Set the error message."""
|
||||
super(NodeException, self).__init__(*msg)
|
||||
self.msg = ' '.join(msg)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
"""
|
||||
Node for an OPENQASM prefix expression.
|
||||
"""
|
||||
from ._node import Node
|
||||
import sympy
|
||||
|
||||
from ._node import Node
|
||||
|
||||
|
||||
class Prefix(Node):
|
||||
"""Node for an OPENQASM prefix expression.
|
||||
|
@ -39,6 +40,7 @@ class Prefix(Node):
|
|||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
"""Return the corresponding math mode latex string."""
|
||||
# pylint: disable=unused-argument
|
||||
# TODO prec ignored
|
||||
return sympy.latex(self.sym(nested_scope))
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
|
|
@ -31,6 +31,7 @@ class Real(Node):
|
|||
|
||||
def __init__(self, id):
|
||||
"""Create the real node."""
|
||||
# pylint: disable=redefined-builtin
|
||||
Node.__init__(self, "real", None, None)
|
||||
self.value = id
|
||||
|
||||
|
@ -43,17 +44,20 @@ class Real(Node):
|
|||
"""Return the corresponding OPENQASM string."""
|
||||
if self.value == pi:
|
||||
return "pi"
|
||||
else:
|
||||
return ccode(self.value, precision=prec)
|
||||
|
||||
return ccode(self.value, precision=prec)
|
||||
|
||||
def latex(self, prec=15, nested_scope=None):
|
||||
"""Return the corresponding math mode latex string."""
|
||||
# pylint: disable=unused-argument
|
||||
return latex(self.value)
|
||||
|
||||
def sym(self, nested_scope=None):
|
||||
"""Return the correspond symbolic number."""
|
||||
# pylint: disable=unused-argument
|
||||
return self.value
|
||||
|
||||
def real(self, nested_scope=None):
|
||||
"""Return the correspond floating point number."""
|
||||
# pylint: disable=unused-argument
|
||||
return float(self.value.evalf())
|
||||
|
|
|
@ -51,4 +51,6 @@ class UnaryOperator(Node):
|
|||
self.value)
|
||||
|
||||
def qasm(self, prec=15):
|
||||
"""Return QASM representation."""
|
||||
# pylint: disable=unused-argument
|
||||
return self.value
|
||||
|
|
|
@ -30,8 +30,8 @@ class Qasm(object):
|
|||
if filename is None and data is None:
|
||||
raise QasmError("Missing input file and/or data")
|
||||
if filename is not None and data is not None:
|
||||
raise QasmError("File and data must not both be"
|
||||
+ " specified initializing qasm")
|
||||
raise QasmError("File and data must not both be specified"
|
||||
"initializing qasm")
|
||||
self._filename = filename
|
||||
self._data = data
|
||||
|
||||
|
|
|
@ -21,11 +21,13 @@ Exception for errors raised while parsing OPENQASM.
|
|||
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class QasmError(QISKitError):
|
||||
"""Base class for errors raised while parsing OPENQASM."""
|
||||
|
||||
def __init__(self, *msg):
|
||||
"""Set the error message."""
|
||||
super(QasmError, self).__init__(*msg)
|
||||
self.msg = ' '.join(msg)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -23,11 +23,13 @@ by creating a stack of lexers.
|
|||
"""
|
||||
|
||||
import os
|
||||
|
||||
import ply.lex as lex
|
||||
from ._qasmerror import QasmError
|
||||
from . import _node as node
|
||||
from sympy import Number
|
||||
|
||||
from . import _node as node
|
||||
from ._qasmerror import QasmError
|
||||
|
||||
CORE_LIBS_PATH = os.path.join(os.path.dirname(__file__), 'libs')
|
||||
CORE_LIBS = os.listdir(CORE_LIBS_PATH)
|
||||
|
||||
|
@ -38,7 +40,8 @@ class QasmLexer(object):
|
|||
This is a wrapper around the PLY lexer to support the "include" statement
|
||||
by creating a stack of lexers.
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: disable=invalid-name,missing-docstring,unused-argument
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
||||
def __mklexer__(self, filename):
|
||||
"""Create a PLY lexer."""
|
||||
|
@ -127,37 +130,34 @@ class QasmLexer(object):
|
|||
|
||||
def t_INCLUDE(self, t):
|
||||
'include'
|
||||
|
||||
'''
|
||||
Now eat up the next two tokens which must be
|
||||
1 - the name of the include file, and
|
||||
2 - a terminating semicolon
|
||||
|
||||
Then push the current lexer onto the stack, create a new one from
|
||||
the include file, and push it onto the stack.
|
||||
|
||||
When we hit eof (the t_eof) rule, we pop.
|
||||
'''
|
||||
next = self.lexer.token()
|
||||
lineno = next.lineno
|
||||
#
|
||||
# Now eat up the next two tokens which must be
|
||||
# 1 - the name of the include file, and
|
||||
# 2 - a terminating semicolon
|
||||
#
|
||||
# Then push the current lexer onto the stack, create a new one from
|
||||
# the include file, and push it onto the stack.
|
||||
#
|
||||
# When we hit eof (the t_eof) rule, we pop.
|
||||
next_token = self.lexer.token()
|
||||
lineno = next_token.lineno
|
||||
# print('NEXT', next, "next.value", next.value, type(next))
|
||||
if isinstance(next.value, str):
|
||||
incfile = next.value.strip('"')
|
||||
if isinstance(next_token.value, str):
|
||||
incfile = next_token.value.strip('"')
|
||||
else:
|
||||
raise QasmError("Invalid include: must be a quoted string.")
|
||||
|
||||
if incfile in CORE_LIBS:
|
||||
incfile = os.path.join(CORE_LIBS_PATH, incfile)
|
||||
|
||||
next = self.lexer.token()
|
||||
if next is None or next.value != ';':
|
||||
raise QasmError('Invalid syntax, missing ";" at line',
|
||||
str(lineno))
|
||||
next_token = self.lexer.token()
|
||||
if next_token is None or next_token.value != ';':
|
||||
raise QasmError('Invalid syntax, missing ";" at line', str(lineno))
|
||||
|
||||
if not os.path.exists(incfile):
|
||||
raise QasmError('Include file', incfile,
|
||||
'cannot be found, line', str(next.lineno),
|
||||
', file', self.filename)
|
||||
raise QasmError(
|
||||
'Include file %s cannot be found, line %s, file %s' %
|
||||
(incfile, str(next_token.lineno), self.filename))
|
||||
self.push(incfile)
|
||||
return self.lexer.token()
|
||||
|
||||
|
@ -191,11 +191,10 @@ class QasmLexer(object):
|
|||
t.lexer.lineno = self.lineno
|
||||
|
||||
def t_eof(self, t):
|
||||
if len(self.stack) > 0:
|
||||
if self.stack:
|
||||
self.pop()
|
||||
return self.lexer.token()
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
t_ignore = ' \t\r'
|
||||
|
||||
|
|
|
@ -19,20 +19,22 @@
|
|||
OPENQASM parser.
|
||||
"""
|
||||
import os
|
||||
import sympy
|
||||
import tempfile
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import ply.yacc as yacc
|
||||
import sympy
|
||||
|
||||
from ._qasmlexer import QasmLexer
|
||||
from ._qasmerror import QasmError
|
||||
from . import _node as node
|
||||
from ._qasmerror import QasmError
|
||||
from ._qasmlexer import QasmLexer
|
||||
|
||||
|
||||
class QasmParser(object):
|
||||
"""OPENQASM Parser."""
|
||||
|
||||
# pylint: disable=unused-argument,missing-docstring,invalid-name
|
||||
|
||||
def __init__(self, filename):
|
||||
"""Create the parser."""
|
||||
if filename is None:
|
||||
|
@ -41,10 +43,10 @@ class QasmParser(object):
|
|||
self.tokens = self.lexer.tokens
|
||||
self.parse_dir = tempfile.mkdtemp(prefix='qiskit')
|
||||
self.precedence = (
|
||||
('left', '+', '-'),
|
||||
('left', '*', '/'),
|
||||
('left', 'negative', 'positive'),
|
||||
('right', '^'))
|
||||
('left', '+', '-'),
|
||||
('left', '*', '/'),
|
||||
('left', 'negative', 'positive'),
|
||||
('right', '^'))
|
||||
# For yacc, also, write_tables = Bool and optimize = Bool
|
||||
self.parser = yacc.yacc(module=self, debug=False,
|
||||
outputdir=self.parse_dir)
|
||||
|
@ -53,7 +55,8 @@ class QasmParser(object):
|
|||
self.global_symtab = {} # global symtab
|
||||
self.current_symtab = self.global_symtab # top of symbol stack
|
||||
self.symbols = [] # symbol stack
|
||||
self.external_functions = ['sin', 'cos', 'tan', 'exp', 'ln', 'sqrt','acos','atan','asin']
|
||||
self.external_functions = ['sin', 'cos', 'tan', 'exp', 'ln', 'sqrt',
|
||||
'acos', 'atan', 'asin']
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
@ -173,8 +176,9 @@ class QasmParser(object):
|
|||
|
||||
if g_sym.type != object_type:
|
||||
raise QasmError("Type for '" + g_sym.name + "' should be '"
|
||||
+ object_type + "' but was found to be '" + g_sym.type
|
||||
+ "'", "line", str(obj.line), "file", obj.file)
|
||||
+ object_type + "' but was found to be '"
|
||||
+ g_sym.type + "'", "line", str(obj.line),
|
||||
"file", obj.file)
|
||||
|
||||
if obj.type == 'indexed_id':
|
||||
bound = g_sym.index
|
||||
|
@ -456,8 +460,8 @@ class QasmParser(object):
|
|||
"""
|
||||
if len(program) > 2:
|
||||
if program[2] != ';':
|
||||
raise QasmError("Missing ';' in qreg or creg declaraton."
|
||||
+ " Instead received '" + program[2].value + "'")
|
||||
raise QasmError("Missing ';' in qreg or creg declaration."
|
||||
" Instead received '" + program[2].value + "'")
|
||||
program[0] = program[1]
|
||||
|
||||
# ----------------------------------------
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
"""Unroll QASM and different backends."""
|
||||
from ._unroller import Unroller
|
||||
from ._dagbackend import DAGBackend
|
||||
from ._printerbackend import PrinterBackend
|
||||
|
|
|
@ -21,11 +21,13 @@ Exception for errors raised by unroller backends.
|
|||
|
||||
from qiskit import QISKitError
|
||||
|
||||
|
||||
class BackendError(QISKitError):
|
||||
"""Base class for errors raised by unroller backends."""
|
||||
|
||||
def __init__(self, *message):
|
||||
"""Set the error message."""
|
||||
super(BackendError, self).__init__(*message)
|
||||
self.message = ' '.join(message)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -18,15 +18,12 @@
|
|||
"""
|
||||
Backend for the unroller that produces a QuantumCircuit.
|
||||
"""
|
||||
|
||||
from ._backenderror import BackendError
|
||||
from ._unrollerbackend import UnrollerBackend
|
||||
from .._quantumregister import QuantumRegister
|
||||
from .._classicalregister import ClassicalRegister
|
||||
from .._quantumcircuit import QuantumCircuit
|
||||
|
||||
import sys
|
||||
sys.path.append("../..")
|
||||
import qiskit.extensions.standard
|
||||
from .._quantumregister import QuantumRegister
|
||||
|
||||
|
||||
class CircuitBackend(UnrollerBackend):
|
||||
|
@ -40,6 +37,7 @@ class CircuitBackend(UnrollerBackend):
|
|||
|
||||
basis is a list of operation name strings.
|
||||
"""
|
||||
super(CircuitBackend, self).__init__(basis)
|
||||
self.creg = None
|
||||
self.cval = None
|
||||
if basis:
|
||||
|
@ -72,8 +70,8 @@ class CircuitBackend(UnrollerBackend):
|
|||
sz = size of the register
|
||||
"""
|
||||
assert size >= 0, "invalid qreg size"
|
||||
q = QuantumRegister(name, size)
|
||||
self.circuit.add(q)
|
||||
q_register = QuantumRegister(name, size)
|
||||
self.circuit.add(q_register)
|
||||
|
||||
def new_creg(self, name, size):
|
||||
"""Create a new classical register.
|
||||
|
@ -82,8 +80,8 @@ class CircuitBackend(UnrollerBackend):
|
|||
sz = size of the register
|
||||
"""
|
||||
assert size >= 0, "invalid creg size"
|
||||
c = ClassicalRegister(name, size)
|
||||
self.circuit.add(c)
|
||||
c_register = ClassicalRegister(name, size)
|
||||
self.circuit.add(c_register)
|
||||
|
||||
def define_gate(self, name, gatedata):
|
||||
"""Define a new quantum gate.
|
||||
|
@ -246,11 +244,9 @@ class CircuitBackend(UnrollerBackend):
|
|||
"ry": [(1, 1), lambda x: self.circuit.ry(x[0][0], x[1][0])],
|
||||
"rz": [(1, 1), lambda x: self.circuit.rz(x[0][0], x[1][0])],
|
||||
"s": [(0, 1), lambda x: self.circuit.s(x[1][0])],
|
||||
"sdg": [(0, 1), lambda x: self.circuit.s(x[1][0]).inverse()
|
||||
],
|
||||
"sdg": [(0, 1), lambda x: self.circuit.s(x[1][0]).inverse()],
|
||||
"t": [(0, 1), lambda x: self.circuit.t(x[1][0]).inverse()],
|
||||
"tdg": [(0, 1), lambda x: self.circuit.t(x[1][0]).inverse()
|
||||
],
|
||||
"tdg": [(0, 1), lambda x: self.circuit.t(x[1][0]).inverse()],
|
||||
"u1": [(1, 1), lambda x: self.circuit.u1(x[0][0], x[1][0])],
|
||||
"u2": [(2, 1), lambda x: self.circuit.u2(x[0][0], x[0][1],
|
||||
x[1][0])],
|
||||
|
@ -258,17 +254,16 @@ class CircuitBackend(UnrollerBackend):
|
|||
x[0][2], x[1][0])],
|
||||
"x": [(0, 1), lambda x: self.circuit.x(x[1][0])],
|
||||
"y": [(0, 1), lambda x: self.circuit.y(x[1][0])],
|
||||
"z": [(0, 1), lambda x: self.circuit.z(x[1][0])],
|
||||
}
|
||||
"z": [(0, 1), lambda x: self.circuit.z(x[1][0])]}
|
||||
if name not in lut:
|
||||
raise BackendError("gate %s not in standard extensions" %
|
||||
name)
|
||||
name)
|
||||
gate_data = lut[name]
|
||||
if gate_data[0] != (len(args), len(qubits)):
|
||||
raise BackendError("gate %s signature (%d, %d) is " %
|
||||
(name, len(args), len(qubits)) +
|
||||
"incompatible with the standard " +
|
||||
"extensions")
|
||||
(name, len(args), len(qubits)) +
|
||||
"incompatible with the standard " +
|
||||
"extensions")
|
||||
this_gate = gate_data[1]([list(map(lambda x:
|
||||
x.sym(nested_scope), args)),
|
||||
list(map(self._map_qubit, qubits))])
|
||||
|
|
|
@ -31,6 +31,7 @@ class DAGBackend(UnrollerBackend):
|
|||
|
||||
basis is a list of operation name strings.
|
||||
"""
|
||||
super(DAGBackend, self).__init__(basis)
|
||||
self.prec = 15
|
||||
self.creg = None
|
||||
self.cval = None
|
||||
|
@ -135,9 +136,9 @@ class DAGBackend(UnrollerBackend):
|
|||
"""
|
||||
if self.listen:
|
||||
names = []
|
||||
for x in qubitlists:
|
||||
for j in range(len(x)):
|
||||
names.append(x[j])
|
||||
for qubit in qubitlists:
|
||||
for j, _ in enumerate(qubit):
|
||||
names.append(qubit[j])
|
||||
if "barrier" not in self.basis:
|
||||
self.basis.append("barrier")
|
||||
self.circuit.add_basis_element("barrier", -1)
|
||||
|
|
|
@ -44,7 +44,6 @@ The input is a AST and a basis set and returns a json memory object::
|
|||
]
|
||||
}
|
||||
"""
|
||||
import json
|
||||
from qiskit.unroll import BackendError
|
||||
from qiskit.unroll import UnrollerBackend
|
||||
|
||||
|
@ -58,6 +57,7 @@ class JsonBackend(UnrollerBackend):
|
|||
basis is a list of operation name strings.
|
||||
The default basis is ["U", "CX"].
|
||||
"""
|
||||
super(JsonBackend, self).__init__(basis)
|
||||
self.circuit = {}
|
||||
self.circuit['operations'] = []
|
||||
self.circuit['header'] = {}
|
||||
|
@ -193,7 +193,7 @@ class JsonBackend(UnrollerBackend):
|
|||
})
|
||||
self._add_condition()
|
||||
|
||||
def measure(self, qubit, cbit):
|
||||
def measure(self, qubit, bit):
|
||||
"""Measurement operation.
|
||||
|
||||
qubit is (regname, idx) tuple for the input qubit.
|
||||
|
@ -202,7 +202,7 @@ class JsonBackend(UnrollerBackend):
|
|||
if "measure" not in self.basis:
|
||||
self.basis.append("measure")
|
||||
qubit_indices = [self._qubit_order_internal.get(qubit)]
|
||||
clbit_indices = [self._cbit_order_internal.get(cbit)]
|
||||
clbit_indices = [self._cbit_order_internal.get(bit)]
|
||||
self.circuit['operations'].append({
|
||||
'name': 'measure',
|
||||
'qubits': qubit_indices,
|
||||
|
@ -310,5 +310,5 @@ class JsonBackend(UnrollerBackend):
|
|||
|
||||
def _is_circuit_valid(self):
|
||||
"""Checks whether the circuit object is a valid one or not."""
|
||||
return len(self.circuit['header']) > 0 \
|
||||
and len(self.circuit['operations']) > 0
|
||||
return (len(self.circuit['header']) > 0 and
|
||||
len(self.circuit['operations']) > 0)
|
||||
|
|
|
@ -33,6 +33,7 @@ class PrinterBackend(UnrollerBackend):
|
|||
|
||||
basis is a list of operation name strings.
|
||||
"""
|
||||
super(PrinterBackend, self).__init__(basis)
|
||||
self.prec = 15
|
||||
self.creg = None
|
||||
self.cval = None
|
||||
|
@ -235,7 +236,7 @@ class PrinterBackend(UnrollerBackend):
|
|||
if self.creg is not None:
|
||||
print("if(%s==%d) " % (self.creg, self.cval), end="")
|
||||
print(name, end="")
|
||||
if len(args) > 0:
|
||||
if args:
|
||||
print("(%s)" % ",".join(map(lambda x:
|
||||
str(x.sym(nested_scope)),
|
||||
args)), end="")
|
||||
|
|
|
@ -56,12 +56,13 @@ class Unroller(object):
|
|||
|
||||
Return a list of tuples (name,index).
|
||||
"""
|
||||
# pylint: disable=inconsistent-return-statements
|
||||
if node.type == "indexed_id":
|
||||
# An indexed bit or qubit
|
||||
return [(node.name, node.index)]
|
||||
elif node.type == "id":
|
||||
# A qubit or qreg or creg
|
||||
if len(self.bit_stack[-1]) == 0:
|
||||
if not self.bit_stack[-1]:
|
||||
# Global scope
|
||||
if node.name in self.qregs:
|
||||
return [(node.name, j)
|
||||
|
@ -69,18 +70,17 @@ class Unroller(object):
|
|||
elif node.name in self.cregs:
|
||||
return [(node.name, j)
|
||||
for j in range(self.cregs[node.name])]
|
||||
else:
|
||||
raise UnrollerError("expected qreg or creg name:",
|
||||
"line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
raise UnrollerError("expected qreg or creg name:",
|
||||
"line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
else:
|
||||
# local scope
|
||||
if node.name in self.bit_stack[-1]:
|
||||
return [self.bit_stack[-1][node.name]]
|
||||
else:
|
||||
raise UnrollerError("excepted local bit name:",
|
||||
"line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
raise UnrollerError("excepted local bit name:",
|
||||
"line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
return None
|
||||
|
||||
def _process_custom_unitary(self, node):
|
||||
"""Process a custom unitary node."""
|
||||
|
@ -101,8 +101,8 @@ class Unroller(object):
|
|||
self.arg_stack.append({gargs[j]: args[j]
|
||||
for j in range(len(gargs))})
|
||||
# Only index into register arguments.
|
||||
element = list(map(lambda x: idx * x,
|
||||
[len(bits[j]) > 1 for j in range(len(bits))]))
|
||||
element = [idx*x for x in
|
||||
[len(bits[j]) > 1 for j in range(len(bits))]]
|
||||
self.bit_stack.append({gbits[j]: bits[j][element[j]]
|
||||
for j in range(len(gbits))})
|
||||
self.backend.start_gate(name,
|
||||
|
@ -119,7 +119,7 @@ class Unroller(object):
|
|||
self.bit_stack.pop()
|
||||
else:
|
||||
raise UnrollerError("internal error undefined gate:",
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
|
||||
def _process_gate(self, node, opaque=False):
|
||||
"""Process a gate node.
|
||||
|
@ -127,20 +127,20 @@ class Unroller(object):
|
|||
If opaque is True, process the node as an opaque gate node.
|
||||
"""
|
||||
self.gates[node.name] = {}
|
||||
de = self.gates[node.name]
|
||||
de["opaque"] = opaque
|
||||
de["n_args"] = node.n_args()
|
||||
de["n_bits"] = node.n_bits()
|
||||
de_gate = self.gates[node.name]
|
||||
de_gate["opaque"] = opaque
|
||||
de_gate["n_args"] = node.n_args()
|
||||
de_gate["n_bits"] = node.n_bits()
|
||||
if node.n_args() > 0:
|
||||
de["args"] = [element.name for element in node.arguments.children]
|
||||
de_gate["args"] = [element.name for element in node.arguments.children]
|
||||
else:
|
||||
de["args"] = []
|
||||
de["bits"] = [c.name for c in node.bitlist.children]
|
||||
de_gate["args"] = []
|
||||
de_gate["bits"] = [c.name for c in node.bitlist.children]
|
||||
if opaque:
|
||||
de["body"] = None
|
||||
de_gate["body"] = None
|
||||
else:
|
||||
de["body"] = node.body
|
||||
self.backend.define_gate(node.name, copy.deepcopy(de))
|
||||
de_gate["body"] = node.body
|
||||
self.backend.define_gate(node.name, copy.deepcopy(de_gate))
|
||||
|
||||
def _process_cnot(self, node):
|
||||
"""Process a CNOT gate node."""
|
||||
|
@ -148,7 +148,7 @@ class Unroller(object):
|
|||
id1 = self._process_bit_id(node.children[1])
|
||||
if not(len(id0) == len(id1) or len(id0) == 1 or len(id1) == 1):
|
||||
raise UnrollerError("internal error: qreg size mismatch",
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
maxidx = max([len(id0), len(id1)])
|
||||
for idx in range(maxidx):
|
||||
if len(id0) > 1 and len(id1) > 1:
|
||||
|
@ -164,7 +164,7 @@ class Unroller(object):
|
|||
id1 = self._process_bit_id(node.children[1])
|
||||
if len(id0) != len(id1):
|
||||
raise UnrollerError("internal error: reg size mismatch",
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
"line=%s" % node.line, "file=%s" % node.file)
|
||||
for idx, idy in zip(id0, id1):
|
||||
self.backend.measure(idx, idy)
|
||||
|
||||
|
@ -252,8 +252,8 @@ class Unroller(object):
|
|||
|
||||
elif node.type == "reset":
|
||||
id0 = self._process_bit_id(node.children[0])
|
||||
for idx in range(len(id0)):
|
||||
self.backend.reset(id0[idx])
|
||||
for i, _ in enumerate(id0):
|
||||
self.backend.reset(id0[i])
|
||||
|
||||
elif node.type == "if":
|
||||
self._process_if(node)
|
||||
|
@ -266,8 +266,9 @@ class Unroller(object):
|
|||
|
||||
else:
|
||||
raise UnrollerError("internal error: undefined node type",
|
||||
node.type, "line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
node.type, "line=%s" % node.line,
|
||||
"file=%s" % node.file)
|
||||
return None
|
||||
|
||||
def set_backend(self, backend):
|
||||
"""Set the backend object."""
|
||||
|
|
|
@ -35,7 +35,6 @@ class UnrollerBackend(object):
|
|||
"""
|
||||
if basis:
|
||||
basis = []
|
||||
raise BackendError("Backend __init__ unimplemented")
|
||||
|
||||
def set_basis(self, basis):
|
||||
"""Declare the set of user-defined gates to emit.
|
||||
|
@ -83,6 +82,7 @@ class UnrollerBackend(object):
|
|||
nested_scope is a list of dictionaries mapping expression variables
|
||||
to Node expression objects in order of increasing nesting depth.
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
raise BackendError("Backend u unimplemented")
|
||||
|
||||
def cx(self, qubit0, qubit1):
|
||||
|
@ -91,6 +91,7 @@ class UnrollerBackend(object):
|
|||
qubit0 is (regname,idx) tuple for the control qubit.
|
||||
qubit1 is (regname,idx) tuple for the target qubit.
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
raise BackendError("Backend cx unimplemented")
|
||||
|
||||
def measure(self, qubit, bit):
|
||||
|
|
|
@ -27,6 +27,7 @@ class UnrollerError(QISKitError):
|
|||
|
||||
def __init__(self, *message):
|
||||
"""Set the error message."""
|
||||
super(UnrollerError, self).__init__(*message)
|
||||
self.message = ' '.join(message)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
|
@ -14,6 +14,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
"""QISKit unit tests."""
|
||||
|
||||
import os
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
"""Generate random circuits."""
|
||||
|
||||
import random
|
||||
|
||||
|
@ -35,29 +36,30 @@ def choices(population, weights=None, k=1):
|
|||
return numpy.random.choice(population, size=k, p=weights)
|
||||
|
||||
|
||||
class RandomCircuitGenerator():
|
||||
class RandomCircuitGenerator(object):
|
||||
"""
|
||||
Generate random size circuits for profiling.
|
||||
"""
|
||||
def __init__(self, seed=None,
|
||||
maxQubits=5, minQubits=1,
|
||||
maxDepth=100, minDepth=1):
|
||||
max_qubits=5, min_qubits=1,
|
||||
max_depth=100, min_depth=1):
|
||||
"""
|
||||
Args:
|
||||
seed (int): Random number seed. If none, don't seed the generator.
|
||||
minDepth int): Minimum number of operations in circuit.
|
||||
maxDepth (int): Maximum number of operations in a circuit.
|
||||
minQubits (int): Minimum number of operations in a cirucit.
|
||||
maxQubits (int): Maximum number of qubits in a circuit.
|
||||
max_qubits (int): Maximum number of qubits in a circuit.
|
||||
min_qubits (int): Minimum number of operations in a cirucit.
|
||||
max_depth (int): Maximum number of operations in a circuit.
|
||||
min_depth (int): Minimum number of operations in circuit.
|
||||
"""
|
||||
self.maxDepth = maxDepth
|
||||
self.maxQubits = maxQubits
|
||||
self.minDepth = minDepth
|
||||
self.minQubits = minQubits
|
||||
self.max_depth = max_depth
|
||||
self.max_qubits = max_qubits
|
||||
self.min_depth = min_depth
|
||||
self.min_qubits = min_qubits
|
||||
self.circuit_list = []
|
||||
self.nQubit_list = []
|
||||
self.n_qubit_list = []
|
||||
self.depth_list = []
|
||||
self.basis_gates = None
|
||||
self.circuit_name_list = []
|
||||
if seed is not None:
|
||||
random.seed(a=seed)
|
||||
# specify number of parameters and args for each op
|
||||
|
@ -65,7 +67,7 @@ class RandomCircuitGenerator():
|
|||
# maybe we can guess this. "nregs" are the number of qubits the
|
||||
# operation uses. If nregs=0 then it means either 1 qubit or
|
||||
# 1 register. "nparams" are the number of parameters the operation takes.
|
||||
self.opSignature = {
|
||||
self.op_signature = {
|
||||
'barrier': {'nregs': 0, 'nparams': None},
|
||||
'ccx': {'nregs': 3, 'nparams': None},
|
||||
'ch': {'nregs': 2, 'nparams': None},
|
||||
|
@ -82,7 +84,7 @@ class RandomCircuitGenerator():
|
|||
'reset': {'nregs': 1, 'nparams': None},
|
||||
'rx': {'nregs': 1, 'nparams': 1},
|
||||
'ry': {'nregs': 1, 'nparams': 1},
|
||||
'rz': {'nregs': 1, 'nparams': 1},
|
||||
'rz': {'nregs': 1, 'nparams': 1},
|
||||
's': {'nregs': 1, 'nparams': None},
|
||||
't': {'nregs': 1, 'nparams': None},
|
||||
'u1': {'nregs': 1, 'nparams': 1},
|
||||
|
@ -92,7 +94,7 @@ class RandomCircuitGenerator():
|
|||
'y': {'nregs': 1, 'nparams': None},
|
||||
'z': {'nregs': 1, 'nparams': None}}
|
||||
|
||||
def add_circuits(self, nCircuits, doMeasure=True, basis=None,
|
||||
def add_circuits(self, n_circuits, do_measure=True, basis=None,
|
||||
basis_weights=None):
|
||||
"""Adds circuits to program.
|
||||
|
||||
|
@ -101,19 +103,21 @@ class RandomCircuitGenerator():
|
|||
[1,nQubits] to end of circuit.
|
||||
|
||||
Args:
|
||||
nCircuits (int): Number of circuits to add.
|
||||
doMeasure (bool): Whether to add measurements.
|
||||
basis (list(str) | None): List of op names. If None, basis
|
||||
n_circuits (int): Number of circuits to add.
|
||||
do_measure (bool): Whether to add measurements.
|
||||
basis (list(str) or None): List of op names. If None, basis
|
||||
is randomly chosen with unique ops in (2,7)
|
||||
basis_weights (list of float or None): List of weights
|
||||
basis_weights (list(float) or None): List of weights
|
||||
corresponding to indices in `basis`.
|
||||
Raises:
|
||||
AttributeError: if operation is not recognized.
|
||||
"""
|
||||
if basis is None:
|
||||
basis = list(random.sample(self.opSignature.keys(),
|
||||
random.randint(2,7)))
|
||||
basis = list(random.sample(self.op_signature.keys(),
|
||||
random.randint(2, 7)))
|
||||
basis_weights = [1./len(basis)] * len(basis)
|
||||
if basis_weights is not None:
|
||||
assert(len(basis) == len(basis_weights))
|
||||
assert len(basis) == len(basis_weights)
|
||||
uop_basis = basis[:]
|
||||
if basis_weights:
|
||||
uop_basis_weights = basis_weights[:]
|
||||
|
@ -133,106 +137,106 @@ class RandomCircuitGenerator():
|
|||
del uop_basis_weights[ind]
|
||||
# self.basis_gates = uop_basis
|
||||
self.basis_gates = basis
|
||||
self.circuitNameList = []
|
||||
self.circuit_name_list = []
|
||||
# TODO: replace choices with random.choices() when python 3.6 is
|
||||
# required.
|
||||
self.nQubit_list = choices(
|
||||
range(self.minQubits, self.maxQubits+1), k=nCircuits)
|
||||
self.n_qubit_list = choices(
|
||||
range(self.min_qubits, self.max_qubits + 1), k=n_circuits)
|
||||
self.depth_list = choices(
|
||||
range(self.minDepth, self.maxDepth+1), k=nCircuits)
|
||||
for iCircuit in range(nCircuits):
|
||||
nQubits = self.nQubit_list[iCircuit]
|
||||
if self.min_regs_exceeds_nqubits(uop_basis, nQubits):
|
||||
range(self.min_depth, self.max_depth + 1), k=n_circuits)
|
||||
for i_circuit in range(n_circuits):
|
||||
n_qubits = self.n_qubit_list[i_circuit]
|
||||
if self.min_regs_exceeds_nqubits(uop_basis, n_qubits):
|
||||
# no gate operation from this circuit can fit in the available
|
||||
# number of qubits.
|
||||
continue
|
||||
depthCnt = self.depth_list[iCircuit]
|
||||
regpop = numpy.arange(1, nQubits+1)
|
||||
registerWeights = regpop[::-1].astype(float)
|
||||
registerWeights /= registerWeights.sum()
|
||||
maxRegisters = numpy.random.choice(regpop, p=registerWeights)
|
||||
regWeight = numpy.ones(maxRegisters) / float(maxRegisters)
|
||||
regSizes = rand_register_sizes(nQubits, regWeight)
|
||||
nRegisters = len(regSizes)
|
||||
depth_cnt = self.depth_list[i_circuit]
|
||||
reg_pop = numpy.arange(1, n_qubits+1)
|
||||
register_weights = reg_pop[::-1].astype(float)
|
||||
register_weights /= register_weights.sum()
|
||||
max_registers = numpy.random.choice(reg_pop, p=register_weights)
|
||||
reg_weight = numpy.ones(max_registers) / float(max_registers)
|
||||
reg_sizes = rand_register_sizes(n_qubits, reg_weight)
|
||||
n_registers = len(reg_sizes)
|
||||
circuit = QuantumCircuit()
|
||||
for isize, size in enumerate(regSizes):
|
||||
cr_name = 'cr' + str(isize)
|
||||
qr_name = 'qr' + str(isize)
|
||||
cr = ClassicalRegister(cr_name, size)
|
||||
qr = QuantumRegister(qr_name, size)
|
||||
circuit.add(qr, cr)
|
||||
while depthCnt > 0:
|
||||
for i_size, size in enumerate(reg_sizes):
|
||||
cr_name = 'cr' + str(i_size)
|
||||
qr_name = 'qr' + str(i_size)
|
||||
creg = ClassicalRegister(cr_name, size)
|
||||
qreg = QuantumRegister(qr_name, size)
|
||||
circuit.add(qreg, creg)
|
||||
while depth_cnt > 0:
|
||||
# TODO: replace choices with random.choices() when python 3.6
|
||||
# is required.
|
||||
opName = choices(basis, weights=basis_weights)[0]
|
||||
if hasattr(circuit, opName):
|
||||
op = getattr(circuit, opName)
|
||||
op_name = choices(basis, weights=basis_weights)[0]
|
||||
if hasattr(circuit, op_name):
|
||||
operator = getattr(circuit, op_name)
|
||||
else:
|
||||
raise AttributeError('operation \"{0}\"'
|
||||
' not recognized'.format(opName))
|
||||
nregs = self.opSignature[opName]['nregs']
|
||||
nparams = self.opSignature[opName]['nparams']
|
||||
if nregs == 0: # this is a barrier or measure
|
||||
nregs = random.randint(1, nQubits)
|
||||
if nQubits >= nregs:
|
||||
' not recognized'.format(op_name))
|
||||
n_regs = self.op_signature[op_name]['nregs']
|
||||
n_params = self.op_signature[op_name]['nparams']
|
||||
if n_regs == 0: # this is a barrier or measure
|
||||
n_regs = random.randint(1, n_qubits)
|
||||
if n_qubits >= n_regs:
|
||||
# warning: assumes op function signature specifies
|
||||
# op parameters before qubits
|
||||
op_args = []
|
||||
if nparams:
|
||||
op_args = [random.random() for p in range(nparams)]
|
||||
if opName == 'measure':
|
||||
if n_params:
|
||||
op_args = [random.random() for _ in range(n_params)]
|
||||
if op_name == 'measure':
|
||||
# if measure occurs here, assume it's to do a conditional
|
||||
# randomly select a register to measure
|
||||
ireg = random.randint(0, nRegisters-1)
|
||||
ireg = random.randint(0, n_registers-1)
|
||||
qr_name = 'qr' + str(ireg)
|
||||
cr_name = 'cr' + str(ireg)
|
||||
qreg = circuit.regs[qr_name]
|
||||
creg = circuit.regs[cr_name]
|
||||
for qind in range(qreg.size):
|
||||
op(qreg[qind], creg[qind])
|
||||
operator(qreg[qind], creg[qind])
|
||||
ifval = random.randint(0, (1 << qreg.size) - 1)
|
||||
# TODO: replace choices with random.choices() when
|
||||
# python 3.6 is required.
|
||||
uopName = choices(uop_basis, weights=uop_basis_weights)[0]
|
||||
if hasattr(circuit, uopName):
|
||||
uop = getattr(circuit, uopName)
|
||||
uop_name = choices(uop_basis, weights=uop_basis_weights)[0]
|
||||
if hasattr(circuit, uop_name):
|
||||
uop = getattr(circuit, uop_name)
|
||||
else:
|
||||
raise AttributeError('operation \"{0}\"'
|
||||
' not recognized'.format(uopName))
|
||||
unregs = self.opSignature[uopName]['nregs']
|
||||
unparams = self.opSignature[uopName]['nparams']
|
||||
if unregs == 0: # this is a barrier or measure
|
||||
unregs = random.randint(1, nQubits)
|
||||
' not recognized'.format(uop_name))
|
||||
unregs = self.op_signature[uop_name]['nregs']
|
||||
unparams = self.op_signature[uop_name]['nparams']
|
||||
if unregs == 0: # this is a barrier or measure
|
||||
unregs = random.randint(1, n_qubits)
|
||||
if qreg.size >= unregs:
|
||||
qindList = random.sample(range(qreg.size), unregs)
|
||||
qind_list = random.sample(range(qreg.size), unregs)
|
||||
uop_args = []
|
||||
if unparams:
|
||||
uop_args = [random.random() for p in range(unparams)]
|
||||
uop_args.extend([qreg[qind] for qind in qindList])
|
||||
uop_args = [random.random() for _ in range(unparams)]
|
||||
uop_args.extend([qreg[qind] for qind in qind_list])
|
||||
uop(*uop_args).c_if(creg, ifval)
|
||||
depthCnt -= 1
|
||||
elif opName == 'barrier':
|
||||
ireg = random.randint(0, nRegisters-1)
|
||||
depth_cnt -= 1
|
||||
elif op_name == 'barrier':
|
||||
ireg = random.randint(0, n_registers-1)
|
||||
qr_name = 'qr' + str(ireg)
|
||||
qreg = circuit.regs[qr_name]
|
||||
bar_args = [(qreg, mi) for mi in range(qreg.size)]
|
||||
op(*bar_args)
|
||||
operator(*bar_args)
|
||||
else:
|
||||
# select random register
|
||||
ireg = random.randint(0, nRegisters-1)
|
||||
ireg = random.randint(0, n_registers-1)
|
||||
qr_name = 'qr' + str(ireg)
|
||||
qreg = circuit.regs[qr_name]
|
||||
if qreg.size >= nregs:
|
||||
qindList = random.sample(range(qreg.size), nregs)
|
||||
op_args.extend([qreg[qind] for qind in qindList])
|
||||
op(*op_args)
|
||||
depthCnt -= 1
|
||||
if qreg.size >= n_regs:
|
||||
qind_list = random.sample(range(qreg.size), n_regs)
|
||||
op_args.extend([qreg[qind] for qind in qind_list])
|
||||
operator(*op_args)
|
||||
depth_cnt -= 1
|
||||
else:
|
||||
break
|
||||
nmeasure = random.randint(1, nQubits)
|
||||
mList = random.sample(range(nmeasure), nmeasure)
|
||||
if doMeasure:
|
||||
for qind in mList:
|
||||
nmeasure = random.randint(1, n_qubits)
|
||||
m_list = random.sample(range(nmeasure), nmeasure)
|
||||
if do_measure:
|
||||
for qind in m_list:
|
||||
rind = 0 # register index
|
||||
cumtot = 0
|
||||
while qind >= cumtot + circuit.regs['qr' + str(rind)].size:
|
||||
|
@ -244,32 +248,37 @@ class RandomCircuitGenerator():
|
|||
circuit.measure(qreg[qrind], creg[qrind])
|
||||
self.circuit_list.append(circuit)
|
||||
|
||||
def min_regs_exceeds_nqubits(self, basis, nQubits):
|
||||
def min_regs_exceeds_nqubits(self, basis, n_qubits):
|
||||
"""Check whether the minimum number of qubits used by the operations
|
||||
in basis is between 1 and the number of qubits.
|
||||
|
||||
Args:
|
||||
basis (list): list of basis names
|
||||
nQubits (int): number of qubits in circuit
|
||||
n_qubits (int): number of qubits in circuit
|
||||
Returns:
|
||||
boolean: result of the check.
|
||||
"""
|
||||
return not any((nQubits >= self.opSignature[opName]['nregs'] > 0
|
||||
return not any((n_qubits >= self.op_signature[opName]['nregs'] > 0
|
||||
for opName in basis))
|
||||
|
||||
def get_circuits(self, format='dag'):
|
||||
def get_circuits(self, format_='dag'):
|
||||
"""Get the compiled circuits generated.
|
||||
|
||||
Args:
|
||||
format (str, optional): "qasm" | "qobj" | "QuantumCircuit"
|
||||
format_ (str, optional): "qasm" | "qobj" | "QuantumCircuit"
|
||||
|
||||
Returns:
|
||||
List of Compiled QuantumCircuit objects.
|
||||
list: List of Compiled QuantumCircuit objects.
|
||||
|
||||
Raises:
|
||||
NameError: if the output format is not valid.
|
||||
"""
|
||||
if format is 'qasm':
|
||||
if format_ == 'qasm':
|
||||
qasm_list = []
|
||||
for circuit in self.circuit_list:
|
||||
qasm_list.append(circuit.qasm())
|
||||
return qasm_list
|
||||
elif format is 'qobj':
|
||||
elif format_ == 'qobj':
|
||||
json_list = []
|
||||
for circuit in self.circuit_list:
|
||||
node_circuit = qasm.Qasm(data=circuit.qasm()).parse()
|
||||
|
@ -278,7 +287,7 @@ class RandomCircuitGenerator():
|
|||
unroll.JsonBackend(self.basis_gates))
|
||||
json_list.append(unrolled_circuit.execute())
|
||||
return json_list
|
||||
elif format is 'QuantumCircuit':
|
||||
elif format_ == 'QuantumCircuit':
|
||||
qc_list = []
|
||||
for circuit in self.circuit_list:
|
||||
node_circuit = qasm.Qasm(data=circuit.qasm()).parse()
|
||||
|
@ -298,10 +307,10 @@ class RandomCircuitGenerator():
|
|||
# return qc_list
|
||||
else:
|
||||
raise NameError('Unrecognized circuit output format: "{}"'.format(
|
||||
format))
|
||||
format_))
|
||||
|
||||
def rand_register_sizes(nRegisters, pvals):
|
||||
"""Return a randomly chosen list of nRegisters summing to nQubits
|
||||
"""
|
||||
v = numpy.random.multinomial(nRegisters, pvals)
|
||||
return v[v.nonzero()]
|
||||
|
||||
def rand_register_sizes(n_registers, pvals):
|
||||
"""Return a randomly chosen list of nRegisters summing to nQubits."""
|
||||
vector = numpy.random.multinomial(n_registers, pvals)
|
||||
return vector[vector.nonzero()]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -23,33 +24,35 @@ import numpy
|
|||
from qiskit import QuantumProgram
|
||||
|
||||
|
||||
class RandomQasmGenerator():
|
||||
class RandomQasmGenerator(object):
|
||||
"""
|
||||
Generate random size circuits for profiling.
|
||||
"""
|
||||
def __init__(self, seed=None,
|
||||
maxQubits=5, minQubits=1,
|
||||
maxDepth=100, minDepth=1):
|
||||
max_qubits=5, min_qubits=1,
|
||||
max_depth=100, min_depth=1):
|
||||
"""
|
||||
Args:
|
||||
seed: Random number seed. If none, don't seed the generator.
|
||||
maxDepth: Maximum number of operations in a circuit.
|
||||
maxQubits: Maximum number of qubits in a circuit.
|
||||
seed (int): Random number seed. If none, don't seed the generator.
|
||||
max_qubits (int): Maximum number of qubits in a circuit.
|
||||
min_qubits (int): Minimum number of qubits in a circuit.
|
||||
max_depth (int): Maximum number of operations in a circuit.
|
||||
min_depth (int): Minimum number of operations in a circuit.
|
||||
"""
|
||||
self.maxDepth = maxDepth
|
||||
self.maxQubits = maxQubits
|
||||
self.minDepth = minDepth
|
||||
self.minQubits = minQubits
|
||||
self.qp = QuantumProgram()
|
||||
self.qr = self.qp.create_quantum_register('qr', maxQubits)
|
||||
self.cr = self.qp.create_classical_register('cr', maxQubits)
|
||||
self.circuitNameList = []
|
||||
self.nQubitList = []
|
||||
self.depthList = []
|
||||
self.max_depth = max_depth
|
||||
self.max_qubits = max_qubits
|
||||
self.min_depth = min_depth
|
||||
self.min_qubits = min_qubits
|
||||
self.qprogram = QuantumProgram()
|
||||
self.qreg = self.qprogram.create_quantum_register('qr', max_qubits)
|
||||
self.creg = self.qprogram.create_classical_register('cr', max_qubits)
|
||||
self.circuit_name_list = []
|
||||
self.n_qubit_list = []
|
||||
self.depth_list = []
|
||||
if seed is not None:
|
||||
random.seed(a=seed)
|
||||
|
||||
def add_circuits(self, nCircuits, doMeasure=True):
|
||||
def add_circuits(self, n_circuits, do_measure=True):
|
||||
"""Adds circuits to program.
|
||||
|
||||
Generates a circuit with a random number of operations equally weighted
|
||||
|
@ -57,43 +60,44 @@ class RandomQasmGenerator():
|
|||
[1,nQubits] to end of circuit.
|
||||
|
||||
Args:
|
||||
nCircuits (int): Number of circuits to add.
|
||||
doMeasure (boolean): whether to add measurements
|
||||
n_circuits (int): Number of circuits to add.
|
||||
do_measure (boolean): whether to add measurements
|
||||
"""
|
||||
self.circuitNameList = []
|
||||
self.nQubitList = numpy.random.choice(
|
||||
range(self.minQubits, self.maxQubits+1), size=nCircuits)
|
||||
self.depthList = numpy.random.choice(
|
||||
range(self.minDepth, self.maxDepth+1), size=nCircuits)
|
||||
for i in range(nCircuits):
|
||||
circuitName = ''.join(numpy.random.choice(
|
||||
self.circuit_name_list = []
|
||||
self.n_qubit_list = numpy.random.choice(
|
||||
range(self.min_qubits, self.max_qubits + 1), size=n_circuits)
|
||||
self.depth_list = numpy.random.choice(
|
||||
range(self.min_depth, self.max_depth + 1), size=n_circuits)
|
||||
for i in range(n_circuits):
|
||||
circuit_name = ''.join(numpy.random.choice(
|
||||
list(string.ascii_letters + string.digits), size=10))
|
||||
self.circuitNameList.append(circuitName)
|
||||
nQubits = self.nQubitList[i]
|
||||
depth = self.depthList[i]
|
||||
circuit = self.qp.create_circuit(circuitName, [self.qr], [self.cr])
|
||||
for j in range(depth):
|
||||
if nQubits == 1:
|
||||
opInd = 0
|
||||
self.circuit_name_list.append(circuit_name)
|
||||
n_qubits = self.n_qubit_list[i]
|
||||
depth = self.depth_list[i]
|
||||
circuit = self.qprogram.create_circuit(circuit_name,
|
||||
[self.qreg], [self.creg])
|
||||
for _ in range(depth):
|
||||
if n_qubits == 1:
|
||||
op_ind = 0
|
||||
else:
|
||||
opInd = random.randint(0, 1)
|
||||
if opInd == 0: # U3
|
||||
qind = random.randint(0, nQubits-1)
|
||||
op_ind = random.randint(0, 1)
|
||||
if op_ind == 0: # U3
|
||||
qind = random.randint(0, n_qubits-1)
|
||||
circuit.u3(random.random(), random.random(), random.random(),
|
||||
self.qr[qind])
|
||||
elif opInd == 1: # CX
|
||||
source, target = random.sample(range(nQubits), 2)
|
||||
circuit.cx(self.qr[source], self.qr[target])
|
||||
nmeasure = random.randint(1, nQubits)
|
||||
for j in range(nmeasure):
|
||||
qind = random.randint(0, nQubits-1)
|
||||
if doMeasure:
|
||||
self.qreg[qind])
|
||||
elif op_ind == 1: # CX
|
||||
source, target = random.sample(range(n_qubits), 2)
|
||||
circuit.cx(self.qreg[source], self.qreg[target])
|
||||
n_measure = random.randint(1, n_qubits)
|
||||
for _ in range(n_measure):
|
||||
qind = random.randint(0, n_qubits-1)
|
||||
if do_measure:
|
||||
# doing this if here keeps the RNG from depending on
|
||||
# whether measurements are done.
|
||||
circuit.measure(self.qr[qind], self.cr[qind])
|
||||
circuit.measure(self.qreg[qind], self.creg[qind])
|
||||
|
||||
def get_circuit_names(self):
|
||||
return self.circuitNameList
|
||||
return self.circuit_name_list
|
||||
|
||||
def getProgram(self):
|
||||
return self.qp
|
||||
def get_program(self):
|
||||
return self.qprogram
|
||||
|
|
|
@ -75,5 +75,7 @@ class QiskitTestCase(unittest.TestCase):
|
|||
Args:
|
||||
filename (string): filename or relative path to the resource.
|
||||
path (Path): path used as relative to the filename.
|
||||
Returns:
|
||||
str: the absolute path to the resource.
|
||||
"""
|
||||
return os.path.normpath(os.path.join(path.value, filename))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name,missing-docstring
|
||||
# pylint: disable=invalid-name,missing-docstring,no-member
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
|
@ -20,12 +20,10 @@ import os
|
|||
from unittest import skipIf
|
||||
from unittest.mock import patch
|
||||
|
||||
from qiskit import QuantumProgram, QISKitError
|
||||
from IBMQuantumExperience.IBMQuantumExperience import _Request
|
||||
|
||||
from qiskit import QuantumProgram, QISKitError
|
||||
from .common import QiskitTestCase
|
||||
|
||||
|
||||
# We need the environment variable for Travis.
|
||||
HAS_GROUP_VARS = False
|
||||
try:
|
||||
|
@ -123,7 +121,6 @@ class TestApiHub(QiskitTestCase):
|
|||
['qc'], backend=self.backend, shots=1, max_credits=3)
|
||||
self.assertIn('Backend ibmqx4 not found!', str(context.exception))
|
||||
|
||||
|
||||
@skipIf(not HAS_GROUP_VARS, 'QE group variables not present')
|
||||
def test_execute_api_modified_parameters(self):
|
||||
"""Test calling the API with modified hub parameters."""
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
|
||||
import unittest
|
||||
|
||||
from scipy import linalg as la
|
||||
import numpy as np
|
||||
from scipy import linalg as la
|
||||
|
||||
from qiskit.tools.apps.optimization import (Energy_Estimate, make_Hamiltonian,
|
||||
Hamiltonian_from_file,
|
||||
trial_circuit_ry)
|
||||
from qiskit.tools.qi.pauli import Pauli
|
||||
|
||||
from .common import QiskitTestCase
|
||||
|
||||
|
||||
|
@ -61,6 +60,7 @@ class TestQuantumOptimization(QiskitTestCase):
|
|||
|
||||
class TestHamiltonian(QiskitTestCase):
|
||||
def test_hamiltonian(self):
|
||||
# pylint: disable=unexpected-keyword-arg
|
||||
# printing an example from a H2 file
|
||||
hfile = self._get_resource_path("H2Equilibrium.txt")
|
||||
hamiltonian = make_Hamiltonian(Hamiltonian_from_file(hfile))
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# pylint: disable=invalid-name,missing-docstring
|
||||
|
||||
# Copyright 2017 IBM RESEARCH. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# =============================================================================
|
||||
|
||||
import unittest
|
||||
|
||||
from qiskit import QISKitError
|
||||
|
@ -9,12 +25,12 @@ from qiskit.backends import (BaseBackend,
|
|||
register_backend)
|
||||
from qiskit.backends._backendutils import (_REGISTERED_BACKENDS,
|
||||
discover_local_backends)
|
||||
|
||||
from .common import QiskitTestCase
|
||||
|
||||
|
||||
class TestBaseBackend(QiskitTestCase):
|
||||
def setUp(self):
|
||||
# pylint: disable=redefined-outer-name,unused-variable
|
||||
QiskitTestCase.setUp(self)
|
||||
|
||||
# Manually clear and populate the list of registered backends, as it is
|
||||
|
@ -50,6 +66,7 @@ class TestBaseBackend(QiskitTestCase):
|
|||
self.assertEqual(initial_backends_len, len(_REGISTERED_BACKENDS))
|
||||
|
||||
def test_fail_incomplete_implementation(self):
|
||||
# pylint: disable=abstract-method,super-init-not-called,abstract-class-instantiated
|
||||
class SubclassTest(BaseBackend):
|
||||
def __init__(self, qobj):
|
||||
pass
|
||||
|
@ -67,21 +84,20 @@ class TestBaseBackend(QiskitTestCase):
|
|||
|
||||
def test_local_backends(self):
|
||||
available_backends = local_backends()
|
||||
self.log.info('The discovered local devices are: {}'.format(
|
||||
available_backends))
|
||||
self.log.info('The discovered local devices are: %s', available_backends)
|
||||
|
||||
# Some local backends should always be present.
|
||||
self.assertIn('local_qasm_simulator', available_backends)
|
||||
self.assertIn('local_unitary_simulator', available_backends)
|
||||
|
||||
def test_remote_backends(self):
|
||||
self.log.info('The discovered remote devices are: {}'.format(
|
||||
remote_backends()))
|
||||
self.log.info('The discovered remote devices are: %s', remote_backends())
|
||||
|
||||
|
||||
# Dummy backend classes for testing registration.
|
||||
class NoConfigurationBackend(BaseBackend):
|
||||
def __init__(self, configuration=None):
|
||||
# pylint: disable=super-init-not-called
|
||||
pass
|
||||
|
||||
def run(self, q_job):
|
||||
|
@ -94,8 +110,9 @@ class NoConfigurationBackend(BaseBackend):
|
|||
|
||||
class ValidBackend(NoConfigurationBackend):
|
||||
def __init__(self, configuration=None):
|
||||
if configuration == None:
|
||||
self._configuration = {'name':'valid_backend'}
|
||||
# pylint: disable=super-init-not-called
|
||||
if not configuration:
|
||||
self._configuration = {'name': 'valid_backend'}
|
||||
else:
|
||||
self._configuration = configuration
|
||||
|
||||
|
@ -106,6 +123,7 @@ class ValidBackend(NoConfigurationBackend):
|
|||
|
||||
class UninstantiableBackend(ValidBackend):
|
||||
def __init__(self):
|
||||
# pylint: disable=super-init-not-called
|
||||
raise Exception
|
||||
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue