# Classical expressions

`qiskit.circuit.classical`

This module contains an exploratory representation of real-time operations on classical values during circuit execution.

Currently, only simple expressions on bits and registers that result in a Boolean value are supported, and these are only valid for use in the conditions of `QuantumCircuit.if_test()`

(`IfElseOp`

) and `QuantumCircuit.while_loop()`

(`WhileLoopOp`

), and in the target of `QuantumCircuit.switch()`

(`SwitchCaseOp`

).

This is an exploratory module, and while we will commit to the standard Qiskit deprecation policy within it, please be aware that the module will be deliberately limited in scope at the start, and early versions may not evolve cleanly into the final version. It is possible that various components of this module will be replaced (subject to deprecations) instead of improved into a new form.

The type system and expression tree will be expanded over time, and it is possible that the allowed types of some operations may need to change between versions of Qiskit as the classical processing capabilities develop.

## Expressions

`qiskit.circuit.classical.expr`

The necessary components for building expressions are all exported from the `expr`

namespace within `qiskit.circuit.classical`

, so you can choose whether to use qualified access (for example `expr.Value`

) or import the names you need directly and call them without the prefix.

There are two pathways for constructing expressions. The classes that form the representation of the expression system have constructors that perform zero type checking; it is up to the caller to ensure that they are building valid objects. For a more user-friendly interface to direct construction, there are helper functions associated with most of the classes that do type validation and inference. These are described below, in Construction.

### Representation

The expression system is based on tree representation. All nodes in the tree are final (uninheritable) instances of the abstract base class:

#### Expr

*class *`qiskit.circuit.classical.expr.Expr`

Root base class of all nodes in the expression tree. The base case should never be instantiated directly.

This must not be subclassed by users; subclasses form the internal data of the representation of expressions, and it does not make sense to add more outside of Qiskit library code.

All subclasses are responsible for setting their `type`

attribute in their `__init__`

, and should not call the parent initialiser.

These objects are mutable and should not be reused in a different location without a copy.

The base for dynamic variables is the `Var`

, which can be either an arbitrarily typed real-time variable, or a wrapper around a `Clbit`

or `ClassicalRegister`

.

#### Var

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

A classical variable.

These variables take two forms: a new-style variable that owns its storage location and has an associated name; and an old-style variable that wraps a `Clbit`

or `ClassicalRegister`

instance that is owned by some containing circuit. In general, construction of variables for use in programs should use `Var.new()`

or `QuantumCircuit.add_var()`

.

Variables are immutable after construction, so they can be used as dictionary keys.

##### name

Type: `str | None`

The name of the variable. This is required to exist if the backing `var`

attribute is a `UUID`

(opens in a new tab), i.e. if it is a new-style variable, and must be `None`

if it is an old-style variable.

##### new

*classmethod *`new(name, type)`

Generate a new named variable that owns its own backing storage.

**Return type**

##### var

Type: `qiskit.circuit.Clbit | qiskit.circuit.ClassicalRegister | uuid.UUID`

A reference to the backing data storage of the `Var`

instance. When lifting old-style `Clbit`

or `ClassicalRegister`

instances into a `Var`

, this is exactly the `Clbit`

or `ClassicalRegister`

. If the variable is a new-style classical variable (one that owns its own storage separate to the old `Clbit`

/`ClassicalRegister`

model), this field will be a `UUID`

(opens in a new tab) to uniquely identify it.

Similarly, literals used in expressions (such as integers) should be lifted to `Value`

nodes with associated types.

#### Value

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

A single scalar value.

The operations traditionally associated with pre-, post- or infix operators in programming are represented by the `Unary`

and `Binary`

nodes as appropriate. These each take an operation type code, which are exposed as enumerations inside each class as `Unary.Op`

and `Binary.Op`

respectively.

#### Unary

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

A unary expression.

**Parameters**

**op**(*Unary.Op*) – The opcode describing which operation is being done.**operand**(*Expr*) – The operand of the operation.**type**(*Type*) – The resolved type of the result.

##### Op

*class *`Op(value)`

Enumeration of the opcodes for unary operations.

The bitwise negation `BIT_NOT`

takes a single bit or an unsigned integer of known width, and returns a value of the same type.

The logical negation `LOGIC_NOT`

takes an input that is implicitly coerced to a Boolean, and returns a Boolean.

###### BIT_NOT

Default value: `1`

Bitwise negation. `~operand`

