Skip to main content
IBM Quantum Platform

Expresiones clásicas

qiskit.circuit.classical

Este módulo contiene una representación exploratoria de las operaciones en tiempo real sobre valores clásicos durante la ejecución del circuito.

Actualmente, sólo se admiten expresiones simples sobre bits y registros que den como resultado un valor booleano, y éstas sólo son válidas para su uso en las condiciones de QuantumCircuit.if_test() (IfElseOp) y QuantumCircuit.while_loop() (WhileLoopOp), y en el objetivo de QuantumCircuit.switch() (SwitchCaseOp).

Nota

Este es un módulo exploratorio, y aunque nos comprometeremos con la política estándar de depreciación de Qiskit, ten en cuenta que el módulo estará deliberadamente limitado en su alcance al principio, y las primeras versiones pueden no evolucionar limpiamente hacia la versión final. Es posible que varios componentes de este módulo sean sustituidos (sujetos a depreciaciones) en lugar de ser mejorados en una nueva forma.

El sistema de tipos y el árbol de expresiones se ampliarán con el tiempo, y es posible que los tipos permitidos de algunas operaciones deban cambiar entre versiones de Qiskit a medida que se desarrollen las capacidades de procesamiento clásicas.


Expresiones

qiskit.circuit.classical.expr

Todos los componentes necesarios para crear expresiones se exportan desde el espacio de nombres expr dentro de qiskit.circuit.classicalpor lo que puede elegir entre utilizar un acceso cualificado (por ejemplo expr.Value) o importar directamente los nombres que necesite y llamarlos sin el prefijo.

Existen dos vías para construir expresiones. Las clases que forman la representación del sistema de expresión tienen constructores que realizan una comprobación de tipo nula; depende de quien los llama asegurarse de que están construyendo objetos válidos. Para una interfaz más fácil de usar para la construcción directa, hay funciones de ayuda asociadas con la mayoría de las clases que hacen la validación de tipos y la inferencia. Se describen a continuación, en Construcción.

Representación

El sistema de expresión se basa en la representación arbórea. Todos los nodos del árbol son instancias finales (no heredables) de la clase base abstracta:

Expr

class qiskit.circuit.classical.expr.Expr

Bases: object

Clase base raíz de todos los nodos del árbol de expresión. El caso base nunca debe instanciarse directamente.

Esto no debe ser subclasificado por los usuarios; las subclases forman los datos internos de la representación de expresiones, y no tiene sentido añadir más fuera del código de la biblioteca Qiskit.

Todas las subclases deben encargarse de establecer su type atributo en su __init__, y no deben llamar al inicializador de la clase padre.

Estos objetos son mutables y no deben reutilizarse en una ubicación diferente sin una copia.

Todas las instancias de Expr definen un atributo booleano const , que indica si la expresión puede evaluarse en tiempo de compilación. La mayoría de las clases de expresiones deducen esto durante la construcción basándose en la constancia de sus operandos.

La base de las variables dinámicas es Varque puede ser una variable en tiempo real de tipo arbitrario o una envoltura alrededor de una variable de tipo Clbit o ClassicalRegister.

Variable

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

Bases: Expr

Una variable clásica.

Estas variables tienen dos formas: una variable de estilo nuevo que posee su ubicación de almacenamiento y tiene un nombre asociado; y una variable de estilo antiguo que envuelve una variable de tipo Clbit o ClassicalRegister que pertenece a un circuito contenedor. En general, la construcción de variables para su uso en programas debe utilizar Var.new() o QuantumCircuit.add_var().

Las variables son inmutables una vez creadas, por lo que pueden utilizarse como claves de diccionario.

name

El nombre de la variable. UUIDEsto debe existir si el atributo «backing» var es una variable de nuevo estilo, es decir, si se trata de una variable de nuevo estilo, y debe ser None una variable de estilo antiguo si se trata de una variable de estilo antiguo.

new

classmethod new(name, ty)

Genera una nueva variable con nombre que posee su propio almacenamiento de respaldo.

var

Una referencia al almacenamiento de datos de respaldo de la Var instancia. ClassicalRegisterAl migrar instancias de ClassicalRegister estilo Clbit antiguo a un Var, esto es exactamente el Clbit o el. Si la variable es una variable clásica de nuevo estilo (una que dispone de su propio espacio de almacenamiento, independiente del antiguo Clbit/ClassicalRegister modelo), este campo será un UUID que la identificará de forma única.

