# Logical circuit in Dual-rail encoding with perceval (efficiently)

Hi,

I am trying to to build a generic logical circuits Class ( à la Qiskit) based on LO components available in Perceval. The idea is to provide an CS friendly API with Hadamard etc and without having to handle the encoding manually.

I am not so familiar with Perceval’s best practices yet, but I tried to follow the doc to achieve what I am trying to do.

• Provide an API/wrapper for some functions H, CNOT/CZ and phase shift notably.

• Each logical qubit is encoded on 2 Perceval qubits. The logical 0 is 01, the logical 1 is 10 so that’s why I multiply the (logical) width by 2 (in init function) and I assume our initial state is always |0…0> (the common assumption in the circuit model as usual) so I use as initial state 01 01…01 in measurement via the function “with inputs”.

• Measurement is performed using pcvl sampler and returning an object to the user.

Unfortunately, my current implementation seems to be very resource intensive, takes a lot of time, RAM and I can’t go beyond 3-4 logical qubits…

Are there any mistakes or any mis-uses in my implementation that could be fixed to improve efficiency?

Thanks

``````import numpy as np
import sympy as sp

from collections import Counter

import perceval as pcvl
import perceval.components as comp
from perceval.components import catalog

class LogicalCirc():
def __init__(self,circ_width:int):
# I have a doubt here, since we will be working will LO circs, so I should call pcvl

self.circuit = pcvl.Circuit(2*circ_width)
self.circ_width = circ_width#*2
init_state = [0,1]*circ_width  # should I init them to 01 in dual ral is equivalent to |0>L?
self.basic_state = pcvl.BasicState(init_state)
self.p=pcvl.Processor("SLOS",2*circ_width)
def x(self,wire):
circ_x=comp.PERM([1,0])

def y(self,wire):
circ_y=comp.PERM([1,0]) // (0,PS(-np.pi/2)) // (1,PS(np.pi/2))

circ_h=comp.BS.H()

## Rotation gates
# todo
def phase_shift(self,wire,angle=sp.pi/2):
ph_shifter = comp.PS(angle)
def cnot(self,ctrl,target):
cnot=catalog['heralded cnot'].as_processor().build()

def cz(self,ctrl,target):
#1. Making a Controlled-Z from a CNOT
self.cnot(ctrl,target)

def measure(self,nb_samples=50):
self.p.with_input (self.basic_state)
sampler = pcvl.algorithm.Sampler(self.p)
samples = sampler.samples(nb_samples)

samples_counter = dict()
for state in samples['results']:
if samples_counter.get(state)==None:
samples_counter[state]=1
else: samples_counter[state]+=1
#             print(state)
#         return max(samples_counter, key = samples_counter.get)
return samples_counter
def draw(self):
return pcvl.pdisplay(self.p)
``````

I had a look at your question. Normally, SLOS runs pretty well on a local machine up to 6 photons, so it’s unusual that 3-4 is so memory intensive. I am not the expert on Perceval’s memory management (@Eric is), but I would have a few quick questions/suggestions:

1. Since you are running a noiseless/lossless simulation, have you tried the Clifford and Clifford Processor? Does it run any faster for you? [this is probably not the error, as you’re still well under 6 photons, but worth a try]
2. Do you know which function is slowing you down the most? Is it `measure`? If you have a minimum example which runs slowly on 3-4 photons, it would be helpful for us to diagnose.