.

###### LOGIC_NOT

Default value: `2`

Logical negation. `!operand`

.

#### Binary

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

A binary expression.

**Parameters**

**op**(*Binary.Op*) – The opcode describing which operation is being done.**left**(*Expr*) – The left-hand operand.**right**(*Expr*) – The right-hand operand.**type**(*Type*) – The resolved type of the result.

##### Op

*class *`Op(value)`

Enumeration of the opcodes for binary operations.

The bitwise operations `BIT_AND`

, `BIT_OR`

and `BIT_XOR`

apply to two operands of the same type, which must be a single bit or an unsigned integer of fixed width. The resultant type is the same as the two input types.

The logical operations `LOGIC_AND`

and `LOGIC_OR`

first implicitly coerce their arguments to Booleans, and then apply the logical operation. The resultant type is always Boolean.

The binary mathematical relations `EQUAL`

, `NOT_EQUAL`

, `LESS`

, `LESS_EQUAL`

, `GREATER`

and `GREATER_EQUAL`

take unsigned integers (with an implicit cast to make them the same width), and return a Boolean.

The bitshift operations `SHIFT_LEFT`

and `SHIFT_RIGHT`

can take bit-like container types (e.g. unsigned integers) as the left operand, and any integer type as the right-hand operand. In all cases, the output bit width is the same as the input, and zeros fill in the “exposed” spaces.

###### BIT_AND

Default value: `1`

Bitwise “and”. `lhs & rhs`

.

###### BIT_OR

Default value: `2`

Bitwise “or”. `lhs | rhs`

.

###### BIT_XOR

Default value: `3`

Bitwise “exclusive or”. `lhs ^ rhs`

.

###### LOGIC_AND

Default value: `4`

Logical “and”. `lhs && rhs`

.

###### LOGIC_OR

Default value: `5`

Logical “or”. `lhs || rhs`

.

###### EQUAL

Default value: `6`

Numeric equality. `lhs == rhs`

.

###### NOT_EQUAL

Default value: `7`

Numeric inequality. `lhs != rhs`

.

###### LESS

Default value: `8`

Numeric less than. `lhs < rhs`

.

###### LESS_EQUAL

Default value: `9`

Numeric less than or equal to. `lhs <= rhs`

###### GREATER

Default value: `10`

Numeric greater than. `lhs > rhs`

.

###### GREATER_EQUAL

Default value: `11`

Numeric greater than or equal to. `lhs >= rhs`

.

###### SHIFT_LEFT

Default value: `12`

Zero-padding bitshift to the left. `lhs << rhs`

.

###### SHIFT_RIGHT

Default value: `13`

Zero-padding bitshift to the right. `lhs >> rhs`

.

Bit-like types (unsigned integers) can be indexed by integer types, represented by `Index`

. The result is a single bit. The resulting expression has an associated memory location (and so can be used as an lvalue for `Store`

, etc) if the target is also an lvalue.

#### Index

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

An indexing expression.

**Parameters**

When constructing expressions, one must ensure that the types are valid for the operation. Attempts to construct expressions with invalid types will raise a regular Python `TypeError`

.

Expressions in this system are defined to act only on certain sets of types. However, values may be cast to a suitable supertype in order to satisfy the typing requirements. In these cases, a node in the expression tree is used to represent the promotion. In all cases where operations note that they “implicitly cast” or “coerce” their arguments, the expression tree must have this node representing the conversion.

#### Cast

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

A cast from one type to another, implied by the use of an expression in a different context.

### Construction

Constructing the tree representation directly is verbose and easy to make a mistake with the typing. In many cases, much of the typing can be inferred, scalar values can automatically be promoted to `Value`

instances, and any required promotions can be resolved into suitable `Cast`

nodes.

The functions and methods described in this section are a more user-friendly way to build the expression tree, while staying close to the internal representation. All these functions will automatically lift valid Python scalar values into corresponding `Var`

or `Value`

objects, and will resolve any required implicit casts on your behalf. If you want to directly use some scalar value as an `Expr`

node, you can manually `lift()`

it yourself.

#### lift

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

Lift the given Python `value`

to a `Value`

or `Var`

.

If an explicit `type`

is given, the typing in the output will reflect that.

**Examples**

Lifting simple circuit objects to be `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))
```

The type of the return value can be influenced, if the given value could be interpreted losslessly as the given type (use `cast()`

to perform a full set of casting operations, include lossy ones):

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