Del mismo modo, los literales utilizados en expresiones (como los enteros) deben elevarse a nodos Value con tipos asociados. A Value se considera siempre una expresión constante.

Valor

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

Bases: Expr

Un único valor escalar.

Las variables de estiramiento para su uso en expresiones de duración se representan mediante el nodo Stretch nodo.

Expandir

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

Bases: Expr

Una variable extensible.

En general, la construcción de variables extensibles para su uso en programas debe utilizar Stretch.new() o QuantumCircuit.add_stretch()

name

El nombre de la variable de estiramiento.

new

classmethod new(name)

Genera una nueva variable de estiramiento con nombre.

var

A UUID para identificar de forma única este tramo.

Las operaciones tradicionalmente asociadas a los operadores pre, post o infijos en programación se representan mediante los operadores Unary y Binary según corresponda. Cada uno de ellos toma un código de tipo de operación, que se exponen como enumeraciones dentro de cada clase como Unary.Op y Binary.Op respectivamente.

Unario

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

Bases: Expr

Una expresión unaria.

Parámetros

  • op - El opcode que describe la operación que se está realizando.
  • operando - El operando de la operación.
  • type - El tipo resuelto del resultado.
Op

class Op(*values)

Bases: Enum

Enumeración de los opcodes de las operaciones unarias.

La negación bit a bit BIT_NOT toma un único bit o un entero sin signo de anchura conocida, y devuelve un valor del mismo tipo.

La negación lógica LOGIC_NOT toma una entrada que está implícitamente coaccionada a un booleano, y devuelve un booleano.

La negación aritmética NEGATE toma como entrada un valor de tipo float o de duración y devuelve un valor del mismo tipo.

Binario

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

Bases: Expr

Una expresión binaria.

Parámetros

  • op - El opcode que describe la operación que se está realizando.
  • left - El operando de la izquierda.
  • right - El operando de la derecha.
  • type - El tipo resuelto del resultado.
Op

class Op(*values)

Bases: Enum

Enumeración de los opcodes de las operaciones binarias.

Las operaciones bit a bit BIT_AND, BIT_OR y BIT_XOR se aplican a dos operandos del mismo tipo, que debe ser un solo bit o un entero sin signo de anchura fija. El tipo resultante es el mismo que los dos tipos de entrada.

Las operaciones lógicas LOGIC_AND y LOGIC_OR primero coaccionan implícitamente sus argumentos a booleanos y luego aplican la operación lógica. El tipo resultante es siempre booleano.

Las relaciones matemáticas binarias EQUAL, NOT_EQUAL, LESS, LESS_EQUAL, GREATER y GREATER_EQUAL toman enteros sin signo (con un reparto implícito para que tengan la misma anchura), y devuelven un booleano.

Las operaciones de desplazamiento de bits SHIFT_LEFT y SHIFT_RIGHT pueden tomar tipos de contenedores tipo bit (por ejemplo, enteros sin signo) como operando izquierdo, y cualquier tipo entero como operando derecho. En todos los casos, la anchura de bits de salida es la misma que la de entrada, y los ceros rellenan los espacios "expuestos".

Los operadores aritméticos ADD binarios, SUB, MUL, y DIV pueden aplicarse a dos números de tipo float o a dos enteros sin signo, que deben tener la misma longitud mediante una conversión de tipo durante su definición. Los DIV operadores ADD, SUB, y pueden aplicarse a dos duraciones para obtener otra duración, o un número flotante en el caso de DIV. El MUL operador también se puede aplicar a una duración y a un tipo numérico, lo que da como resultado otra duración. Por último, el DIV operador se puede utilizar para dividir una duración entre un valor numérico, lo que da como resultado una duración.

Los tipos tipo bit (enteros sin signo) pueden ser indexados por tipos enteros, representados por Index. El resultado es un único bit. La expresión resultante tiene una posición de memoria asociada (y por lo tanto se puede utilizar como un lvalue para Storeetc.) si el objetivo también es un lvalue.

Índice

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

Bases: Expr

Una expresión de indexación.

Parámetros

  • target - El objeto indexado.
  • index - La expresión que realiza la indexación.
  • type - El tipo resuelto del resultado.

Al construir expresiones, hay que asegurarse de que los tipos son válidos para la operación. Los intentos de construir expresiones con tipos no válidos provocarán un error regular Python TypeError.

