Skip to main content
IBM Quantum Platform

Expressions classiques

qiskit.circuit.classical

Ce module contient une représentation exploratoire des opérations en temps réel sur les valeurs classiques pendant l'exécution du circuit.

À l'heure actuelle, seules les expressions simples portant sur des bits et des registres et donnant lieu à une valeur booléenne sont prises en charge; celles-ci ne peuvent être utilisées que dans les conditions des opérateurs QuantumCircuit.if_test() (IfElseOp) et QuantumCircuit.while_loop() (WhileLoopOp), ainsi que dans l'argument de l'opérateur QuantumCircuit.switch() (SwitchCaseOp).

Remarque

Il s'agit d'un module exploratoire, et bien que nous nous engagions à respecter la politique de dépréciation standard de Qiskit, sachez que la portée du module sera délibérément limitée au départ, et que les premières versions pourraient ne pas évoluer proprement vers la version finale. Il est possible que certains éléments de ce module soient remplacés (sous réserve de dépréciation) au lieu d'être améliorés sous une nouvelle forme.

Le système de types et l'arbre d'expressions seront étendus au fil du temps, et il est possible que les types autorisés de certaines opérations doivent changer entre les versions de Qiskit au fur et à mesure que les capacités de traitement classiques se développent.


Expressions

qiskit.circuit.classical.expr

Les composants nécessaires à la construction des expressions sont tous exportés de l'espace de noms expr dans l'espace de noms qiskit.circuit.classicalvous pouvez donc choisir d'utiliser l'accès qualifié (par exemple expr.Value) ou d'importer directement les noms dont vous avez besoin et de les appeler sans le préfixe.

Il existe deux façons de construire des expressions. Les classes qui forment la représentation du système d'expression ont des constructeurs qui n'effectuent aucune vérification de type; c'est à l'appelant de s'assurer qu'il construit des objets valides. Pour une interface plus conviviale de la construction directe, il existe des fonctions d'aide associées à la plupart des classes qui effectuent la validation et l'inférence de type. Ils sont décrits ci-dessous, dans la section Construction.

Représentation

Le système d'expression est basé sur une représentation arborescente. Tous les nœuds de l'arbre sont des instances finales (non héritables) de la classe de base abstraite :

Expr

class qiskit.circuit.classical.expr.Expr

Bases : object

Classe de base de tous les nœuds de l'arbre d'expression. Le cas de base ne doit jamais être instancié directement.

Elle ne doit pas être sous-classée par les utilisateurs; les sous-classes forment les données internes de la représentation des expressions et il n'est pas judicieux d'en ajouter en dehors du code de la bibliothèque Qiskit.

Toutes les sous-classes doivent définir leur type attribut dans leur __init__constructeur et ne doivent pas appeler le constructeur du parent.

Ces objets sont mutables et ne doivent pas être réutilisés à un autre endroit sans copie.

Toutes les instances Expr définissent un attribut booléen const , qui indique si l'expression peut être évaluée au moment de la compilation. La plupart des classes d'expressions le déduisent lors de la construction en se basant sur la constance de leurs opérandes.

La base des variables dynamiques est la variable Varqui peut être soit une variable temps réel arbitrairement typée, soit une enveloppe autour d'une variable de type Clbit ou ClassicalRegister.

Var

class qiskit.circuit.classical.expr.Var(var, type, *, name=None)

Bases : Expr

Une variable classique.

Ces variables se présentent sous deux formes : une variable de type nouveau qui possède son emplacement de stockage et un nom associé, et une variable de type ancien qui englobe une variable de type Clbit ou ClassicalRegister qui appartient à un circuit contenant. En général, la construction de variables destinées à être utilisées dans des programmes doit utiliser Var.new() ou QuantumCircuit.add_var().

Les variables sont immuables une fois créées; elles peuvent donc servir de clés dans un dictionnaire.

name

Nom de la variable. Cette variable doit exister si l'attribut backing var est de type UUIDnew-style, c'est-à-dire s'il s'agit d'une variable de style nouveau, et doit être None de type old-style s'il s'agit d'une variable de style ancien.

new

classmethod new(name, ty)

Générer une nouvelle variable nommée qui possède son propre stockage de sauvegarde.

var

Une référence au stockage de données de sauvegarde de Var l'instance. ClassicalRegisterLorsqu'on transfère des ClassicalRegister instances de Clbit type ancien vers un Var, il s'agit précisément du Clbit ou du. Si la variable est une variable classique de nouveau type (c'est-à-dire une variable disposant de sa propre mémoire, distincte de l'ancienne Clbit/ClassicalRegister modèle), ce champ contiendra un UUID identifiant unique permettant de l'identifier.

De même, les littéraux utilisés dans les expressions (tels que les entiers) doivent être élevés au rang de nœuds Value avec les types associés. A Value est toujours considérée comme une expression constante.

Valeur

class qiskit.circuit.classical.expr.Value(value, type)

Bases : Expr

Une seule valeur scalaire.

Les variables d'étirement à utiliser dans les expressions de durée sont représentées par le nœud Stretch nœud.

Étirement

class qiskit.circuit.classical.expr.Stretch(var, name)

Bases : Expr

Une variable extensible.

En général, la construction de variables extensibles destinées à être utilisées dans des programmes devrait utiliser Stretch.new() ou QuantumCircuit.add_stretch()

name

Le nom de la variable d'étirement.

new

classmethod new(name)

Générer une nouvelle variable d'étirement nommée.

var

A UUID pour identifier de manière unique ce tronçon.