**Return type**

Typically you should create memory-owning `Var`

instances by using the `QuantumCircuit.add_var()`

method to declare them in some circuit context, since a `QuantumCircuit`

will not accept an `Expr`

that contains variables that are not already declared in it, since it needs to know how to allocate the storage and how the variable will be initialized. However, should you want to do this manually, you should use the low-level `Var.new()`

call to safely generate a named variable for usage.

You can manually specify casts in cases where the cast is allowed in explicit form, but may be lossy (such as the cast of a higher precision `Uint`

to a lower precision one).

#### cast

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

Create an explicit cast from the given value to the given type.

**Examples**

Add an explicit cast node that explicitly casts a higher precision type to a lower precision one:

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

**Return type**

There are helper constructor functions for each of the unary operations.

#### bit_not

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

Create a bitwise ‘not’ expression node from the given value, resolving any implicit casts and lifting the value into a `Value`

node if required.

**Examples**

Bitwise negation of 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))
```

**Return type**

#### logic_not

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

Create a logical ‘not’ expression node from the given value, resolving any implicit casts and lifting the value into a `Value`

node if required.

**Examples**

Logical negation of 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())
```

**Return type**

Similarly, the binary operations and relations have helper functions defined.

#### bit_and

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

Create a bitwise ‘and’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Bitwise ‘and’ of a classical register and an integer literal:

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

**Return type**

#### bit_or

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

Create a bitwise ‘or’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Bitwise ‘or’ of a classical register and an integer literal:

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

**Return type**

#### bit_xor

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

Create a bitwise ‘exclusive or’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Bitwise ‘exclusive or’ of a classical register and an integer literal:

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

**Return type**

#### logic_and

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

Create a logical ‘and’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Logical ‘and’ of two classical bits:

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

**Return type**

#### logic_or

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

Create a logical ‘or’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Logical ‘or’ of two classical bits

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

**Return type**

#### equal

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

Create an ‘equal’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Equality between a classical register and an integer:

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

**Return type**

#### not_equal

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

Create a ‘not equal’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Inequality between a classical register and an integer:

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

**Return type**

#### less

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

Create a ‘less than’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Query if a classical register is less than an integer:

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

**Return type**

#### less_equal

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

Create a ‘less than or equal to’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Query if a classical register is less than or equal to another:

```
>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.less(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))
```

**Return type**

#### greater

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

Create a ‘greater than’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Query if a classical register is greater than an integer:

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

**Return type**

#### greater_equal

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

Create a ‘greater than or equal to’ expression node from the given value, resolving any implicit casts and lifting the values into `Value`

nodes if required.

**Examples**

Query if a classical register is greater than or equal to another:

```
>>> from qiskit.circuit import ClassicalRegister
>>> from qiskit.circuit.classical import expr
>>> expr.less(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))
```

**Return type**

#### shift_left

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

Create a ‘bitshift left’ expression node from the given two values, resolving any implicit casts and lifting the values into `Value`

nodes if required.

If `type`

is given, the `left`

operand will be coerced to it (if possible).

**Examples**

Shift the value of a standalone variable left by some amount:

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

Shift an integer literal by a variable amount, coercing the type of the 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))
```

**Return type**

#### shift_right

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

Create a ‘bitshift right’ expression node from the given values, resolving any implicit casts and lifting the values into `Value`

nodes if required.

If `type`

is given, the `left`

operand will be coerced to it (if possible).

**Examples**

Shift the value of a classical register right by some amount:

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

**Return type**

You can index into unsigned integers and bit-likes using another unsigned integer of any width. This includes in storing operations, if the target of the index is writeable.

#### index

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

Index into the `target`

with the given integer `index`

, lifting the values into `Value`

nodes if required.

This can be used as the target of a `Store`

, if the `target`

is itself an lvalue.

**Examples**

Index into a classical register with a 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())
```

**Return type**

Qiskit’s legacy method for specifying equality conditions for use in conditionals is to use a two-tuple of a `Clbit`

or `ClassicalRegister`

and an integer. This represents an exact equality condition, and there are no ways to specify any other relations. The helper function `lift_legacy_condition()`

converts this legacy format into the new expression syntax.

#### lift_legacy_condition

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

Lift a legacy two-tuple equality condition into a new-style `Expr`

.

**Examples**

Taking an old-style conditional instruction and getting an `Expr`

