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 34 logical qubits…
Are there any mistakes or any misuses in my implementation that could be fixed to improve efficiency?
I appreciate your assistance
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])
self.p.add(wire,2*circ_x)
def y(self,wire):
circ_y=comp.PERM([1,0]) // (0,PS(np.pi/2)) // (1,PS(np.pi/2))
self.p.add(wire,circ_y)
def had(self,wire):
circ_h=comp.BS.H()
self.p.add(2*wire,circ_h)
## Rotation gates
# todo
def phase_shift(self,wire,angle=sp.pi/2):
ph_shifter = comp.PS(angle)
self.p.add(1+wire*2,ph_shifter)
def cnot(self,ctrl,target):
cnot=catalog['heralded cnot'].as_processor().build()
self.p.add([ctrl*2,1+ctrl*2,target*2,1+target*2],cnot)
def cz(self,ctrl,target):
#1. Making a ControlledZ from a CNOT
self.had(target)
self.cnot(ctrl,target)
self.had(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)