Arithmetic functions


while working on a project, I realized it would be nice if there was a small library of basic arithmetic functions. Specifically, since continuous functions can be approximated by a power series, the following minimal toolkit would allow users to implement whatever they want:

With these one could calculate e.g.
exp(x) = 1 + x + 1/2! x^2 + 1/3! x^3


Thanks @rdisipio!

This is great feedback and I agree that it would be something very nice to add.

I’m not sure how soon we’d be able to get to looking at such a feature, but in the meantime we actively welcome contributions!


And as always, pull requests are very welcome. :slight_smile:

Yeah, I’ll see what I can do but no committments. Since we’re here, I actually started looking at the QFT. I couldn’t find an implementation anywhere in the code base. Is called something else? Also, when I print out the circtuit, I get this:

 1: ──────────────────────────╭C─────────────────╭C────────────────│──────────────────H──│──────────────────╰Rot(1.57, 0, 0)─────│─────── ⟨Z⟩ 
 2: ─────╭C────────────────H──│──────────────────╰Rot(1.57, 0, 0)──│─────────────────────╰Rot(0.785, 0, 0)───────────────────────│─────── ⟨Z⟩ 
 3: ──H──╰Rot(1.57, 0, 0)─────╰Rot(0.785, 0, 0)────────────────────╰Rot(0.393, 0, 0)─────────────────────────────────────────────╰SWAP─── ⟨Z⟩ 

The second H gate is supposed to be applied after the sequence of controlled rotations. Is there any β€œbarrier” command in PennyLane? Or is it just an issue with the printing routine?

FYI, one can get some inspiration from this library based on Qiskit:


1 Like

Thanks @rdisipio!

The QFT is available in the development branch of PennyLane. To access this, you can install using these instructions.

1 Like

Hello again,

To get my feet wet, I tried to implement the Draper Adder but I’m quite confused. The algorithm is implemented in a number of languages but this is probably the easiest to read:

I see that QFT in PennyLane derives from Operation base class, but for now I wanted to keep things easy, so I implemented it as a simple sequence of gates.

#!/usr/bin/env python

import numpy as np
import pennylane as qml

def add(wires_a, wires_b):
    assert len(wires_b) > len(wires_a)
    n = len(wires_a)
    # encode number a into the phase basis
    for i in range(n, 0, -1):
        # loop over control qubits (a)
        for j in range(i, 0, -1):
            if n - 1 >= j - 1:
                phi = 2 * np.pi / np.power(2, i-j+1)
                qml.ControlledPhaseShift(phi, wires=[wires_a[j-1], wires_b[i-1]])
    # go back to computational basis

def test_add(bs):
   qml.BasisState(bs, wires=wires)
   add(wires_a, wires_b)
   return [qml.expval(qml.PauliZ(i)) for i in wires_b]

n_qubits_per_number = 3
wires_a = [f'a{i}' for i in range(n_qubits_per_number)]
wires_b = [f'b{i}' for i in range(n_qubits_per_number+1)]
wires = wires_a + wires_b

dev = qml.device('default.qubit', wires=wires, shots=1000, analytic=False)
circ = qml.QNode(test_add, dev)

pad = [0]
a = [0, 1, 0]
b =  pad + [0, 0, 1]
bs = a + b
z = circ(bs)

I don’t know if the output is correct. I get z = [ 0.678 1. -1. -1. ] which may be a base-2 encoding of 3 (it’s either 1100 or 0011 depending on how you interpret the pauli-z states). If I print out the circuit after execution, I see this:

 a0: ──╭|0βŸ©β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•­ControlledPhaseShift(0.785)──╭ControlledPhaseShift(1.57)──╭ControlledPhaseShift(3.14)───────────     
 a1: β”€β”€β”œ|1βŸ©β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•­ControlledPhaseShift(1.57)──╭ControlledPhaseShift(3.14)──│─────────────────────────────│────────────────────────────│─────────────────────────────────────     
 a2: β”€β”€β”œ|0βŸ©β”€β”€β”€β”€β”€β”€β”€β”€β•­ControlledPhaseShift(3.14)──│────────────────────────────│────────────────────────────│─────────────────────────────│────────────────────────────│─────────────────────────────────────     
 b0: β”€β”€β”œ|0βŸ©β”€β”€β•­QFT──│────────────────────────────│────────────────────────────│────────────────────────────│─────────────────────────────│────────────────────────────╰ControlledPhaseShift(3.14)──╭QFT⁻¹─── ⟨Z⟩ 
 b1: β”€β”€β”œ|0βŸ©β”€β”€β”œQFT──│────────────────────────────│────────────────────────────╰ControlledPhaseShift(3.14)──│─────────────────────────────╰ControlledPhaseShift(1.57)β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”œQFT⁻¹─── ⟨Z⟩ 
 b2: β”€β”€β”œ|0βŸ©β”€β”€β”œQFT──╰ControlledPhaseShift(3.14)──╰ControlledPhaseShift(1.57)───────────────────────────────╰ControlledPhaseShift(0.785)β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”œQFT⁻¹─── ⟨Z⟩ 
 b3: ──╰|1βŸ©β”€β”€β•°QFT─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╰QFT⁻¹─── ⟨Z⟩ 

I don’t think the gates are executed in the same order they are defined in the nested loops, e.g. controlled gates acting on b3 should be executed before moving to b2. What am I doing wrong?


Hi @rdisipio,

This looks really cool! Thanks for checking it out.

I need a bit more time to get familiar with the circuit, but from an initial look at the printed-out circuit, it seems weird that no phase shift gates are being applied to b3. Has your code taken into account that the b register has n + 1 qubits? Maybe you just need to add-in that offset.

I will have a closer look though, this looks really cool! In the long run, it might be nice to add this as a PennyLane template.