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?
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 Controlled-Z 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)