Les opérations traditionnellement associées aux opérateurs pré, post ou infixes dans la programmation sont représentées par les opérateurs Unary et Binary selon le cas. Chacun d'entre eux prend un code de type d'opération, qui est exposé sous forme d'énumérations à l'intérieur de chaque classe en tant que Unary.Op et Binary.Op respectivement.

Unaire

class qiskit.circuit.classical.expr.Unary(op, operand, type)

Bases : Expr

Une expression unaire.

Paramètres

  • op - Le code d'opération décrivant l'opération en cours.
  • operand - L'opérande de l'opération.
  • type - Le type résolu du résultat.
Op

class Op(*values)

Bases : Enum

Enumération des opcodes pour les opérations unaires.

La négation bit à bit BIT_NOT prend un bit unique ou un entier non signé de largeur connue et renvoie une valeur du même type.

La négation logique LOGIC_NOT prend une entrée qui est implicitement transformée en booléen et renvoie un booléen.

La négation arithmétique NEGATE prend en entrée une valeur de type float ou duration et renvoie une valeur du même type.

Binaire

class qiskit.circuit.classical.expr.Binary(op, left, right, type)

Bases : Expr

Une expression binaire.

Paramètres

  • op - Le code d'opération décrivant l'opération en cours.
  • left - L'opérande de gauche.
  • right - L'opérande de droite.
  • type - Le type résolu du résultat.
Op

class Op(*values)

Bases : Enum

Enumération des opcodes pour les opérations binaires.

Les opérations bit à bit BIT_AND, BIT_OR et BIT_XOR s'appliquent à deux opérandes de même type, qui doivent être un bit unique ou un entier non signé de largeur fixe. Le type résultant est le même que les deux types d'entrée.

Les opérations logiques LOGIC_AND et LOGIC_OR contraignent d'abord implicitement leurs arguments à être des booléens, puis appliquent l'opération logique. Le type résultant est toujours booléen.