Las expresiones de este sistema están definidas para actuar sólo sobre determinados conjuntos de tipos. Sin embargo, los valores se pueden convertir a un supertipo adecuado para satisfacer los requisitos de tipado. En estos casos, se utiliza un nodo del árbol de expresión para representar la promoción. En todos los casos en que las operaciones indiquen que "moldean implícitamente" o "coaccionan" sus argumentos, el árbol de expresión debe tener este nodo que representa la conversión.

Convertir temporalmente

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

Bases: Expr

Un reparto de un tipo a otro, implícito en el uso de una expresión en un contexto diferente.

Construcción

Construir directamente la representación en árbol es verboso y es fácil equivocarse al teclear. En muchos casos, gran parte de la tipificación puede inferirse, los valores escalares pueden promoverse automáticamente a Value instancias, y cualquier promoción necesaria puede resolverse en nodos Cast nodos.

Las funciones y métodos descritos en esta sección son una forma más fácil de construir el árbol de expresiones, al tiempo que se mantienen cerca de la representación interna. Todas estas funciones convertirán automáticamente los valores escalares válidos de Python en los valores correspondientes de Var o Value y resolverán cualquier cambio implícito en su nombre. Si desea utilizar directamente algún valor escalar como nodo Expr nodo, puede hacerlo manualmente lift() manualmente.

lift

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

GitHub

Eleva el Python dado value a un Value o Var.

Si se indica explícitamente type , el texto de salida lo reflejará.

Ejemplos

Elevación de objetos de circuito simples a Var instancias:

>>> 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))

El tipo del valor de retorno puede modificarse si el valor proporcionado puede interpretarse sin pérdida de información como el tipo especificado (utiliza cast() para realizar un conjunto completo de operaciones de conversión, incluidas las que implican pérdida de información):

>>> 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))

Parámetros

Tipo de retorno

Expr

Normalmente, para crear instancias con memoria Var utilizando el método QuantumCircuit.add_var() para declararlas en algún contexto de circuito, ya que un método QuantumCircuit no aceptará un Expr que contenga variables que no estén ya declaradas en él, ya que necesita saber cómo asignar el almacenamiento y cómo se inicializará la variable. Sin embargo, si desea hacerlo manualmente, debe utilizar la llamada de bajo nivel Var.new() para generar de forma segura una variable con nombre para su uso.

Puede especificar manualmente las conversiones en los casos en que se permite la conversión de forma explícita, pero puede tener pérdidas (como la conversión de una precisión mayor Uint a una de menor precisión).

cast

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

GitHub

Crea una conversión explícita del valor dado al tipo dado.

Ejemplos

Añade un nodo de conversión explícita que convierte explícitamente un tipo de mayor precisión en uno de menor precisión:

>>> 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)

Parámetros

Tipo de retorno

Expr

Existen funciones constructoras de ayuda para cada una de las operaciones unarias.

bit_not

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

GitHub

Crea un nodo de expresión bitwise 'not' a partir del valor dado, resolviendo cualquier conversión implícita y elevando el valor a un nodo Value si es necesario.

Ejemplos

Negación bit a bit 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))

Parámetros

operand (Any)

Tipo de retorno

Expr

logic_not

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

GitHub

Crea un nodo de expresión lógica 'not' a partir del valor dado, resolviendo cualquier conversión implícita y elevando el valor a un nodo Value si es necesario.

Ejemplos

Negación lógica 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())

Parámetros

operand (Any)

Tipo de retorno

Expr

negate

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

GitHub

Niega un nodo de expresión a partir del valor dado, resolviendo cualquier conversión implícita y elevando el valor a un Value nodo si es necesario.

Ejemplos

Negación de un número de coma flotante:

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

Negación de una duración:

>>> 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())

Parámetros

operand (Any)

Tipo de retorno

Expr

Del mismo modo, las operaciones y relaciones binarias tienen definidas funciones de ayuda.

bit_and

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

GitHub

Crea un nodo de expresión 'and' bitwise a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Bitwise 'and' de un registro clásico y un literal entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

bit_or

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

GitHub

Crea un nodo de expresión 'or' bitwise a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Bitwise 'or' de un registro clásico y un literal entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

bit_xor

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

GitHub

Crea un nodo de expresión 'exclusive or' bitwise a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Bitwise 'exclusive or' de un registro clásico y un literal entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

