In order to correctly emulate the behavior of a software stack built on a specific hardware, one might need to force some simulator to publish some particular hardware specs.
Lets say, for instance, that you want to particularize the LinAlg
simulator in order for it to publish a limited connectivity, or a fixed number of qubits. Any plugin on top of this particularized LinAlg
would see these constraints, and would act according to this information.
This is exactly the purpose of the Quameleon
Plugin.
The following cell demonstrate the use of this Plugin to build a custom LinAlg
instance that publish a limited number of qubits over a linear nearest neighbor connectivity.
from qat.core import HardwareSpecs, Topology, TopologyType
from qat.core.quameleon import QuameleonPlugin
from qat.qpus import get_default_qpu
my_custom_specs = HardwareSpecs(nbqbits=12, topology=Topology(type=TopologyType.LNN))
qpu = QuameleonPlugin(specs=my_custom_specs) | get_default_qpu()
qpu_specs = qpu.get_specs()
print("Default specs of LinAlg:", get_default_qpu().get_specs())
print("Our specs:", qpu_specs)
As you can see, this new QPU publishes exactly the specs we required, instead of publishing a trivial set of specs.
Moreover, sending a circuit that is not compliant with these specs will raise an appropriate exception:
from qat.lang.AQASM import *
prog = Program()
qbits= prog.qalloc(3)
prog.apply(CNOT, qbits[0], qbits[2])# This gate is not LNN
job = prog.to_circ().to_job()
try:
qpu.submit(job)
except Exception as e:
print(e.message)
prog = Program()
qbits= prog.qalloc(15)
prog.apply(H, qbits[14])# This qubit is out of bound
job = prog.to_circ().to_job()
try:
qpu.submit(job)
except Exception as e:
print(e.message)
Of course, we can do the same with custom topologies:
my_topology = Topology(type=TopologyType.CUSTOM)
my_topology.add_edge(0, 2)
my_topology.add_edge(1, 2)
my_topology.add_edge(3, 2)
my_topology.add_edge(4, 2)
my_topology.add_edge(0, 1)
my_topology.add_edge(3, 4)
my_ibm_qx4_specs = HardwareSpecs(nbqbits=5, topology=my_topology)
qpu = QuameleonPlugin(specs=my_ibm_qx4_specs) | get_default_qpu()
print(qpu.get_specs())
And also custom gate sets:
from qat.core.gate_set import GateSet
gate_set = GateSet({
"H" : AbstractGate("H", [], arity=1)
})
my_specs = HardwareSpecs(gateset=gate_set)
qpu = QuameleonPlugin(specs=my_specs) | get_default_qpu()
print(qpu.get_specs())
# declaring a custom gate "FOO"
FOO = AbstractGate("FOO", [], arity=1)
prog = Program()
qbits= prog.qalloc(1)
prog.apply(FOO(), qbits)
job = prog.to_circ().to_job()
try:
qpu.submit(job)
except Exception as e:
print(e)
# using only declared gates
prog = Program()
qbits= prog.qalloc(1)
prog.apply(H, qbits)
job = prog.to_circ().to_job()
results = qpu.submit(job)
print("Everything went fine.")