I am trying to simulate Deutsch's algorithm, and I need to apply the oracle function matrix to my circuit.


This is going to change somewhat radically in the next version of cirq, so I'll give an answer for both versions.

In v0.3, in order for a simulator to understand a custom gate, the gate must implement either cirq.CompositeGate or cirq.KnownMatrix. For your case, the simplest is to implement the matrix:

# assuming cirq v0.3
import cirq
import numpy as np
class Oracle(cirq.Gate, cirq.KnownMatrix):
    def __init__(self, secret_state, qubit_count):
        self.secret_state = secret_state
        self.qubit_count = qubit_count
    def matrix(self):
        m = np.eye(1 << self.qubit_count)
        m[self.secret_state, self.secret_state] = -1
        return m

You can then use this oracle to simulate e.g. a Grover circuit and see that the secret state ends up with quite a high probability:

qs = cirq.LineQubit.range(5)
secret = 5
oracle = Oracle(secret, len(qs)).on(*qs)

diffusion = [
    Oracle(0, len(qs)).on(*qs),
c = cirq.Circuit.from_ops(
    [oracle, diffusion] * 4
output_vector = c.apply_unitary_effect_to_state()
print(np.round(abs(output_vector)**2, 3))
# [0  0  0  0  0  .999  0  0 ...]
#                  ^ big probability at offset 5

In the coming v0.4 the classes such as KnownMatrix will be replaced by "magic methods" such as _unitary_. (This is generally how things are supposed to be done in python.) One of those magic methods is _apply_unitary_to_tensor_, which is used to enable faster simulation. With that method the oracle application can be simulated much much faster; in $O(q)$ time instead of $O(4^q)$ time assuming the oracle covers all of the qubits. We also happen to avoid the need to know the number of qubits ahead of time:

# assuming cirq v0.4
import cirq
class Oracle(cirq.Gate):
    def __init__(self, secret_state):
        self.secret_state = secret_state
    def _apply_unitary_to_tensor_(self, target_tensor, available_buffer, axes):
        s = cirq.slice_for_qubits_equal_to(axes, self.secret_state)
        target_tensor[s] *= -1
        return target_tensor

I searched for doing a custom gate on the Cirq documentation and here are the results :

Gate sets

The xmon simulator is designed to work with operations that are either a GateOperation applying an XmonGate, a CompositeOperation that decomposes (recursively) to XmonGates, or a 1-qubit or 2-qubit operation with a KnownMatrix. By default the xmon simulator uses an Extension defined in xgate_gate_extensions to try to resolve gates that are not XmonGates to XmonGates.

So if you are using a custom gate, there are multiple options for getting it to work with the simulator:

Define it directly as an XmonGate. Provide a CompositeGate made up of XmonGates. Supply an Exentension to the simulator which converts the gate to an XmonGate or to a CompositeGate which itself can be decomposed in XmonGates.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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