logic_and

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

GitHub

Crea un nodo de expresión lógica 'y' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

La "y" lógica de dos bits clásicos:

>>> 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())

Parámetros

Tipo de retorno

Expr

logic_or

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

GitHub

Crea un nodo de expresión lógica "o" a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

O lógico de dos bits clásicos

>>> 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())

Parámetros

Tipo de retorno

Expr

equal

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

GitHub

Crea un nodo de expresión 'igual' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Igualdad entre un registro clásico y un entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

not_equal

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

GitHub

Crea un nodo de expresión 'no igual' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Desigualdad entre un registro clásico y un entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

less

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

GitHub

Crea un nodo de expresión 'menor que' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Consulta si un registro clásico es menor que un entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

less_equal

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

GitHub

Crea un nodo de expresión 'menor o igual que' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Consulta si un registro clásico es menor o igual que otro:

>>> 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))

Parámetros

Tipo de retorno

Expr

greater

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

GitHub

Crea un nodo de expresión 'mayor que' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Consulta si un registro clásico es mayor que un entero:

>>> 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))

Parámetros

Tipo de retorno

Expr

greater_equal

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

GitHub

Crea un nodo de expresión 'mayor o igual que' a partir del valor dado, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Consulta si un registro clásico es mayor o igual que otro:

>>> 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))

Parámetros

Tipo de retorno

Expr

shift_left

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

GitHub

Crea un nodo de expresión 'bitshift left' a partir de los dos valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Si se da type , el operando left será coaccionado a él (si es posible).

Ejemplos

Desplaza el valor de una variable independiente hacia la izquierda en una cantidad determinada:

>>> 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))

Desplaza un literal entero una cantidad variable, coaccionando el tipo del literal:

>>> 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))

Parámetros

Tipo de retorno

Expr

shift_right

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

GitHub

Crea un nodo de expresión 'bitshift right' a partir de los valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Si se da type , el operando left será coaccionado a él (si es posible).

Ejemplos

Desplazar el valor de un registro clásico hacia la derecha en una cantidad determinada:

>>> 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))

Parámetros

Tipo de retorno

Expr

add

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

GitHub

Crea un nodo de expresión de suma a partir de los valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Suma de dos números en coma flotante:

>>> 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())

Adición de dos duraciones:

>>> 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())

Parámetros

Tipo de retorno

Expr

sub

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

GitHub

Crea un nodo de expresión de sustracción a partir de los valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Ejemplos

Resta de dos números en coma flotante:

>>> 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())

Resta de dos duraciones:

>>> 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())

Parámetros

Tipo de retorno

Expr

mul

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

GitHub

Crea un nodo de expresión de multiplicación a partir de los valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Se puede utilizar para multiplicar operandos numéricos del mismo tipo, o para multiplicar un operando de duración por un operando numérico.

Ejemplos

Multiplicación de dos números de coma flotante:

>>> 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())

Multiplicación de una duración por un flotante:

>>> 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())

Parámetros

Tipo de retorno

Expr

div

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

GitHub

Crea un nodo de expresión de división a partir de los valores dados, resolviendo cualquier conversión implícita y elevando los valores a nodos Value si es necesario.

Se puede utilizar para dividir operandos numéricos del mismo tipo, para dividir un Duration operando por un operando numérico, o para dividir dos Duration operandos que devuelven una expresión de tipo Float.

Ejemplos

División de dos números de coma flotante:

>>> 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())

División de dos duraciones:

>>> 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())

División de una duración por un flotante:

>>> 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())

Parámetros

Tipo de retorno

Expr

Puede indexar en enteros sin signo y similares a bits utilizando otro entero sin signo de cualquier anchura. Esto incluye en las operaciones de almacenamiento, si el destino del índice es escribible.

index

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

GitHub

Indexa en target con el entero dado index, levantando los valores en Value nodos si es necesario.

Puede utilizarse como destino de un Storesi el propio target es un valor l.

Ejemplos

Índice en un registro clásico con un literal:

>>> 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())

Parámetros

Tipo de retorno

Expr

El método heredado de Qiskit para especificar condiciones de igualdad para su uso en condicionales consiste en utilizar una bicategoría de a Clbit o ClassicalRegister y un entero. Esto representa una condición de igualdad exacta, y no hay forma de especificar ninguna otra relación. La función de ayuda lift_legacy_condition() convierte este formato heredado en la nueva sintaxis de expresión.

