1
$\begingroup$

I'm trying to define a custom gate for my computations. I decided to copy the structure in one of the files in qiskit.extensions.standard package. Here is the code of h.py (Hadamard gate):

# -*- coding: utf-8 -*-

# Copyright 2017, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

# pylint: disable=invalid-name

"""
Hadamard gate.
"""
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import InstructionSet
from qiskit.circuit import QuantumRegister
from qiskit.qasm import pi
from qiskit.dagcircuit import DAGCircuit
from qiskit.extensions.standard import header  # pylint: disable=unused-import
from qiskit.extensions.standard.u2 import U2Gate


class HGate(Gate):
    """Hadamard gate."""

    def __init__(self, qubit, circ=None):
        """Create new Hadamard gate."""
        super().__init__("h", [], [qubit], circ)

    def _define_decompositions(self):
        """
        gate h a { u2(0,pi) a; }
        """
        decomposition = DAGCircuit()
        q = QuantumRegister(1, "q")
        decomposition.add_qreg(q)
        decomposition.add_basis_element("u2", 1, 0, 2)
        rule = [
            U2Gate(0, pi, q[0])
        ]
        for inst in rule:
            decomposition.apply_operation_back(inst)
        self._decompositions = [decomposition]

    def inverse(self):
        """Invert this gate."""
        return self  # self-inverse

    def reapply(self, circ):
        """Reapply this gate to corresponding qubits in circ."""
        self._modifiers(circ.h(self.qargs[0]))


def h(self, q):
    """Apply H to q."""
    if isinstance(q, QuantumRegister):
        instructions = InstructionSet()
        for j in range(q.size):
            instructions.add(self.h((q, j)))
        return instructions

    if isinstance(q, QuantumRegister):
        instructions = InstructionSet()
        for j in range(q.size):
            instructions.add(self.h(q))
        return instructions

    self._check_qubit(q)
    return self._attach(HGate(q, self))


QuantumCircuit.h = h

Trying to change the names of the class, the property of QuantumCircuit and the name string in Gate constructor results in an exception (name of the gate) is not in the list of basic operations if I try to either draw or execute an example circuit containing the gate.

"

""
[1]-const gate.
"""
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import InstructionSet
from qiskit.circuit import QuantumRegister
from qiskit.qasm import pi
from qiskit.dagcircuit import DAGCircuit
from qiskit.extensions.standard import header  # pylint: disable=unused-import
from qiskit.extensions.standard.u2 import U2Gate


class OneConstGate(Gate):

    def __init__(self, qubit, circ=None):
        super().__init__("oneconst", [], [qubit], circ)

    def _define_decompositions(self):
        decomposition = DAGCircuit()
        q = QuantumRegister(1, "q")
        decomposition.add_qreg(q)
        decomposition.add_basis_element("u2", 1, 0, 2)
        rule = [
            U2Gate(0, pi, q[0])
        ]
        for inst in rule:
            decomposition.apply_operation_back(inst)
        self._decompositions = [decomposition]

    def inverse(self):
        """Invert this gate."""
        return self  # self-inverse

    def reapply(self, circ):
        """Reapply this gate to corresponding qubits in circ."""
        self._modifiers(circ.oneconst(self.qargs[0]))


def oneconst(self, q):
    """Apply H to q."""
    if isinstance(q, QuantumRegister):
        instructions = InstructionSet()
        for j in range(q.size):
            instructions.add(self.oneconst((q, j)))
        return instructions

    if isinstance(q, QuantumRegister):
        instructions = InstructionSet()
        for j in range(q.size):
            instructions.add(self.oneconst(q))
        return instructions

    self._check_qubit(q)
    return self._attach(OneConstGate(q, self))


QuantumCircuit.oneconst = oneconst

Here is the example code:

x = QuantumRegister(1, 'x')
gate = QuantumCircuit(x)
gate.oneconst(x[0])
gate.draw()

Note that I haven't changed any logic yet. Just the names. Did I forgot something?

Edit (1):

I had a look at header.py code in qiskit.extensions.standard. Adding these lines of code remove the error on draw method, but not in execute method:

import sympy
from qiskit.circuit import QuantumCircuit
from qiskit.qasm import _node as node

QuantumCircuit.definitions["oneconst"] = {
    "print": False,
    "opaque": False,
    "n_args": 0,
    "n_bits": 1,
    "args": [],
    "bits": ["a"],
    # gate x a { u3(pi,0,pi) a; }
    "body": node.GateBody([
        node.CustomUnitary([
            node.Id("u3", 0, ""),
            node.ExpressionList([
                node.Real(sympy.pi),
                node.Int(0),
                node.Real(sympy.pi)
            ]),
            node.PrimaryList([
                node.Id("a", 0, "")
            ])
        ])
    ])
}
$\endgroup$

1 Answer 1

3
$\begingroup$

Did you add these lines to the file qiskit/extensions/standard/__init__.py:

from .oneconst import oneconst
from .oneconst import OneConstGate

I did everything you described doing, as well as added those lines to __init__.py and the following code ran without error:

import qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute
from qiskit import Aer

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
gate = QuantumCircuit(qr, cr)
gate.oneconst(qr[0])
gate.measure(qr[0], cr[0])
print(gate.draw())

backend = Aer.get_backend("qasm_simulator")

job = execute(gate, backend, shots=100)

print(job.result().get_counts(gate))
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.