microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/replace-qsharp-with-qdk-python-tests

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/pip/qsharp/_device/_atom/_utils.py

92lines · modecode

1# Copyright (c) Microsoft Corporation.
2# Licensed under the MIT License.
3
4from pyqir import (
5 Instruction,
6 Call,
7 Constant,
8 PointerType,
9 Value,
10 ptr_id,
11)
12from typing import Dict
13
14TOLERANCE: float = 1.1920929e-7 # Machine epsilon for 32-bit IEEE FP numbers.
15
16# QIS gates that consume a measurement result; the value is the 0-based index
17# of the result argument. All other pointer-typed arguments of a QIS call are
18# qubit arguments.
19_RESULT_ARG_INDEX: Dict[str, int] = {
20 "__quantum__qis__m__body": 1,
21 "__quantum__qis__mz__body": 1,
22 "__quantum__qis__mresetz__body": 1,
23 "__quantum__qis__read_result__body": 0,
24}
25
26
27# If this is a call to a __qis__ gate, return a dict describing the gate and its arguments.
28def as_qis_gate(instr: Instruction) -> Dict:
29 if isinstance(instr, Call) and instr.callee.name.startswith("__quantum__qis__"):
30 parts = instr.callee.name.split("__")
31 result_idx = _RESULT_ARG_INDEX.get(instr.callee.name)
32 qubit_args = []
33 result_args = []
34 other_args = []
35 for i, arg in enumerate(instr.args):
36 if isinstance(arg.type, PointerType):
37 pid = ptr_id(arg)
38 if pid is None:
39 other_args.append(arg)
40 elif result_idx is not None and i == result_idx:
41 result_args.append(pid)
42 else:
43 qubit_args.append(pid)
44 else:
45 other_args.append(arg)
46 return {
47 "gate": parts[3] + ("_adj" if parts[4] == "adj" else ""),
48 "qubit_args": qubit_args,
49 "result_args": result_args,
50 "other_args": other_args,
51 }
52 return {}
53
54
55# Returns all values and, separately, all measurement results used by the instruction.
56def get_used_values(instr: Instruction) -> tuple[list[Value], list[Value]]:
57 vals = []
58 meas_results = []
59 if isinstance(instr, Call):
60 vals = instr.args
61 if (
62 instr.callee.name == "__quantum__qis__mresetz__body"
63 or instr.callee.name == "__quantum__qis__m__body"
64 or instr.callee.name == "__quantum__qis__mz__body"
65 ):
66 # Measurement uses a result as the second argument
67 meas_results += vals[1:]
68 vals = vals[:1]
69 elif (
70 instr.callee.name == "__quantum__qis__read_result__body"
71 or instr.callee.name == "__quantum__rt__read_result"
72 or instr.callee.name == "__quantum__rt__read_atom_result"
73 ):
74 # Read result uses a result as the first argument
75 meas_results += vals
76 vals = []
77 else:
78 vals = instr.operands
79 vals.append(instr)
80 return (vals, meas_results)
81
82
83# Returns true if any of the used values are in the existing values.
84# Useful for determining if an instruction depends on any instructions in a set.
85def uses_any_value(used_values, existing_values) -> bool:
86 return any(
87 [
88 val in existing_values
89 for val in used_values
90 if not isinstance(val, Constant) or isinstance(val.type, PointerType)
91 ]
92 )
93