############################################################################
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################################################
"""Classes representing variables containing quantum types (i.e. Qubits)."""
from __future__ import annotations
import contextlib
from typing import TYPE_CHECKING, Iterator, Union
from openpulse import ast
from oqpy.base import Var
if TYPE_CHECKING:
from oqpy.program import Program
__all__ = ["Qubit", "QubitArray", "defcal", "PhysicalQubits", "Cal"]
[docs]class Qubit(Var):
"""OQpy variable representing a single qubit."""
def __init__(self, name: str, needs_declaration: bool = True):
super().__init__(name, needs_declaration=needs_declaration)
self.name = name
[docs] def to_ast(self, prog: Program) -> ast.Expression:
"""Converts the OQpy variable into an ast node."""
prog._add_var(self)
return ast.Identifier(self.name)
[docs] def make_declaration_statement(self, program: Program) -> ast.Statement:
"""Make an ast statement that declares the OQpy variable."""
return ast.QubitDeclaration(ast.Identifier(self.name), size=None)
[docs]class PhysicalQubits:
"""Provides a means of accessing qubit variables corresponding to physical qubits.
For example, the openqasm qubit "$3" is accessed by ``PhysicalQubits[3]``.
"""
def __class_getitem__(cls, item: int) -> Qubit:
return Qubit(f"${item}", needs_declaration=False)
# Todo (#51): support QubitArray
[docs]class QubitArray:
"""Represents an array of qubits."""
[docs]@contextlib.contextmanager
def defcal(program: Program, qubits: Union[Qubit, list[Qubit]], name: str) -> Iterator[None]:
"""Context manager for creating a defcal.
.. code-block:: python
with defcal(program, q1, "X"):
program.play(frame, waveform)
"""
program._push()
yield
state = program._pop()
if isinstance(qubits, Qubit):
qubits = [qubits]
stmt = ast.CalibrationDefinition(
ast.Identifier(name),
[], # TODO (#52): support arguments
[ast.Identifier(q.name) for q in qubits],
None, # TODO (#52): support return type,
state.body,
)
program._add_statement(stmt)
for qubit in qubits:
program._add_defcal(qubit.name, name, stmt)
[docs]@contextlib.contextmanager
def Cal(program: Program) -> Iterator[None]:
"""Context manager that begins a cal block."""
program._push()
yield
state = program._pop()
program._add_statement(ast.CalibrationStatement(state.body))