All the logic for the analysis of a specific 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 meaningful metric modules, that is, in the extension of QuRA with support for additional metrics.
The definition of a new metric analysis boils down to the definition of what indices should be produced when analyzing a small number of key circuit building scenarios. Indices are arithmetic expressions built from natural numbers and index variables, and are represented by the Index
datatype, in the Index.AST
module.
Here follows a list of the Index
constructors that can be used when defining new metrics:
Number :: Int -> Index
makes an index out of an integer number. For matters of soundness, this number should be non-negative.IVar :: IVarId -> Index
makes an index variable out of a string identifier.Plus :: Index -> Index -> Index
represents the sum of two index expressions.Minus :: Index -> Index -> Index
represents the natural subtractions of two index expression. Note thatMinus e1 e2
is equal to zero whenevere1
is less or equal thane2
.Mult :: Index -> Index -> Index
represents the product of two index expressionsMax :: Index -> Index -> Index
represents the maximum of two index expressionsBoundedSum :: IVarId -> Index -> Index
represents the bounded sum of indices.BoundedSum "i" e1 e2
is the sum fori
going from 0 (included) toe1
(excluded) ofe2
, wheree2
can depend oni
.BoundedMax :: IVarId -> Index -> Index
represents the bounded maximum of indices.BoundedMax "i" e1 e2
is the maximum fori
going from 0 (included) toe1
(excluded) ofe2
, wheree2
can depend oni
.
An instance of GlobalMetricModule
requires the definition of the following functions:
-
name :: String
is just the name of the metric, used for pretty printing. -
desugarIdentity :: Index
defines the neutral element for the metric (e.g. what it means to have "no width"). This is usually justNumber 0
. -
desugarWire :: WireType -> Index
defines the size of a wire, which might depend on its wiretype. Note thatWireType = Bit | Qubit
. For example, for width:-- src/Index/Semantics/Global/Width.hs desugarWire Bit = Number 1 desugarWire Qubit = Number 1
-
desugarOperation :: QuantumOperation -> Index
defines the size of each elementary quantum operation available in PQR. The list of of availableQuantumOperation
s is available in theCircuit
module. For example, for T-count:-- src/Index/Semantics/Global/TCount.hs desugarOperation T = Number 1 desugarOperation _ = Number 0
-
desugarSequence :: Index -> Index -> Index
defines the size of two circuits composed in sequence. SupposeC
is a circuit of sizee1
andD
is a circuit of sizee2
. Then,desugarSequence e1 e2
should be the size of the composition in sequence ofC
andD
. For example, for width:-- src/Index/Semantics/Global/Width.hs desugarSequence e1 e2 = Max e1 e2
-
desugarParallel :: Index -> Index -> Index
defines the size of two circuits composed in parallel. SupposeC
is a circuit of sizee1
andD
is a circuit of sizee2
. Then,desugarSequence e1 e2
should be the size of the composition in parallel ofC
andD
. For example, for width:-- src/Index/Semantics/Global/Width.hs desugarParallel e1 e2 = Plus e1 e2
-
desugarBoundedSequence :: IVarId -> Index -> Index -> Index
is the same asdesugarSequence
, but generalized to bounded sequences. That is,desugarBoundedSequence "i" e1 e2
is the size of the circuit obtained by composing in sequencee1
circuits, where the size of thei
-th circuit ise2
and might depend oni
.-- src/Index/Semantics/Global/Width.hs desugarBoundedSequence i e1 e2 = BoundedMax i e1 e2
-
desugarBoundedParallel :: IVarId -> Index -> Index -> Index
is the same asdesugarParallel
, but generalized to bounded sequences. That is,desugarBoundedParallel "i" e1 e2
is the size of the circuit obtained by composing in parallele1
circuits, where the size of thei
-th circuit ise2
and might depend oni
.-- src/Index/Semantics/Global/Width.hs desugarBoundedParallel i e1 e2 = BoundedSum i e1 e2
For more examples of global metric modules, consult the modules under Index.Semantics.Global
Once you have defined a global resource module, you need to make the following changes Main.hs
in order to make it available from QuRA's interface:
- Add a new case to
globalMetricArgParser
to parse your new metric as a command line option. - Also 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
with QuRA, run
$ qura filename -g myglobalmetric
An instance of LocalMetricModule
requires the definition of the following functions:
-
name :: String
is just the name of the metric, used for pretty printing. -
desugarOutput :: QuantumOperation -> Int -> [Index] -> Index
describes the local metric associated to each of the outputs of a quantum operations, as a function of the operation and its inputs.desugarOutput op n inMetrics
is 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/Index/Semantics/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 Index.Semantics.Local
Once you have defined a local resource module, you need to make the following changes Main.hs
in order to make it available from QuRA's interface:
- Add a new case to
localMetricArgParser
to parse your new metric as a command line option. - Also 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
with QuRA, run
$ qura filename -l mylocalmetric