from its condition:

```
from qiskit.circuit import ClassicalRegister
from qiskit.circuit.library import HGate
from qiskit.circuit.classical import expr
cr = ClassicalRegister(2)
instr = HGate().c_if(cr, 3)
lifted = expr.lift_legacy_condition(instr.condition)
```

**Return type**

### Working with the expression tree

A typical consumer of the expression tree wants to recursively walk through the tree, potentially statefully, acting on each node differently depending on its type. This is naturally a double-dispatch problem; the logic of ‘what is to be done’ is likely stateful and users should be free to define their own operations, yet each node defines ‘what is being acted on’. We enable this double dispatch by providing a base visitor class for the expression tree.

#### ExprVisitor

*class *`qiskit.circuit.classical.expr.ExprVisitor`

Base class for visitors to the `Expr`

tree. Subclasses should override whichever of the `visit_*`

methods that they are able to handle, and should be organised such that non-existent methods will never be called.

##### visit_binary

##### visit_cast

##### visit_generic

##### visit_index

##### visit_unary

##### visit_value

##### visit_var

Consumers of the expression tree should subclass the visitor, and override the `visit_*`

methods that they wish to handle. Any non-overridden methods will call `visit_generic()`

, which unless overridden will raise a `RuntimeError`

to ensure that you are aware if new nodes have been added to the expression tree that you are not yet handling.

For the convenience of simple visitors that only need to inspect the variables in an expression and not the general structure, the iterator method `iter_vars()`

is provided.

#### iter_vars

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

Get an iterator over the `Var`

nodes referenced at any level in the given `Expr`

.

**Examples**

Print out the name of each `ClassicalRegister`

encountered:

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

**Return type**

Two expressions can be compared for direct structural equality by using the built-in Python `==`

operator. In general, though, one might want to compare two expressions slightly more semantically, allowing that the `Var`

nodes inside them are bound to different memory-location descriptions between two different circuits. In this case, one can use `structurally_equivalent()`

with two suitable “key” functions to do the comparison.

#### structurally_equivalent

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

Do these two expressions have exactly the same tree structure, up to some key function for the `Var`

objects?

In other words, are these two expressions the exact same trees, except we compare the `Var.var`

fields by calling the appropriate `*_var_key`

function on them, and comparing that output for equality. This function does not allow any semantic “equivalences” such as asserting that `a == b`

is equivalent to `b == a`

; the evaluation order of the operands could, in general, cause such a statement to be false (consider hypothetical `extern`

functions that access global state).

There’s no requirements on the key functions, except that their outputs should have general `__eq__`

methods. If a key function returns `None`

, the variable will be used verbatim instead.

**Parameters**

**left**(*expr.Expr*) – one of the`Expr`

nodes.**right**(*expr.Expr*) – the other`Expr`

node.**left_var_key**(*Callable*(opens in a new tab)*[[**Any*(opens in a new tab)*],**Any*(opens in a new tab)*] | None*) – a callable whose output should be used when comparing`Var.var`

attributes. If this argument is`None`

or its output is`None`

for a given variable in`left`

, the variable will be used verbatim.**right_var_key**(*Callable*(opens in a new tab)*[[**Any*(opens in a new tab)*],**Any*(opens in a new tab)*] | None*) – same as`left_var_key`

, but used on the variables in`right`

instead.

**Return type**

**Examples**

Comparing two expressions for structural equivalence, with no remapping of the variables. These are different because the different `Clbit`

instances compare differently:

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