lift_legacy_condition

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

GitHub

Convertir una condición de igualdad de dos tuplas heredada en una de nuevo estilo Expr.

Parámetros

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

Tipo de retorno

Expr

Trabajar con el árbol de expresiones

Un consumidor típico del árbol de expresiones quiere recorrer recursivamente el árbol, potencialmente con estado, actuando en cada nodo de forma diferente dependiendo de su tipo. Se trata, naturalmente, de un problema de doble envío: la lógica de "lo que hay que hacer" es probablemente estatal y los usuarios deberían ser libres de definir sus propias operaciones, pero cada nodo define "sobre qué se está actuando". Permitimos este doble envío proporcionando una clase visitante base para el árbol de expresión.

ExprVisitor

class qiskit.circuit.classical.expr.ExprVisitor

GitHub

Bases: Generic[_T_co]

Clase base para los visitantes del Expr árbol. Las subclases deben anular cualquiera de los métodos de visit_* que sean capaces de manejar, y deben organizarse de tal manera que los métodos inexistentes nunca sean llamados.

visit_binary

visit_binary(node, /)

GitHub

Parámetros

node (Binary)

Tipo de retorno

_T_co

visit_cast

visit_cast(node, /)

GitHub

Parámetros

node (Cast)

Tipo de retorno

_T_co

visit_generic

visit_generic(node, /)

GitHub

Parámetros

node (Expr)

Tipo de retorno

_T_co

visit_index

visit_index(node, /)

GitHub

Parámetros

node (Index)

Tipo de retorno

_T_co

visit_stretch

visit_stretch(node, /)

GitHub

Parámetros

node (Stretch)

Tipo de retorno

_T_co

visit_unary

visit_unary(node, /)

GitHub

Parámetros

node (Unary)

Tipo de retorno

_T_co

visit_value

visit_value(node, /)

GitHub

Parámetros

node (Value)

Tipo de retorno

_T_co

visit_var

visit_var(node, /)

GitHub

Parámetros

node (Var)

Tipo de retorno

_T_co

Los consumidores del árbol de expresiones deben subclasificar el visitante y anular los métodos de visit_* que deseen utilizar. Cualquier método no sobreescrito llamará a visit_generic()que, a menos que se sobreescriba, lanzará un mensaje RuntimeError para asegurarse de que es consciente de si se han añadido nuevos nodos al árbol de expresiones que aún no está manejando.

Para la comodidad de los visitantes simples que sólo necesitan inspeccionar las variables de una expresión y no la estructura general, se proporciona el método iterador iter_vars() .

iter_vars

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

GitHub

Obtiene un iterador sobre los Var referenciados a cualquier nivel en el directorio Expr.

Ejemplos

Imprime el nombre de cada ClassicalRegister encontrado:

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)
Consulte también

iter_identifiers()

Obtiene un iterador sobre todos los nodos identificadores de la expresión, incluyendo ambos Var y Stretch nodos.

Parámetros

node (Expr)

Tipo de retorno

Iterador[* Var* ]

Para iterar sobre todas las variables, incluidas las variables estiradas, se proporciona el método iterator iter_identifiers() .

iter_identifiers

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

GitHub

Obtiene un iterador sobre Var y Stretch referenciados a cualquier nivel en el directorio Expr.

Ejemplos

Imprime el nombre de cada ClassicalRegister encontrado:

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)
Consulte también

iter_vars()

Obtiene un iterador sólo sobre los Var nodos de la expresión.

Parámetros

node (Expr)

Tipo de retorno

Iterator[* Var* | Stretch ]

Dos expresiones pueden compararse para una igualdad estructural directa utilizando el operador incorporado Python == . En general, sin embargo, uno podría querer comparar dos expresiones ligeramente más semánticas, permitiendo que los Var estén vinculados a diferentes descripciones de ubicación de memoria entre dos circuitos diferentes. En este caso, se puede utilizar structurally_equivalent() con dos funciones "clave" adecuadas para realizar la comparación.

structurally_equivalent

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

GitHub

¿Tienen estas dos expresiones exactamente la misma estructura de árbol, hasta alguna función clave para los Var objetos?

