Extending QuRA
All the logic for the analysis of a specific resource metric is encoded as a metric module, that is, an instance of GlobalMetricModule (for global metrics) or LocalMetricModule (for local metrics).
This guide is meant to aid contributors in the implementation of new metric modules, that is, in the extension of QuRA with the ability tackle new definitions of "resource".
The Index datatype
The definition of a new metric analysis boils down to specifying what resource annotations should be produced when analyzing a small number of key circuit building scenarios. These annotations are called indices, and they are essentially arithmetic expressions built from natural numbers and index variables. They are represented through the Index datatype, in the PQ.Index module.
Here is a list of the Index constructors that can be used when defining new metrics:
Number :: Int -> Indexmakes an index out of an integer. For matters of soundness, only non-negative integers should appear in indices.IVar :: IVarId -> Indexmakes an index variable out of a string identifier.Plus :: Index -> Index -> Indexrepresents the sum of two index expressions.Minus :: Index -> Index -> Indexrepresents the natural subtractions of two index expression. Note thatMinus e1 e2is equal to zero whenevere1is less or equal thane2.Mult :: Index -> Index -> Indexrepresents the product of two index expressions.Max :: Index -> Index -> Indexrepresents the maximum of two index expressions.BoundedSum :: IVarId -> Index -> Indexrepresents the bounded sum of indices.BoundedSum "i" e1 e2is the sum forigoing from 0 (included) toe1(excluded) ofe2, wheree2can depend oni.BoundedMax :: IVarId -> Index -> Indexrepresents the bounded maximum of indices.BoundedMax "i" e1 e2is the maximum forigoing from 0 (included) toe1(excluded) ofe2, wheree2can depend oni.
Global metrics
Defining a global metric module
An instance of GlobalMetricModule requires the definition of the following functions:
name :: Stringis just the name of the metric, used for pretty printing.desugarIdentity :: Indexdefines the neutral element for the metric (e.g. what it means to have "no width"). This is usually justNumber 0.desugarWire :: WireType -> Indexdefines the size of a wire, which might depend on its wiretype. Note thatWireType = Bit | Qubit. For example, in the case of width:
-- src/Metric/Global/Width.hs
desugarWire Bit = Number 1
desugarWire Qubit = Number 1
desugarOperation :: QuantumOperation -> Indexdefines the size of each elementary quantum operation available in PQR. The list of of availableQuantumOperations is available in theCircuitmodule. For example, for T-count:
-- src/Metric/Global/TCount.hs
desugarOperation T = Number 1
desugarOperation _ = Number 0
desugarSequence :: Index -> Index -> Indexdefines the size of two circuits composed in sequence. SupposeCis a circuit of sizee1andDis a circuit of sizee2. Then,desugarSequence e1 e2should be the size of the composition in sequence ofCandD. For example, in the case of width:
-- src/Metric/Global/Width.hs
desugarSequence e1 e2 = Max e1 e2
desugarParallel :: Index -> Index -> Indexdefines the size of two circuits composed in parallel. SupposeCis a circuit of sizee1andDis a circuit of sizee2. Then,desugarSequence e1 e2should be the size of the composition in parallel ofCandD. For example, in the case of width:
-- src/Metric/Global/Width.hs
desugarParallel e1 e2 = Plus e1 e2
desugarBoundedSequence :: IVarId -> Index -> Index -> Indexis the same asdesugarSequence, but generalized to bounded sequences. That is,desugarBoundedSequence "i" e1 e2is the size of the circuit obtained by composing in sequencee1circuits, where the size of thei-th circuit ise2and might depend oni.
-- src/Metric/Global/Width.hs
desugarBoundedSequence i e1 e2 = BoundedMax i e1 e2
desugarBoundedParallel :: IVarId -> Index -> Index -> Indexis the same asdesugarParallel, but generalized to bounded sequences. That is,desugarBoundedParallel "i" e1 e2is the size of the circuit obtained by composing in parallele1circuits, where the size of thei-th circuit ise2and might depend oni.
-- src/Metric/Global/Width.hs
desugarBoundedParallel i e1 e2 = BoundedSum i e1 e2
For more examples of global metric modules, consult the modules under Metric.Global
Making it available through QuRA's interface
In order to make a new GlobalMetricModule available from QuRA's interface, you need to first re-export it in Metric.hs and then make the following changes to Interface.hs:
- Add a new case to
globalMetricArgParserto parse your new metric as a command line option. - Add your metric's name to the error message of the argument parser, so that users know it's there.
If your metric is defined in myGlobalMetricModule and is called myglobalmetric, the last lines of the case analysis in globalMetricArgParser should look like this:
globalMetricArgParser = do
s <- str
case s of
...
"myglobalmetric" -> return myGlobalMetricModule
_ -> readerError "Supported global resources are 'width', 'gatecount', 'qubits', 'bits', 'tcount', `myglobalmetric`"
Finally, to analyze myglobalmetric in QuRA, run
qura FILE -g myglobalmetric
Local metrics
Defining a local metric module
An instance of LocalMetricModule requires the definition of the following functions:
name :: Stringis just the name of the metric, used for pretty printing.desugarOutput :: QuantumOperation -> Int -> [Index] -> Indexdescribes the local metric associated to each of the outputs of a quantum operation, as a function of the operation itself and the local metrics of its inputs.desugarOutput op n inMetricsis the local metric associated to then-th output ofop, when the local metrics associated to its inputs are those ininMetrics. For example, for depth:
-- src/Metric/Local/Depth.hs
desugarOutput _ _ inDepths =
foldr Max (Number 0) $ map (Number 1 `Plus`) inDepths
For more examples of local metric modules, consult the modules under Metric.Local
Making it available through QuRA's interface
In order to make a new LocalMetricModule available from QuRA's interface, you need to first re-export it in Metric.hs and then make the following changes to Interface.hs:
- Add a new case to
localMetricArgParserto parse your new metric as a command line option. - Add your metric's name to the error message of the argument parser, so that users know it's there.
If your metric is defined in myLocalMetricModule and is called mylocalmetric, the last lines of the case analysis in localMetricArgParser should look like this:
localMetricArgParser = do
s <- str
case s of
...
"mylocalmetric" -> return myLocalMetricModule
_ -> readerError "Supported local resources are 'depth', `tdepth`, `mylocalmetric`"
Finally, to analyze mylocalmetric in QuRA, run
qura FILE -l mylocalmetric