Les relations mathématiques binaires EQUAL, NOT_EQUAL, LESS, LESS_EQUAL, GREATER et GREATER_EQUAL prennent des entiers non signés (avec une conversion implicite pour qu'ils aient la même largeur) et renvoient un booléen.

Les opérations de décalage de bits SHIFT_LEFT et SHIFT_RIGHT peuvent prendre des types de conteneurs de type bit (par exemple, des entiers non signés) comme opérande de gauche, et n'importe quel type d'entier comme opérande de droite. Dans tous les cas, la largeur du bit de sortie est la même que celle de l'entrée, et les zéros remplissent les espaces "exposés".

Les opérateurs arithmétiques ADD binaires, SUB, MUL, et DIV peuvent être appliqués à deux nombres à virgule flottante ou à deux entiers non signés, qui doivent être mis à la même largeur lors de leur création à l'aide d'un transtypage. Les DIV opérateurs ADD, SUB, et peuvent être appliqués à deux durées pour donner une autre durée, ou un nombre à virgule flottante dans le cas de DIV. L'opérateur MUL peut également être appliqué à une durée et à un type numérique, ce qui donne une autre durée. Enfin, DIV l'opérateur peut être utilisé pour diviser une durée par un nombre, ce qui donne une durée.

Les types de type bit (entiers non signés) peuvent être indexés par des types entiers, représentés par Index. Le résultat est un seul bit. L'expression résultante a un emplacement mémoire associé (et peut donc être utilisée comme valeur l pour Storeetc.) si la cible est également une valeur l.

Indice

class qiskit.circuit.classical.expr.Index(target, index, type)

Bases : Expr

Une expression d'indexation.

Paramètres

  • target - L'objet à indexer.
  • index - L'expression qui effectue l'indexation.
  • type - Le type résolu du résultat.

Lors de la construction d'expressions, il faut s'assurer que les types sont valides pour l'opération. Les tentatives de construction d'expressions avec des types non valides entraîneront l'apparition d'une erreur régulière Python TypeError.

Dans ce système, les expressions sont définies de manière à n'agir que sur certains ensembles de types. Toutefois, les valeurs peuvent être moulées dans un super-type approprié afin de satisfaire aux exigences de typage. Dans ce cas, un nœud de l'arbre d'expression est utilisé pour représenter la promotion. Dans tous les cas où les opérations indiquent qu'elles "moulent implicitement" ou "contraignent" leurs arguments, l'arbre d'expression doit comporter ce nœud représentant la conversion.

cast

class qiskit.circuit.classical.expr.Cast(operand, type, implicit=False)

Bases : Expr

Une conversion d'un type à un autre, impliquée par l'utilisation d'une expression dans un contexte différent.

Construction

La construction directe de la représentation de l'arbre est fastidieuse et il est facile de faire une erreur de typage. Dans de nombreux cas, une grande partie du typage peut être déduite, les valeurs scalaires peuvent être automatiquement promues en instances, et toutes les promotions nécessaires peuvent être résolues en instances appropriées Value instances, et toutes les promotions nécessaires peuvent être résolues en nœuds Cast appropriés.

Les fonctions et méthodes décrites dans cette section constituent une manière plus conviviale de construire l'arbre d'expression, tout en restant proche de la représentation interne. Toutes ces fonctions transforment automatiquement les valeurs scalaires valides de Python en valeurs correspondantes de Var ou Value correspondants, et résoudront toute conversion implicite nécessaire en votre nom. Si vous souhaitez utiliser directement une valeur scalaire en tant que nœud Expr vous pouvez le faire manuellement lift() manuellement.

lift

qiskit.circuit.classical.expr.lift(value, /, type=None)

GitHub

Soulevez le site Python value jusqu'à ce qu'il atteigne le niveau Value ou Var.

Si un type explicite est donné, le typage dans la sortie le reflétera.

Exemples

Transformer des objets de circuits simples en Var instances :

>>> from qiskit.circuit import Clbit, ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.lift(Clbit())
Var(<clbit>, Bool())
>>> expr.lift(ClassicalRegister(3, "c"))
Var(ClassicalRegister(3, "c"), Uint(3))

Le type de la valeur renvoyée peut être modifié si la valeur fournie peut être interprétée sans perte comme étant du type spécifié (utilisez cast() pour effectuer l'ensemble complet des opérations de conversion, y compris celles entraînant une perte) :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr, types
>>> expr.lift(ClassicalRegister(3, "c"), types.Uint(5))
Var(ClassicalRegister(3, "c"), Uint(5))
>>> expr.lift(5, types.Uint(4))
Value(5, Uint(4))

Paramètres

Type de retour

Expr

En règle générale, vous devez créer des instances Var en utilisant la méthode QuantumCircuit.add_var() pour les déclarer dans un contexte de circuit, car une méthode QuantumCircuit n'acceptera pas un Expr qui contient des variables qui ne sont pas déjà déclarées en son sein, car il doit savoir comment allouer la mémoire et comment la variable sera initialisée. Toutefois, si vous souhaitez le faire manuellement, vous devez utiliser l'appel de bas niveau Var.new() pour générer en toute sécurité une variable nommée à utiliser.

Vous pouvez spécifier manuellement les casts dans les cas où le cast est autorisé sous forme explicite, mais peut être avec perte (comme le cast d'une précision plus élevée Uint vers un autre de moindre précision).

cast

qiskit.circuit.classical.expr.cast(operand, type, /)

GitHub

Créer un cast explicite de la valeur donnée vers le type donné.

Exemples

Ajout d'un nœud de conversion explicite qui convertit explicitement un type de précision supérieure en un type de précision inférieure :

>>> from qiskit.circuit.classical import expr, types
>>> value = expr.value(5, types.Uint(32))
>>> expr.cast(value, types.Uint(8))
Cast(Value(5, types.Uint(32)), types.Uint(8), implicit=False)

Paramètres

Type de retour

Expr

Il existe des fonctions d'aide à la construction pour chacune des opérations unaires.

bit_not

qiskit.circuit.classical.expr.bit_not(operand, /)

GitHub

Crée un nœud d'expression bitwise "not" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant la valeur dans un nœud "not" si nécessaire Value si nécessaire.

Exemples

Négation bit à bit de a ClassicalRegister:

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.bit_not(ClassicalRegister(3, "c"))
Unary(Unary.Op.BIT_NOT, Var(ClassicalRegister(3, 'c'), Uint(3)), Uint(3))

Paramètres

operand (Any)

Type de retour

Expr

logic_not

qiskit.circuit.classical.expr.logic_not(operand, /)

GitHub

Crée un nœud d'expression logique "not" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant la valeur dans un nœud "not" si nécessaire Value si nécessaire.

Exemples

Négation logique de a ClassicalRegister:

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.logic_not(ClassicalRegister(3, "c"))
Unary(Unary.Op.LOGIC_NOT, Cast(Var(ClassicalRegister(3, 'c'), Uint(3)), Bool(), implicit=True), Bool())

Paramètres

operand (Any)

Type de retour

Expr

negate

qiskit.circuit.classical.expr.negate(operand, /)

GitHub

Négation d'un nœud d'expression à partir de la valeur fournie, en effectuant les conversions implicites nécessaires et en transformant la valeur en un Value nœud si nécessaire.

Exemples

Négation d'un nombre à virgule flottante :

>>> from qiskit.circuit.classical import expr
>>> expr.negate(5.0)
Unary(Unary.Op.NEGATE, Value(5.0, Float()), Float())

Négation d'une durée :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.negate(Duration.dt(1000))
Unary(Unary.Op.NEGATE, Value(Duration.dt(1000), Duration()), Duration())

Paramètres

operand (Any)

Type de retour

Expr

De même, des fonctions d'aide sont définies pour les opérations binaires et les relations.

bit_and

qiskit.circuit.classical.expr.bit_and(left, right, /)

GitHub

Crée un nœud d'expression binaire "et" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans des nœuds "et" si nécessaire Value si nécessaire.

Exemples

La combinaison "et" d'un registre classique et d'un entier littéral :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.bit_and(ClassicalRegister(3, "c"), 0b111)
Binary(Binary.Op.BIT_AND, Var(ClassicalRegister(3, 'c'), Uint(3)), Value(7, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

bit_or

qiskit.circuit.classical.expr.bit_or(left, right, /)

GitHub

Crée un nœud d'expression binaire "ou" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans des nœuds "ou" si nécessaire Value si nécessaire.

Exemples

Ou binaire d'un registre classique et d'un littéral d'entier :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.bit_or(ClassicalRegister(3, "c"), 0b101)
Binary(Binary.Op.BIT_OR, Var(ClassicalRegister(3, 'c'), Uint(3)), Value(5, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

bit_xor

qiskit.circuit.classical.expr.bit_xor(left, right, /)

GitHub

Crée un nœud d'expression binaire "exclusif ou" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs en nœuds Value si nécessaire.

Exemples

Ou exclusif bit à bit d'un registre classique et d'un entier littéral :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.bit_xor(ClassicalRegister(3, "c"), 0b101)
Binary(Binary.Op.BIT_XOR, Var(ClassicalRegister(3, 'c'), Uint(3)), Value(5, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

logic_and

qiskit.circuit.classical.expr.logic_and(left, right, /)

GitHub

Crée un nœud d'expression logique "et" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans des nœuds "et" si nécessaire Value si nécessaire.

Exemples

Le "et" logique de deux bits classiques :

>>> from qiskit.circuit import Clbit
>>> from qiskit.circuit.classical import expr
>>> expr.logic_and(Clbit(), Clbit())
Binary(Binary.Op.LOGIC_AND, Var(<clbit 0>, Bool()), Var(<clbit 1>, Bool()), Bool())

Paramètres

Type de retour

Expr

logic_or

qiskit.circuit.classical.expr.logic_or(left, right, /)

GitHub

Crée un nœud d'expression logique "ou" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs en nœuds "ou" si nécessaire Value si nécessaire.

Exemples

Ou logique de deux bits classiques

>>> from qiskit.circuit import Clbit
>>> from qiskit.circuit.classical import expr
>>> expr.logic_or(Clbit(), Clbit())
Binary(Binary.Op.LOGIC_OR, Var(<clbit 0>, Bool()), Var(<clbit 1>, Bool()), Bool())

Paramètres

Type de retour

Expr

equal

qiskit.circuit.classical.expr.equal(left, right, /)

GitHub

Crée un nœud d'expression "égal" à partir de la valeur donnée, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Exemples

Égalité entre un registre classique et un nombre entier :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.equal(ClassicalRegister(3, "c"), 7)
Binary(Binary.Op.EQUAL, Var(ClassicalRegister(3, "c"), Uint(3)), Value(7, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

not_equal

qiskit.circuit.classical.expr.not_equal(left, right, /)

GitHub

Crée un nœud d'expression "pas égal" à partir de la valeur donnée, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Exemples

Inégalité entre un registre classique et un nombre entier :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.not_equal(ClassicalRegister(3, "c"), 7)
Binary(Binary.Op.NOT_EQUAL, Var(ClassicalRegister(3, "c"), Uint(3)), Value(7, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

less

qiskit.circuit.classical.expr.less(left, right, /)

GitHub

Crée un nœud d'expression "moins que" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs en nœuds Value si nécessaire.

Exemples

Demande si un registre classique est inférieur à un entier :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.less(ClassicalRegister(3, "c"), 5)
Binary(Binary.Op.LESS, Var(ClassicalRegister(3, "c"), Uint(3)), Value(5, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

less_equal

qiskit.circuit.classical.expr.less_equal(left, right, /)

GitHub

Crée un nœud d'expression "inférieur ou égal à" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans les nœuds Value si nécessaire.

Exemples

Demande si un registre classique est inférieur ou égal à un autre :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.less_equal(ClassicalRegister(3, "a"), ClassicalRegister(3, "b"))
Binary(Binary.Op.LESS_EQUAL, Var(ClassicalRegister(3, "a"), Uint(3)), Var(ClassicalRegister(3, "b"), Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

greater

qiskit.circuit.classical.expr.greater(left, right, /)

GitHub

Crée un nœud d'expression "plus grand que" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans les nœuds Value si nécessaire.

Exemples

Demande si un registre classique est supérieur à un entier :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.greater(ClassicalRegister(3, "c"), 5)
Binary(Binary.Op.GREATER, Var(ClassicalRegister(3, "c"), Uint(3)), Value(5, Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

greater_equal

qiskit.circuit.classical.expr.greater_equal(left, right, /)

GitHub

Crée un nœud d'expression "supérieur ou égal à" à partir de la valeur donnée, en résolvant toute conversion implicite et en élevant les valeurs dans les nœuds Value si nécessaire.

Exemples

Demande si un registre classique est supérieur ou égal à un autre :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.greater_equal(ClassicalRegister(3, "a"), ClassicalRegister(3, "b"))
Binary(Binary.Op.GREATER_EQUAL, Var(ClassicalRegister(3, "a"), Uint(3)), Var(ClassicalRegister(3, "b"), Uint(3)), Uint(3))

Paramètres

Type de retour

Expr

shift_left

qiskit.circuit.classical.expr.shift_left(left, right, /, type=None)

GitHub

Créer un nœud d'expression "bitshift left" à partir des deux valeurs données, en résolvant toute conversion implicite et en élevant les valeurs en nœuds Value si nécessaire.

Si type est donné, l'opérande left lui sera imposé (si possible).

Exemples

Déplacer la valeur d'une variable autonome vers la gauche d'un certain montant :

>>> from qiskit.circuit.classical import expr, types
>>> a = expr.Var.new("a", types.Uint(8))
>>> expr.shift_left(a, 4)
Binary(Binary.Op.SHIFT_LEFT, Var(<UUID>, Uint(8), name='a'), Value(4, Uint(3)), Uint(8))

Décale un littéral entier d'une valeur variable, en imposant le type du littéral :

>>> expr.shift_left(3, a, types.Uint(16))
Binary(Binary.Op.SHIFT_LEFT, Value(3, Uint(16)), Var(<UUID>, Uint(8), name='a'), Uint(16))

Paramètres

Type de retour

Expr

shift_right

qiskit.circuit.classical.expr.shift_right(left, right, /, type=None)

GitHub

Crée un nœud d'expression "bitshift right" à partir des valeurs données, en résolvant toute conversion implicite et en élevant les valeurs en nœuds Value si nécessaire.

Si type est donné, l'opérande left lui sera imposé (si possible).

Exemples

Décaler la valeur d'un registre classique vers la droite d'un certain montant :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.shift_right(ClassicalRegister(8, "a"), 4)
Binary(Binary.Op.SHIFT_RIGHT, Var(ClassicalRegister(8, "a"), Uint(8)), Value(4, Uint(3)), Uint(8))

Paramètres

Type de retour

Expr

add

qiskit.circuit.classical.expr.add(left, right, /)

GitHub

Crée un nœud d'expression d'addition à partir des valeurs données, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Exemples

Addition de deux nombres à virgule flottante :

>>> from qiskit.circuit.classical import expr
>>> expr.add(5.0, 2.0)
Binary(Binary.Op.ADD, Value(5.0, Float()), Value(2.0, Float()), Float())

Ajout de deux durées :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.add(Duration.dt(1000), Duration.dt(1000))
Binary(Binary.Op.ADD, Value(Duration.dt(1000), Duration()), Value(Duration.dt(1000), Duration()), Duration())

Paramètres

Type de retour

Expr

sub

qiskit.circuit.classical.expr.sub(left, right, /)

GitHub

Crée un nœud d'expression de soustraction à partir des valeurs données, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Exemples

Soustraction de deux nombres à virgule flottante :

>>> from qiskit.circuit.classical import expr
>>> expr.sub(5.0, 2.0)
Binary(Binary.Op.SUB, Value(5.0, Float()), Value(2.0, Float()), Float())

Soustraction de deux durées :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.add(Duration.dt(1000), Duration.dt(1000))
Binary(Binary.Op.SUB, Value(Duration.dt(1000), Duration()), Value(Duration.dt(1000), Duration()), Duration())

Paramètres

Type de retour

Expr

mul

qiskit.circuit.classical.expr.mul(left, right)

GitHub

Crée un nœud d'expression de multiplication à partir des valeurs données, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Cette fonction peut être utilisée pour multiplier des opérandes numériques du même type, ou pour multiplier un opérande de durée par un opérande numérique.

Exemples

Multiplication de deux nombres à virgule flottante :

>>> from qiskit.circuit.classical import expr
>>> expr.mul(5.0, 2.0)
Binary(Binary.Op.MUL, Value(5.0, Float()), Value(2.0, Float()), Float())

Multiplication d'une durée par un flottant :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.mul(Duration.dt(1000), 0.5)
Binary(Binary.Op.MUL, Value(Duration.dt(1000), Duration()), Value(0.5, Float()), Duration())

Paramètres

Type de retour

Expr

div

qiskit.circuit.classical.expr.div(left, right)

GitHub

Crée un nœud d'expression de division à partir des valeurs données, en résolvant toute conversion implicite et en transformant les valeurs en nœuds Value si nécessaire.

Cette fonction peut être utilisée pour diviser des opérandes numériques du même type, pour diviser un opérande par un opérande numérique ou pour diviser deux opérandes numériques Duration par un opérande numérique, ou pour diviser deux opérandes Duration ce qui donne une expression de type Float.

Exemples

Division de deux nombres à virgule flottante :

>>> from qiskit.circuit.classical import expr
>>> expr.div(5.0, 2.0)
Binary(Binary.Op.DIV, Value(5.0, Float()), Value(2.0, Float()), Float())

Division de deux durées :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.div(Duration.dt(10000), Duration.dt(1000))
Binary(Binary.Op.DIV, Value(Duration.dt(10000), Duration()), Value(Duration.dt(1000), Duration()), Float())

Division d'une durée par un flotteur :

>>> from qiskit.circuit import Duration
>>> from qiskit.circuit.classical import expr
>>> expr.div(Duration.dt(10000), 12.0)
Binary(Binary.Op.DIV, Value(Duration.dt(10000), Duration()), Value(12.0, types.Float()), Duration())

Paramètres

Type de retour

Expr

Vous pouvez indexer des nombres entiers non signés et des nombres binaires en utilisant un autre nombre entier non signé de n'importe quelle largeur. Cela inclut les opérations de stockage, si la cible de l'index est accessible en écriture.

index

qiskit.circuit.classical.expr.index(target, index, /)

GitHub

Indexer le site target avec l'entier donné index, en élevant les valeurs en nœuds si nécessaire Value si nécessaire.

Elle peut être utilisée comme cible d'un Storesi l'adresse target est elle-même une valeur l.

Exemples

Indexation d'un registre classique avec un littéral :

>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.index(ClassicalRegister(8, "a"), 3)
Index(Var(ClassicalRegister(8, "a"), Uint(8)), Value(3, Uint(2)), Bool())

Paramètres

Type de retour

Expr

La méthode traditionnelle de Qiskit pour spécifier des conditions d'égalité à utiliser dans les conditionnelles est d'utiliser un double-tuple de a Clbit ou ClassicalRegister et d'un entier. Il s'agit d'une condition d'égalité exacte et il n'y a aucune possibilité de spécifier d'autres relations. La fonction d'aide lift_legacy_condition() convertit cet ancien format en la nouvelle syntaxe d'expression.

lift_legacy_condition

qiskit.circuit.classical.expr.lift_legacy_condition(condition, /)

GitHub

Transformer une ancienne condition d'égalité de deux tuple en une condition de nouveau style Expr.

Paramètres

condition (tuple[qiskit.circuit.Clbit |qiskit.circuit.ClassicalRegister, int])

Type de retour

Expr

Travailler avec l'arbre d'expression

Un consommateur typique de l'arbre d'expression souhaite parcourir l'arbre de manière récursive, potentiellement avec état, en agissant sur chaque nœud différemment en fonction de son type. Il s'agit naturellement d'un problème de double répartition; la logique de "ce qui doit être fait" est vraisemblablement étatique et les utilisateurs devraient être libres de définir leurs propres opérations, alors que chaque nœud définit "ce sur quoi on agit". Nous permettons cette double distribution en fournissant une classe de visiteurs de base pour l'arbre d'expression.

ExprVisitor

class qiskit.circuit.classical.expr.ExprVisitor

GitHub

Bases : Generic[_T_co]

Classe de base pour les visiteurs de l'arbre Expr l'arbre. Les sous-classes doivent surcharger les méthodes visit_* qu'elles sont en mesure de gérer et doivent être organisées de manière à ce que les méthodes inexistantes ne soient jamais appelées.

visit_binary

visit_binary(node, /)

GitHub

Paramètres

node (Binary)

Type de retour

_T_co

visit_cast

visit_cast(node, /)

GitHub

Paramètres

node (Cast)

Type de retour

_T_co

visit_generic

visit_generic(node, /)

GitHub

Paramètres

node (Expr)

Type de retour

_T_co

visit_index

visit_index(node, /)

GitHub

Paramètres

node (Index)

Type de retour

_T_co

visit_stretch

visit_stretch(node, /)

GitHub

Paramètres

node (Stretch)

Type de retour

_T_co

visit_unary

visit_unary(node, /)

GitHub

Paramètres

node (Unary)

Type de retour

_T_co

visit_value

visit_value(node, /)

GitHub

Paramètres

node (Value)

Type de retour

_T_co

visit_var

visit_var(node, /)

GitHub

Paramètres

node (Var)

Type de retour

_T_co

Les consommateurs de l'arbre d'expression doivent sous-classer le visiteur et surcharger les méthodes visit_* qu'ils souhaitent utiliser. Toute méthode non surchargée appellera visit_generic()qui, si elle n'est pas surchargée, lèvera un RuntimeError pour s'assurer que vous savez si de nouveaux nœuds ont été ajoutés à l'arbre d'expression que vous n'êtes pas encore en train de traiter.

Pour la commodité des visiteurs simples qui n'ont besoin que d'inspecter les variables d'une expression et non la structure générale, la méthode de l'itérateur iter_vars() est fournie.

iter_vars

qiskit.circuit.classical.expr.iter_vars(node)

GitHub

Obtenir un itérateur sur les Var référencés à n'importe quel niveau dans le fichier Expr.

Exemples

Imprimez le nom de chaque ClassicalRegister rencontré :

from qiskit.circuit import ClassicalRegister
from qiskit.circuit.classical import expr

cr1 = ClassicalRegister(3, "a")
cr2 = ClassicalRegister(3, "b")

for node in expr.iter_vars(expr.bit_and(expr.bit_not(cr1), cr2)):
    if isinstance(node.var, ClassicalRegister):
        print(node.var.name)
Voir aussi

iter_identifiers()

Obtenir un itérateur sur tous les nœuds identificateurs de l'expression, y compris les nœuds Var et Stretch et les nœuds.

Paramètres

node (Expr)

Type de retour

Iterator[Var]

Pour itérer sur toutes les variables, y compris les variables extensibles, la méthode iterator iter_identifiers() est fournie.

iter_identifiers

qiskit.circuit.classical.expr.iter_identifiers(node)

GitHub

Obtenir un itérateur sur les éléments Var et Stretch référencés à n'importe quel niveau dans l'élément Expr.

Exemples

Imprimez le nom de chaque ClassicalRegister rencontré :

from qiskit.circuit import ClassicalRegister
from qiskit.circuit.classical import expr

cr1 = ClassicalRegister(3, "a")
cr2 = ClassicalRegister(3, "b")

for node in expr.iter_vars(expr.bit_and(expr.bit_not(cr1), cr2)):
    if isinstance(node.var, ClassicalRegister):
        print(node.var.name)
Voir aussi

iter_vars()

Obtenir un itérateur sur les nœuds de l'expression Var de l'expression.

Paramètres

node (Expr)

Type de retour

Iterator[* Var* | Stretch ]

Deux expressions peuvent être comparées pour une égalité structurelle directe en utilisant l'opérateur intégré Python == . En général, cependant, on peut vouloir comparer deux expressions de manière un peu plus sémantique, en permettant que les nœuds qu'elles contiennent soient liés à des descriptions différentes de l'emplacement de la mémoire entre deux circuits différents Var à l'intérieur de ces expressions soient liés à des descriptions différentes de l'emplacement de la mémoire entre deux circuits différents. Dans ce cas, on peut utiliser structurally_equivalent() avec deux fonctions "clés" appropriées pour effectuer la comparaison.

structurally_equivalent

qiskit.circuit.classical.expr.structurally_equivalent(left, right, left_var_key=None, right_var_key=None)

GitHub

Ces deux expressions ont-elles exactement la même structure arborescente, jusqu'à une fonction clé pour les Var ?

En d'autres termes, ces deux expressions sont-elles exactement les mêmes arbres, si ce n'est que nous comparons les champs en appelant la fonction appropriée sur eux, et en comparant la sortie pour l'égalité Var.var en appelant la fonction *_var_key appropriée et en comparant les résultats pour vérifier l'égalité. Cette fonction n'autorise aucune "équivalence" sémantique telle que l'affirmation que a == b est équivalent à b == a; l'ordre d'évaluation des opérandes pourrait, en général, rendre une telle affirmation fausse (considérons les fonctions hypothétiques de extern qui accèdent à l'état global).

Les fonctions clés ne sont soumises à aucune exigence, si ce n'est que leurs résultats doivent être assortis de méthodes générales __eq__ . Si une fonction clé renvoie None, la variable sera utilisée mot pour mot.

Paramètres

  • left (Expr) – l'un des Expr nœuds.
  • right (Expr) – l'autre Expr nœud.
  • left_var_key (Callable[[Any], Any] | None) – un appel dont la sortie doit être utilisée lors de la comparaison des Var.var attributs. Si cet argument est None ou si sa sortie est None pour une variable donnée dans left, la variable sera utilisée mot pour mot.
  • right_var_key (Callable[[Any], Any] | None) – identique à left_var_key, mais utilisé pour les variables de right .

Type de retour

booléen

Exemples

Comparaison de deux expressions pour l'équivalence structurelle, sans remappage des variables. Elles sont différentes parce que les différentes instances se comparent différemment Clbit comparent différemment :

>>> from qiskit.circuit import Clbit
>>> from qiskit.circuit.classical import expr
>>> left_bits = [Clbit(), Clbit()]
>>> right_bits = [Clbit(), Clbit()]
>>> left = expr.logic_and(expr.logic_not(left_bits[0]), left_bits[1])
>>> right = expr.logic_and(expr.logic_not(right_bits[0]), right_bits[1])
>>> expr.structurally_equivalent(left, right)
False

Comparaison des deux mêmes expressions, mais cette fois en utilisant des fonctions de correspondance qui associent les bits à de simples indices :

>>> left_key = {var: i for i, var in enumerate(left_bits)}.get
>>> right_key = {var: i for i, var in enumerate(right_bits)}.get
>>> expr.structurally_equivalent(left, right, left_key, right_key)
True

Certaines expressions ont des emplacements de mémoire associés, d'autres peuvent être purement temporaires. Vous pouvez utiliser is_lvalue() pour déterminer si une expression est associée à un emplacement mémoire.

is_lvalue

qiskit.circuit.classical.expr.is_lvalue(node, /)

GitHub

Retourne si cette expression peut être utilisée dans des positions de valeur l, c'est-à-dire si elle a un emplacement bien défini dans la mémoire, par exemple un emplacement qui pourrait être accessible en écriture.

Le fait qu'il s'agisse d'une valeur de type l est une condition nécessaire mais non suffisante pour que cet emplacement soit accessible en écriture; il est possible qu'un objet plus grand contenant cet emplacement mémoire n'autorise pas l'écriture depuis la portée qui tente d'y écrire. Il s'agirait toutefois d'une propriété d'accès du programme hôte, et non d'une propriété inhérente au système d'expression.

Une expression constante n'est jamais une valeur l.

Exemples

Les valeurs littérales ne sont jamais des valeurs l; aucun emplacement mémoire n'est associé (par exemple) à la constante 1:

>>> from qiskit.circuit.classical import expr
>>> expr.is_lvalue(expr.lift(2))
False

Var sont toujours des valeurs l, car ils ont toujours un emplacement mémoire associé :

>>> from qiskit.circuit.classical import types
>>> from qiskit.circuit import Clbit
>>> expr.is_lvalue(expr.Var.new("a", types.Bool()))
True
>>> expr.is_lvalue(expr.lift(Clbit()))
True

Actuellement, il n'existe pas d'opérations unaires ou binaires sur les variables qui puissent produire une expression de valeur l, mais il est probable qu'à l'avenir, une sorte d'opération d'"indexation" sera ajoutée, qui pourrait produire des valeurs l :

>>> a = expr.Var.new("a", types.Uint(8))
>>> b = expr.Var.new("b", types.Uint(8))
>>> expr.is_lvalue(a) and expr.is_lvalue(b)
True
>>> expr.is_lvalue(expr.bit_and(a, b))
False

Paramètres

node (Expr)

Type de retour

booléen


saisie

qiskit.circuit.classical.types

Représentation

Le système de type de l'arbre d'expression est exposé à travers ce module. Ceci est intrinsèquement lié au système d'expression du module expr car la plupart des expressions ne peuvent être comprises que dans le contexte des types sur lesquels elles agissent.

Tous les types héritent d'une classe de base abstraite :

Type

class qiskit.circuit.classical.types.Type

Bases : object

Classe de base de tous les nœuds de l'arbre des types. Le cas de base ne doit jamais être instancié directement.

Elle ne doit pas être sous-classée par les utilisateurs; les sous-classes forment les données internes de la représentation des expressions et il n'est pas judicieux d'en ajouter en dehors du code de la bibliothèque Qiskit.

Les types doivent être considérés comme des objets immuables et ne doivent pas être modifiés. Il est permis de réutiliser un Type provenant d'un autre objet sans le copier, et c'est généralement la meilleure approche en termes de performances. Type sont conçus pour être de petites quantités de données, et il est préférable de pointer vers la même instance de données lorsque c'est possible plutôt que d'allouer une nouvelle version de la même chose. Dans la mesure du possible, les constructeurs de la classe renvoient des instances singleton pour faciliter cette opération.

Le type Bool représente Clbit et les littéraux True et False, le type Uint représente ClassicalRegister et Python les entiers, le type Float représente Python flottants, et le type Duration représente une durée à utiliser dans les opérations de circuit tenant compte du temps.

Bool

class qiskit.circuit.classical.types.Bool

Bases : Type

Le type booléen. Celui-ci a exactement deux valeurs : True et False.

Uint

class qiskit.circuit.classical.types.Uint(width)

Bases : Type

Un entier non signé d'une largeur de bit fixe.

Flottant

class qiskit.circuit.classical.types.Float

Bases : Type

Un nombre à virgule flottante à double précision IEEE-754.

À l'avenir, il pourra également être utilisé pour représenter d'autres valeurs flottantes de largeur fixe.

Durée

class qiskit.circuit.classical.types.Duration

Bases : Type

Une durée, éventuellement négative.

Travailler avec les types

Certaines fonctions supplémentaires de ces types sont documentées dans les sections suivantes. Les utilisateurs qui construisent des expressions à l'aide de l' interface de construction orientée vers l'utilisateur ne devraient pas avoir besoin de les utiliser.

Ordre partiel des types

Le système de types est doté d'un ordre partiel, où a<ba < b est interprété comme " aa est un sous-type strict de bb ". Notez que l'ordre partiel est un sous-ensemble du graphe orienté qui décrit les opérations de distribution explicites autorisées entre les types. L'ordre partiel définit quand un type peut être interprété directement sans perte comme un autre.

L'interface de bas niveau permettant d'interroger la relation de sous-typage est la fonction order() fonction.

order

qiskit.circuit.classical.types.order(left, right, /)

GitHub

Obtenir la relation d'ordre entre les deux types sous la forme d'une énumération.

Exemples

Comparez deux Uint types de largeur différente :

>>> from qiskit.circuit.classical import types
>>> types.order(types.Uint(8), types.Uint(16))
Ordering.LESS

Comparez deux types qui n'ont pas d'ordre entre eux :

>>> types.order(types.Uint(8), types.Bool())
Ordering.NONE

Paramètres

Type de retour

Commande

La valeur de retour est une énumération Ordering qui décrit, le cas échéant, la relation de sous-typage existant entre les deux types.

Ordre

class qiskit.circuit.classical.types.Ordering(*values)

GitHub

Bases : Enum

Enumération des relations possibles entre deux types. Les types n'ont qu'un ordre partiel, il est donc possible que deux types n'aient aucune relation de sous-typage.

Il convient de noter que la relation sous-/supériorité n'est pas la même que la possibilité de faire passer explicitement un type d'un type à l'autre.

Certaines méthodes d'aide sont ensuite définies en fonction de cette primitive de bas niveau order() de bas niveau :

is_subtype

qiskit.circuit.classical.types.is_subtype(left, right, /, strict=False)

GitHub

La relation leftright\text{left} \le \text{right} est-elle valable? S'il n'y a pas de relation d'ordre entre les deux types, cette méthode renvoie False. Si strict, l'égalité est également interdite.

Exemples

Vérifier si un type est une sous-classe d'un autre :

>>> from qiskit.circuit.classical import types
>>> types.is_subtype(types.Uint(8), types.Uint(16))
True

Vérifier si un type est une sous-classe stricte d'un autre :

>>> types.is_subtype(types.Bool(), types.Bool())
True
>>> types.is_subtype(types.Bool(), types.Bool(), strict=True)
False

Paramètres

Type de retour

booléen

is_supertype

qiskit.circuit.classical.types.is_supertype(left, right, /, strict=False)

GitHub

La relation leftright\text{left} \ge \text{right} est-elle valable? S'il n'y a pas de relation d'ordre entre les deux types, cette méthode renvoie False. Si strict, l'égalité est également interdite.

Exemples

Vérifier si un type est une superclasse d'un autre :

>>> from qiskit.circuit.classical import types
>>> types.is_supertype(types.Uint(8), types.Uint(16))
False

Vérifier si un type est une superclasse stricte d'un autre :

>>> types.is_supertype(types.Bool(), types.Bool())
True
>>> types.is_supertype(types.Bool(), types.Bool(), strict=True)
False

Paramètres

Type de retour

booléen

greater

qiskit.circuit.classical.types.greater(left, right, /)

GitHub

Obtenir le plus grand des deux types, en supposant qu'il existe une relation d'ordre entre eux. Techniquement, il s'agit d'une version légèrement restreinte du concept de "rencontre" des deux types en ce sens que la valeur de retour doit être l'une des entrées. En pratique, dans le système de types, il n'existe pas de concept de type "somme", de sorte que la "rencontre" existe si et seulement s'il existe un ordre entre les deux types, et qu'elle est égale au plus grand des deux types.

Retours

Le plus grand des deux types.

Augmentations

TypeError - s'il n'y a pas de relation d'ordre entre les deux types.

Paramètres

Type de retour

Type

Exemples

Trouver le plus grand de deux Uint types :

>>> from qiskit.circuit.classical import types
>>> types.greater(types.Uint(8), types.Uint(16))
types.Uint(16)

Conversion entre types

Il est fréquent de devoir convertir des valeurs d'un type en valeurs d'un autre type. Les règles de distribution sont intégrées dans le module types module. Vous pouvez interroger les types de moulage à l'aide de cast_kind():

cast_kind

qiskit.circuit.classical.types.cast_kind(from_, to_, /)

GitHub

Déterminez le type de moulage nécessaire pour passer du type gauche au type droit.

Exemples

>>> from qiskit.circuit.classical import types
>>> types.cast_kind(types.Bool(), types.Bool())
<CastKind.EQUAL: 1>
>>> types.cast_kind(types.Uint(8), types.Bool())
<CastKind.IMPLICIT: 2>
>>> types.cast_kind(types.Bool(), types.Uint(8))
<CastKind.LOSSLESS: 3>
>>> types.cast_kind(types.Uint(16), types.Uint(8))
<CastKind.DANGEROUS: 4>

Paramètres

Type de retour

CastKind

Les valeurs de retour de cette fonction sont une énumération expliquant les types de conversion autorisés du type de gauche vers le type de droite.

Notez que les casts entre Float et Uint sont considérés comme dangereux dans les deux sens et doivent être effectués explicitement.

CastKind

class qiskit.circuit.classical.types.CastKind(*values)

GitHub

Bases : Enum

Valeur de retour indiquant le type de conversion possible d'un type à un autre.

Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.