En otras palabras, ¿son estas dos expresiones exactamente los mismos árboles, excepto que comparamos los campos Var.var campos llamando a la función *_var_key apropiada en ellos, y comparando la salida para la igualdad. Esta función no permite "equivalencias" semánticas tales como afirmar que a == b es equivalente a b == a; el orden de evaluación de los operandos podría, en general, hacer que tal afirmación fuera falsa (considere hipotéticas funciones extern que accedan al estado global).

No hay requisitos para las funciones clave, salvo que sus salidas deben tener métodos generales __eq__ . Si una función clave devuelve None, la variable se utilizará literalmente en su lugar.

Parámetros

  • left (Expr) – uno de los Expr nodos.
  • right (Expr) – el otro Expr nodo.
  • left_var_key (Callable[[Any], Any] | None) – un callable cuya salida debe utilizarse al comparar Var.var atributos. Si este argumento es None o su salida es None para una variable dada en left, la variable se utilizará textualmente.
  • right_var_key (Callable[[Any], Any] | None) – igual que left_var_key, pero utilizado en las variables de right en su lugar.

Tipo de retorno

bool

Ejemplos

Comparación de dos expresiones por equivalencia estructural, sin reasignación de las variables. Son diferentes porque las distintas Clbit instancias se comparan de forma diferente:

>>> 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

Comparación de las mismas dos expresiones, pero esta vez utilizando funciones de mapeo que asocian los bits con índices simples:

>>> 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

Algunas expresiones tienen posiciones de memoria asociadas, y otras pueden ser puramente temporales. Puede utilizar is_lvalue() para determinar si una expresión tiene una posición de memoria asociada.

is_lvalue

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

GitHub

Devuelve si esta expresión se puede utilizar en posiciones de valor l, es decir, si tiene una ubicación bien definida en la memoria, como una que podría ser escribible.

Que sea un valor l es necesario, pero no suficiente, para que esta ubicación sea escribible; es posible que un objeto de mayor tamaño que contenga esta ubicación de memoria no permita la escritura desde el ámbito que intenta escribir en ella. Sin embargo, esto sería una propiedad de acceso del programa contenedor, y no una propiedad inherente al sistema de expresiones.

Una expresión constante nunca es un lvalue.

Ejemplos

Los valores literales nunca son valores l; no hay ninguna posición de memoria asociada a (por ejemplo) la constante 1:

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

Var son siempre valores l, porque siempre tienen alguna posición de memoria asociada:

>>> 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

Actualmente no existen operaciones unarias o binarias sobre variables que puedan producir una expresión de valor l, pero es probable que en el futuro se añada algún tipo de operación de "indexación", que podría producir valores 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

Parámetros

node (Expr)

Tipo de retorno

bool


Creación de tipos

qiskit.circuit.classical.types

Representación

El sistema de tipos del árbol de expresión se expone a través de este módulo. Esto está intrínsecamente ligado al sistema de expresiones del módulo expr ya que la mayoría de las expresiones sólo pueden entenderse en el contexto de los tipos sobre los que actúan.

Todos los tipos heredan de una clase base abstracta:

Tipo

class qiskit.circuit.classical.types.Type

Bases: object

Clase base raíz de todos los nodos del árbol de tipos. El caso base nunca debe instanciarse directamente.

Esto no debe ser subclasificado por los usuarios; las subclases forman los datos internos de la representación de expresiones, y no tiene sentido añadir más fuera del código de la biblioteca Qiskit.

Los tipos deben considerarse objetos inmutables, y no debes mutarlos. Está permitido reutilizar un Type que se toma de otro objeto sin copiarlo, y generalmente éste será el mejor enfoque para el rendimiento. Type están diseñados para ser pequeñas cantidades de datos, y es mejor apuntar a la misma instancia de los datos siempre que sea posible en lugar de heap-asignar una nueva versión de la misma cosa. Siempre que sea posible, los constructores de clase devolverán instancias singleton para facilitar esto.

La dirección Bool tipo representa Clbit y los literales True y False, el tipo Uint tipo representa ClassicalRegister y Python enteros, el tipo Float representa flotantes Python y el tipo Duration representa una duración para su uso en operaciones de circuito con temporización.

Bool

class qiskit.circuit.classical.types.Bool

Bases: Type

El tipo booleano. Tiene exactamente dos valores: True y False.

Uint

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

Bases: Type

Un entero sin signo de ancho de bit fijo.

Flotante

class qiskit.circuit.classical.types.Float

Bases: Type