Comparing the same two expressions, but this time using mapping functions that associate the bits with simple 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
```

Some expressions have associated memory locations, and others may be purely temporary. You can use `is_lvalue()`

to determine whether an expression has an associated memory location.

#### is_lvalue

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

Return whether this expression can be used in l-value positions, that is, whether it has a well-defined location in memory, such as one that might be writeable.

Being an l-value is a necessary but not sufficient for this location to be writeable; it is permissible that a larger object containing this memory location may not allow writing from the scope that attempts to write to it. This would be an access property of the containing program, however, and not an inherent property of the expression system.

**Examples**

Literal values are never l-values; there’s no memory location associated with (for example) the constant `1`

:

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

`Var`

nodes are always l-values, because they always have some associated memory location:

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

Currently there are no unary or binary operations on variables that can produce an l-value expression, but it is likely in the future that some sort of “indexing” operation will be added, which could produce l-values:

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

**Return type**

## Typing

`qiskit.circuit.classical.types`

### Representation

The type system of the expression tree is exposed through this module. This is inherently linked to the expression system in the `expr`

module, as most expressions can only be understood with the context of the types that they act on.

All types inherit from an abstract base class:

#### Type

*class *`qiskit.circuit.classical.types.Type`

Root base class of all nodes in the type tree. The base case should never be instantiated directly.

This must not be subclassed by users; subclasses form the internal data of the representation of expressions, and it does not make sense to add more outside of Qiskit library code.

Types should be considered immutable objects, and you must not mutate them. It is permissible to reuse a `Type`

that you take from another object without copying it, and generally this will be the best approach for performance. `Type`

objects are designed to be small amounts of data, and it’s best to point to the same instance of the data where possible rather than heap-allocating a new version of the same thing. Where possible, the class constructors will return singleton instances to facilitate this.

The two different types available are for Booleans (corresponding to `Clbit`

and the literals `True`

and `False`

), and unsigned integers (corresponding to `ClassicalRegister`

and Python integers).

#### Bool

*final class *`qiskit.circuit.classical.types.Bool`

The Boolean type. This has exactly two values: `True`

and `False`

.

#### Uint

*final class *`qiskit.circuit.classical.types.Uint(width)`

An unsigned integer of fixed bit width.

Note that `Uint`

defines a family of types parametrised by their width; it is not one single type, which may be slightly different to the ‘classical’ programming languages you are used to.

### Working with types

There are some additional functions on these types documented in the subsequent sections. These are mostly expected to be used only in manipulations of the expression tree; users who are building expressions using the user-facing construction interface should not need to use these.

### Partial ordering of types

The type system is equipped with a partial ordering, where $a < b$ is interpreted as “$a$ is a strict subtype of $b$”. Note that the partial ordering is a subset of the directed graph that describes the allowed explicit casting operations between types. The partial ordering defines when one type may be lossless directly interpreted as another.

The low-level interface to querying the subtyping relationship is the `order()`

function.

#### order

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

Get the ordering relationship between the two types as an enumeration value.

**Examples**

Compare two `Uint`

types of different widths:

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

Compare two types that have no ordering between them:

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

**Return type**

The return value is an enumeration `Ordering`

that describes what, if any, subtyping relationship exists between the two types.

#### Ordering

*class *`qiskit.circuit.classical.types.Ordering(value)`

Enumeration listing the possible relations between two types. Types only have a partial ordering, so it’s possible for two types to have no sub-typing relationship.

Note that the sub-/supertyping relationship is not the same as whether a type can be explicitly cast from one to another.

Some helper methods are then defined in terms of this low-level `order()`

primitive:

#### is_subtype

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

Does the relation $\text{left} \le \text{right}$ hold? If there is no ordering relation between the two types, then this returns `False`

. If `strict`

, then the equality is also forbidden.

**Examples**

Check if one type is a subclass of another:

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

Check if one type is a strict subclass of another:

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

**Return type**

#### is_supertype

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

Does the relation $\text{left} \ge \text{right}$ hold? If there is no ordering relation between the two types, then this returns `False`

. If `strict`

, then the equality is also forbidden.

**Examples**

Check if one type is a superclass of another:

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

Check if one type is a strict superclass of another:

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

**Return type**

#### greater

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

Get the greater of the two types, assuming that there is an ordering relation between them. Technically, this is a slightly restricted version of the concept of the ‘meet’ of the two types in that the return value must be one of the inputs. In practice in the type system there is no concept of a ‘sum’ type, so the ‘meet’ exists if and only if there is an ordering between the two types, and is equal to the greater of the two types.

**Returns**

The greater of the two types.

**Raises**

**TypeError**(opens in a new tab) – if there is no ordering relation between the two types.

**Return type**

**Examples**

Find the greater of two `Uint`

types:

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

### Casting between types

It is common to need to cast values of one type to another type. The casting rules for this are embedded into the `types`

(opens in a new tab) module. You can query the casting kinds using `cast_kind()`

:

#### cast_kind

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

Determine the sort of cast that is required to move from the left type to the right type.

**Examples**

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

**Return type**

The return values from this function are an enumeration explaining the types of cast that are allowed from the left type to the right type.

#### CastKind

*class *`qiskit.circuit.classical.types.CastKind(value)`

A return value indicating the type of cast that can occur from one type to another.