From 7f6a63b09031db078642d3ce580cbcb547f24ad4 Mon Sep 17 00:00:00 2001 From: Kartik Singhal Date: Fri, 20 Oct 2023 16:34:11 -0500 Subject: [PATCH 1/4] feat: include units for duration and angles --- phir/model.py | 10 +++++++++- schema.json | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/phir/model.py b/phir/model.py index d1c611b..c5cecf1 100644 --- a/phir/model.py +++ b/phir/model.py @@ -68,13 +68,17 @@ class Op(BaseModel, abc.ABC): metadata: dict[str, Any] | None = None +Radian: TypeAlias = float +PiRadian = NewType("PiRadian", tuple[float, Literal["pi"]]) + + class QOp(Op): """Quantum operation.""" qop: str returns: list[Bit] | None = None args: list[Bit | list[Bit]] - angles: list[float] | None = None + angles: list[Radian | PiRadian] | None = None class COp(Op): @@ -92,10 +96,14 @@ class FFCall(COp): function: str +Duration = NewType("Duration", tuple[float, Literal["s", "ms", "us", "ns"]]) + + class MOp(Op): """Machine operation.""" mop: str + duration: Duration | None = None OpType: TypeAlias = FFCall | COp | QOp | MOp diff --git a/schema.json b/schema.json index 69a7f9f..f3fcf70 100644 --- a/schema.json +++ b/schema.json @@ -404,6 +404,34 @@ "mop": { "title": "Mop", "type": "string" + }, + "duration": { + "anyOf": [ + { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "number" + }, + { + "enum": [ + "s", + "ms", + "us", + "ns" + ], + "type": "string" + } + ], + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Duration" } }, "required": [ @@ -501,7 +529,24 @@ "anyOf": [ { "items": { - "type": "number" + "anyOf": [ + { + "type": "number" + }, + { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "number" + }, + { + "const": "pi" + } + ], + "type": "array" + } + ] }, "type": "array" }, From 072d9049188b6b314464c41344e8e3693813b8fe Mon Sep 17 00:00:00 2001 From: Kartik Singhal Date: Fri, 20 Oct 2023 16:57:58 -0500 Subject: [PATCH 2/4] docs(spec): update spec with specific types for angles and durations Another change is that "duration" is now an optional field of `MOp` --- phir_spec_qasm.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/phir_spec_qasm.md b/phir_spec_qasm.md index 1667e3b..2af2540 100644 --- a/phir_spec_qasm.md +++ b/phir_spec_qasm.md @@ -312,13 +312,16 @@ The generic qop gate structure is: ```json5 { "qop": str, - "angles": [float...], // Include if gate has one or more angles. + "angles": [float | [float, "pi"] ...], // Include if gate has one or more angles. "args": [qubit_id, ... | [qubit_id, ... ], ...], // Can be a list of qubit IDs or a list of lists for multi-qubit gates. "metadata": {}, // Optional metadata for potential auxiliary info or to be utilized by error models. "returns": [[str, int], ...] // Include if gate produces output, e.g., a measurement. } ``` +`"angles"` list is expected to be in radians, ie, `float`. For convenience, multiples of ᴨ (pi radians) are also supported in the +form of tuples `[float, "pi"]`. + Table II details the available qops. For qops like `H q[0]; H q[1]; H q[4];` in QASM, it is translated as: @@ -350,7 +353,7 @@ However, multi-qubit gates, such as `CX`, use a list of lists of qubit IDs. E.g. PECOS ensures all qubit IDs in `"args"` are unique, meaning gates don't overlap on the same qubits. -For gates with one or multiple angles, angles are denoted as floats in the `"angles"` list: +For gates with one or multiple angles, angles are denoted as floats (or pi radians, not shown) in the `"angles"` list: ```json5 { @@ -437,19 +440,22 @@ The general form of `"mop"`s is: { "mop": str, // identifying name "args": [qubit_id, ... | [qubit_id, ... ], ...], // optional + "duration": [float, "s"|"ms"|"us"|"ns"], // optional "metadata": {} // Optional metadata for potential auxiliary info or to be utilized by error models. } ``` +The `"duration"` field supports seconds (s), milliseconds (ms), microseconds (us), and nanoseconds (ns) as its units. + Currently, `"mop"`s are more defined by the implementation of the Machine and ErrorModel classes in PECOS. Therefore, -the `"metadata"` tag is heavily depended on up to supply values that these classes expect. An example of indicating +the `"metadata"` tag is heavily depended upon to supply values that these classes expect. An example of indicating idling and transport include: ```json5 { "mop": "Idle", "args": [["q", 0], ["q", 5], ["w", 1] ], - "metadata": {"duration": 0.000123 } // typically in seconds + "duration": [0.000123, "s"] // typically in seconds } ``` @@ -457,7 +463,8 @@ idling and transport include: { "mop": "Transport", // potentially using "args" to indicate what qubits are being transported - "metadata": {"duration": 0.0005 } // potentially including what positions to and from qubits moved between or what path taken + "duration": [0.5, "ms"] + "metadata": {...} // potentially including what positions to and from qubits moved between or what path taken } ``` From 72a47a269f65a2c6a365e30d0cea356d5889ae8d Mon Sep 17 00:00:00 2001 From: Kartik Singhal Date: Mon, 23 Oct 2023 11:28:30 -0500 Subject: [PATCH 3/4] feat(model): Angle unit is appended after the angles list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on feedback from Ciarán on the PR --- phir/model.py | 6 +----- phir_spec_qasm.md | 11 +++++------ schema.json | 33 +++++++++++++++------------------ 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/phir/model.py b/phir/model.py index c5cecf1..6a6f6c2 100644 --- a/phir/model.py +++ b/phir/model.py @@ -68,17 +68,13 @@ class Op(BaseModel, abc.ABC): metadata: dict[str, Any] | None = None -Radian: TypeAlias = float -PiRadian = NewType("PiRadian", tuple[float, Literal["pi"]]) - - class QOp(Op): """Quantum operation.""" qop: str returns: list[Bit] | None = None args: list[Bit | list[Bit]] - angles: list[Radian | PiRadian] | None = None + angles: tuple[list[float], Literal["rad", "pi"]] | None = None class COp(Op): diff --git a/phir_spec_qasm.md b/phir_spec_qasm.md index 2af2540..7e64435 100644 --- a/phir_spec_qasm.md +++ b/phir_spec_qasm.md @@ -312,15 +312,14 @@ The generic qop gate structure is: ```json5 { "qop": str, - "angles": [float | [float, "pi"] ...], // Include if gate has one or more angles. + "angles": [[float...], "rad" | "pi"], // Include if gate has one or more angles. "args": [qubit_id, ... | [qubit_id, ... ], ...], // Can be a list of qubit IDs or a list of lists for multi-qubit gates. "metadata": {}, // Optional metadata for potential auxiliary info or to be utilized by error models. "returns": [[str, int], ...] // Include if gate produces output, e.g., a measurement. } ``` -`"angles"` list is expected to be in radians, ie, `float`. For convenience, multiples of ᴨ (pi radians) are also supported in the -form of tuples `[float, "pi"]`. +`"angles"` is a tuple of a list of `float`s and a unit. The units supported are radians (preferred) and multiples of ᴨ (pi radians). Table II details the available qops. @@ -353,12 +352,12 @@ However, multi-qubit gates, such as `CX`, use a list of lists of qubit IDs. E.g. PECOS ensures all qubit IDs in `"args"` are unique, meaning gates don't overlap on the same qubits. -For gates with one or multiple angles, angles are denoted as floats (or pi radians, not shown) in the `"angles"` list: +For gates with one or multiple angles, angles are denoted as floats and a unit in the `"angles"` list: ```json5 { "qop": "RZZ", - "angles": [0.173], + "angles": [[0.173], "rad"], "args": [ [ ["q", 0], ["q", 1] ], [ ["q", 2], ["q", 3] ] @@ -370,7 +369,7 @@ For gates with one or multiple angles, angles are denoted as floats (or pi radia ```json5 { "qop": "U1q", - "angles": [0.524, 1.834], + "angles": [[0.524, 1.834], "rad"], "args": [ [ ["q", 0], ["q", 1], ["q", 2], ["q", 3] ] ], diff --git a/schema.json b/schema.json index f3fcf70..44d9d57 100644 --- a/schema.json +++ b/schema.json @@ -528,26 +528,23 @@ "angles": { "anyOf": [ { - "items": { - "anyOf": [ - { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "items": { "type": "number" }, - { - "maxItems": 2, - "minItems": 2, - "prefixItems": [ - { - "type": "number" - }, - { - "const": "pi" - } - ], - "type": "array" - } - ] - }, + "type": "array" + }, + { + "enum": [ + "rad", + "pi" + ], + "type": "string" + } + ], "type": "array" }, { From bc528fee7487233014440e07be0901a798b13ec9 Mon Sep 17 00:00:00 2001 From: Kartik Singhal Date: Mon, 23 Oct 2023 11:32:25 -0500 Subject: [PATCH 4/4] docs(spec): Make a sentence more precise. --- phir_spec_qasm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phir_spec_qasm.md b/phir_spec_qasm.md index 7e64435..2bb2331 100644 --- a/phir_spec_qasm.md +++ b/phir_spec_qasm.md @@ -352,7 +352,7 @@ However, multi-qubit gates, such as `CX`, use a list of lists of qubit IDs. E.g. PECOS ensures all qubit IDs in `"args"` are unique, meaning gates don't overlap on the same qubits. -For gates with one or multiple angles, angles are denoted as floats and a unit in the `"angles"` list: +For gates with one or multiple angles, angles are denoted as a list of floats and a unit in the `"angles"` field: ```json5 {