Un número de coma flotante de doble precisión IEEE-754.

En el futuro, también podrá utilizarse para representar otros flotadores de anchura fija.

Duración

class qiskit.circuit.classical.types.Duration

Bases: Type

Un periodo de tiempo, posiblemente negativo.

Trabajar con tipos

Existen algunas funciones adicionales sobre estos tipos documentadas en las secciones siguientes. Se espera que sólo se utilicen para manipular el árbol de expresiones; los usuarios que construyan expresiones utilizando la interfaz de construcción orientada al usuario no necesitarán utilizarlas.

Ordenación parcial de tipos

El sistema de tipos está equipado con un ordenamiento parcial, donde a<ba < b se interpreta como " aa es un subtipo estricto de bb ". Nótese que la ordenación parcial es un subconjunto del grafo dirigido que describe las operaciones explícitas de reparto entre tipos permitidas. La ordenación parcial define cuándo un tipo puede interpretarse directamente sin pérdidas como otro.

La interfaz de bajo nivel para consultar la relación de subtipado es la función order() función

order

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

GitHub

Obtiene la relación de ordenación entre los dos tipos como un valor de enumeración.

Ejemplos

Compara dos Uint tipos de anchura diferente:

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

Compara dos tipos que no tienen orden entre ellos:

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

Parámetros

Tipo de retorno

Pedidos

El valor de retorno es una enumeración Ordering que describe qué relación de subtipado existe entre los dos tipos, si es que existe alguna.

Ordenación

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

GitHub

Bases: Enum

Enumeración que enumera las relaciones posibles entre dos tipos. Los tipos sólo tienen un orden parcial, por lo que es posible que dos tipos no tengan ninguna relación de subtipado.

Tenga en cuenta que la relación sub/supertipado no es lo mismo que el hecho de que un tipo se pueda convertir explícitamente de uno a otro.

Algunos métodos de ayuda se definen entonces en términos de esta primitiva de bajo nivel order() de bajo nivel:

is_subtype

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

GitHub

¿Se mantiene la relación leftright\text{left} \le \text{right}? Si no existe ninguna relación de ordenación entre los dos tipos, se devuelve False. Si strict, entonces la igualdad también está prohibida.

Ejemplos

Comprueba si un tipo es una subclase de otro:

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

Comprueba si un tipo es una subclase estricta de otro:

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

Parámetros

Tipo de retorno

bool

is_supertype

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

GitHub

¿Se mantiene la relación leftright\text{left} \ge \text{right}? Si no existe ninguna relación de ordenación entre los dos tipos, se devuelve False. Si strict, entonces la igualdad también está prohibida.

Ejemplos

Comprueba si un tipo es superclase de otro:

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

Comprueba si un tipo es una superclase estricta de otro:

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

Parámetros

Tipo de retorno

bool

greater

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

GitHub

Obtiene el mayor de los dos tipos, suponiendo que exista una relación de ordenación entre ellos. Técnicamente, se trata de una versión ligeramente restringida del concepto de "encuentro" de los dos tipos, en el sentido de que el valor de retorno debe ser una de las entradas. En la práctica, en el sistema de tipos no existe el concepto de tipo "suma", por lo que el "encuentro" existe si y sólo si existe un ordenamiento entre los dos tipos, y es igual al mayor de los dos tipos.

Devuelve

El mayor de los dos tipos.

Eleva

TypeError - si no existe ninguna relación de ordenación entre los dos tipos.

Parámetros

Tipo de retorno

Tipo

Ejemplos

Hallar el mayor de dos Uint tipos:

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

Conversión entre tipos

Es frecuente tener que convertir valores de un tipo a otro. Las reglas de reparto están integradas en el módulo types módulo. Puede consultar los tipos de fundición utilizando cast_kind():

cast_kind

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

GitHub

Determine el tipo de reparto necesario para pasar del tipo izquierdo al tipo derecho.

Ejemplos

>>> 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>

Parámetros

Tipo de retorno

CastKind

Los valores de retorno de esta función son una enumeración que explica los tipos de conversión permitidos del tipo izquierdo al tipo derecho.

Tenga en cuenta que los calcos entre Float y Uint se consideran peligrosas en cualquier dirección, y deben hacerse explícitamente.

CastKind

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

GitHub

Bases: Enum

Un valor de retorno que indica el tipo de conversión que puede producirse de un tipo a otro.

¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.