Skip to content

pipeline

pipeline ¤

_PIPELINE_CONTEXT = ContextVar('_PIPELINE_CONTEXT', default=PipelineContext.from_default_backend()) module-attribute ¤

PipelineContext ¤

Bases: AbstractContextManager

A pipeline context is a Python context manager used to compile circuits and specify backend-specific compilation flags and optimizations. A pipeline context can also be used to register compilation rules for user-defined layers, parameterizations and initialization methods. Furthermore, new layer operators can be added to the context.

Source code in cirkit/pipeline.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
class PipelineContext(AbstractContextManager):
    """A pipeline context is a Python context manager used to compile
    circuits and specify backend-specific compilation flags and optimizations.
    A pipeline context can also be used to register compilation rules for user-defined
    layers, parameterizations and initialization methods. Furthermore, new layer operators
    can be added to the context.
    """

    def __init__(self, backend: str = "torch", **backend_kwargs):
        """Initialzes a pipeline context, given the compilation backend and
            the compilation flags.

        Args:
            backend: The compilation backend.  The only backend supported is 'torch'.
            backend_kwargs: The compilation flags to pass to the compiler.

        Raises:
            ValuerError: if the compilation backend is unknown.
        """
        if backend not in SUPPORTED_BACKENDS:
            raise NotImplementedError(f"Backend '{backend}' is not implemented")
        # Backend specs
        self._backend = backend
        self._backend_kwargs = backend_kwargs

        # Symbolic operator registry
        self._op_registry = OperatorRegistry.from_default_rules()

        # Get the compiler, which is backend-dependent
        self._compiler = retrieve_compiler(backend, **backend_kwargs)

        # The token used to restore the pipeline context
        self._token: Token[PipelineContext] | None = None

    @classmethod
    def from_default_backend(cls) -> "PipelineContext":
        """Construts a pipeline context from the default backend.
            The default backend is 'torch'.

        Returns:
            A pipeline context from the default backend by specifying default
                values for the compilation flags.
        """
        return PipelineContext(backend="torch", semiring="lse-sum", fold=True, optimize=True)

    def __getitem__(self, sc: Circuit) -> CompiledCircuit:
        """Retrieves a compiled circuit, given a symbolic one.

        Args:
            sc: The symbolic circuit.

        Returns:
            The circuit compiled from the given symbolic circuit.
        """
        return self._compiler.get_compiled_circuit(sc)

    def __enter__(self) -> "PipelineContext":
        """Enters a pipeline context.

        Returns:
            Itself.
        """
        self._op_registry.__enter__()
        self._token = _PIPELINE_CONTEXT.set(self)
        return self

    def __exit__(
        self,
        __exc_type: type[BaseException] | None,
        __exc_value: BaseException | None,
        __traceback: TracebackType | None,
    ) -> bool | None:
        """Exit a pipeline context."""
        ret = self._op_registry.__exit__(__exc_type, __exc_value, __traceback)
        _PIPELINE_CONTEXT.reset(self._token)
        self._token = None
        return ret

    def add_operator_rule(self, op: LayerOperator, func: LayerOperatorFunc):
        """Add a new layer operator to the context.

        Args:
            op: The layer operator.
            func: The layer operator implementation.
        """
        self._op_registry.add_rule(op, func)

    def add_layer_compilation_rule(self, func: LayerCompilationFunc):
        """Add a new layer compilation rule to the current compilation backend.

        Args:
            func: The layer compilation rule.
        """
        self._compiler.add_layer_rule(func)

    def add_parameter_compilation_rule(self, func: ParameterCompilationFunc):
        """Add a new parameter compilation rule to the current compilation backend.

        Args:
            func: The parameter compilation rule.
        """
        self._compiler.add_parameter_rule(func)

    def add_initializer_compilation_rule(self, func: InitializerCompilationFunc):
        """Add a new initialization method compilation rule to the current compilation backend.

        Args:
            func: The initializer compilation rule.
        """
        self._compiler.add_initializer_rule(func)

    def compile(self, sc: Circuit) -> CompiledCircuit:
        """Compile a symbolic circuit.

        Args:
            sc: The symbolic circuit.

        Returns:
            A compiled circuit, whose type depends on the chosen compilation backend.
        """
        return self._compiler.compile(sc)

    def is_compiled(self, sc: Circuit) -> bool:
        """Check whether a symbolic circuit has been compiled in this context.

        Args:
            sc: The symbolic circuit.

        Returns:
            True if the given symbolic circuit has been compiled in this context, False otherwise.
        """
        return self._compiler.is_compiled(sc)

    def has_symbolic(self, cc: CompiledCircuit) -> bool:
        """Check whether a compiled circuit has a corresponding symbolic circuit
            in this context.

        Args:
            cc: The compiled circuit.

        Returns:
            False if the given compiled circuit has been compiled in this context, False otherwise.
        """
        return self._compiler.has_symbolic(cc)

    def get_compiled_circuit(self, sc: Circuit) -> CompiledCircuit:
        """Retrieves a compiled circuit, given a symbolic one.

        Args:
            sc: The symbolic circuit.

        Returns:
            The circuit compiled from the given symbolic circuit.
        """
        return self._compiler.get_compiled_circuit(sc)

    def get_symbolic_circuit(self, cc: CompiledCircuit) -> Circuit:
        """Retrieves a symbolic circuit, given a compiled one.

        Args:
            cc: The compiled circuit.

        Returns:
            The symbolic circuit associated to the given compiled one.
        """
        return self._compiler.get_symbolic_circuit(cc)

    def concatenate(self, *cc: CompiledCircuit) -> CompiledCircuit:
        """Circuit concatenation interface for compiled circuits.
            See [concantenate][cirkit.symbolic.functional.concatenate] for more details.

        Args:
            *cc: A sequence of compiled circuits.

        Returns:
            The circuit that encodes the concatenation of the given circuits.

        Raises:
            ValueError: if the given circuits have not been compiled in this context.
        """
        for i, cci in enumerate(cc):
            if not self._compiler.has_symbolic(cci):
                raise ValueError(f"The {i}-th given compiled circuit is not known in this pipeline")
        sc = [self._compiler.get_symbolic_circuit(cci) for cci in cc]
        cat_sc = SF.concatenate(*sc, registry=self._op_registry)
        return self.compile(cat_sc)

    def integrate(self, cc: CompiledCircuit, scope: Scope | None = None) -> CompiledCircuit:
        """Circuit integration interface for compiled circuits.
            See [concantenate][cirkit.symbolic.functional.integrate] for more details.

        Args:
            cc: A compiled circuit.
            scope: The variables scope to integrate. If it is None, then all variables
                the given circuit is defined on are integrated.

        Returns:
            The circuit that encodes the integration over (some) variables of the given circuit.

        Raises:
            ValueError: if the given circuit has not been compiled in this context.
        """
        if not self._compiler.has_symbolic(cc):
            raise ValueError("The given compiled circuit is not known in this pipeline")
        sc = self._compiler.get_symbolic_circuit(cc)
        int_sc = SF.integrate(sc, scope=scope, registry=self._op_registry)
        return self.compile(int_sc)

    def multiply(self, cc1: CompiledCircuit, cc2: CompiledCircuit) -> CompiledCircuit:
        """Circuit multiplication interface for compiled circuits.
            See [multiply][cirkit.symbolic.functional.multiply] for more details.

        Args:
            cc1: The first compiled circuit.
            cc2: The second compiled circuit.

        Returns:
            The circuit that encodes the multiplicaton between the given circuits.

        Raises:
            ValueError: if the given circuits have not been compiled in this context.
        """
        if not self._compiler.has_symbolic(cc1):
            raise ValueError("The first compiled circuit is not known in this pipeline")
        if not self._compiler.has_symbolic(cc2):
            raise ValueError("The second compiled circuit is not known in this pipeline")
        sc1 = self._compiler.get_symbolic_circuit(cc1)
        sc2 = self._compiler.get_symbolic_circuit(cc2)
        prod_sc = SF.multiply(sc1, sc2, registry=self._op_registry)
        return self.compile(prod_sc)

    def differentiate(self, cc: CompiledCircuit, *, order: int = 1) -> CompiledCircuit:
        """Circuit differentiation interface for compiled circuits.
            See [differentiate][cirkit.symbolic.functional.differentiate] for more details.

        Args:
            cc: The compiled circuit.
            order: The differentiation order.

        Returns:
            The circuit that encodes the differentiation of the given compiled circuit.

        Raises:
            ValueError: if the given circuit has not been compiled in this context.
            ValueError: if the differentiation order is not a positive integer.
        """
        if not self._compiler.has_symbolic(cc):
            raise ValueError("The given compiled circuit is not known in this pipeline")
        if order <= 0:
            raise ValueError("The order of differentiation must be positive.")
        sc = self._compiler.get_symbolic_circuit(cc)
        diff_sc = SF.differentiate(sc, order=order, registry=self._op_registry)
        return self.compile(diff_sc)

    def conjugate(self, cc: CompiledCircuit) -> CompiledCircuit:
        """Circuit conjugation interface for compiled circuits.
            See [conjugate][cirkit.symbolic.functional.conjugate] for more details.

        Args:
            cc: The compiled circuit.

        Returns:
            The circuit that encodes the complex conjugation of the given compiled circuit.

        Raises:
            ValueError: if the given circuit has not been compiled in this context.
        """
        if not self._compiler.has_symbolic(cc):
            raise ValueError("The given compiled circuit is not known in this pipeline")
        sc = self._compiler.get_symbolic_circuit(cc)
        conj_sc = SF.conjugate(sc, registry=self._op_registry)
        return self.compile(conj_sc)

_backend = backend instance-attribute ¤

_backend_kwargs = backend_kwargs instance-attribute ¤

_compiler = retrieve_compiler(backend, **backend_kwargs) instance-attribute ¤

_op_registry = OperatorRegistry.from_default_rules() instance-attribute ¤

_token = None instance-attribute ¤

__enter__() ¤

Enters a pipeline context.

Returns:

Type Description
PipelineContext

Itself.

Source code in cirkit/pipeline.py
78
79
80
81
82
83
84
85
86
def __enter__(self) -> "PipelineContext":
    """Enters a pipeline context.

    Returns:
        Itself.
    """
    self._op_registry.__enter__()
    self._token = _PIPELINE_CONTEXT.set(self)
    return self

__exit__(__exc_type, __exc_value, __traceback) ¤

Exit a pipeline context.

Source code in cirkit/pipeline.py
88
89
90
91
92
93
94
95
96
97
98
def __exit__(
    self,
    __exc_type: type[BaseException] | None,
    __exc_value: BaseException | None,
    __traceback: TracebackType | None,
) -> bool | None:
    """Exit a pipeline context."""
    ret = self._op_registry.__exit__(__exc_type, __exc_value, __traceback)
    _PIPELINE_CONTEXT.reset(self._token)
    self._token = None
    return ret

__getitem__(sc) ¤

Retrieves a compiled circuit, given a symbolic one.

Parameters:

Name Type Description Default
sc Circuit

The symbolic circuit.

required

Returns:

Type Description
CompiledCircuit

The circuit compiled from the given symbolic circuit.

Source code in cirkit/pipeline.py
67
68
69
70
71
72
73
74
75
76
def __getitem__(self, sc: Circuit) -> CompiledCircuit:
    """Retrieves a compiled circuit, given a symbolic one.

    Args:
        sc: The symbolic circuit.

    Returns:
        The circuit compiled from the given symbolic circuit.
    """
    return self._compiler.get_compiled_circuit(sc)

__init__(backend='torch', **backend_kwargs) ¤

Initialzes a pipeline context, given the compilation backend and the compilation flags.

Parameters:

Name Type Description Default
backend str

The compilation backend. The only backend supported is 'torch'.

'torch'
backend_kwargs

The compilation flags to pass to the compiler.

{}

Raises:

Type Description
ValuerError

if the compilation backend is unknown.

Source code in cirkit/pipeline.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def __init__(self, backend: str = "torch", **backend_kwargs):
    """Initialzes a pipeline context, given the compilation backend and
        the compilation flags.

    Args:
        backend: The compilation backend.  The only backend supported is 'torch'.
        backend_kwargs: The compilation flags to pass to the compiler.

    Raises:
        ValuerError: if the compilation backend is unknown.
    """
    if backend not in SUPPORTED_BACKENDS:
        raise NotImplementedError(f"Backend '{backend}' is not implemented")
    # Backend specs
    self._backend = backend
    self._backend_kwargs = backend_kwargs

    # Symbolic operator registry
    self._op_registry = OperatorRegistry.from_default_rules()

    # Get the compiler, which is backend-dependent
    self._compiler = retrieve_compiler(backend, **backend_kwargs)

    # The token used to restore the pipeline context
    self._token: Token[PipelineContext] | None = None

add_initializer_compilation_rule(func) ¤

Add a new initialization method compilation rule to the current compilation backend.

Parameters:

Name Type Description Default
func InitializerCompilationFunc

The initializer compilation rule.

required
Source code in cirkit/pipeline.py
125
126
127
128
129
130
131
def add_initializer_compilation_rule(self, func: InitializerCompilationFunc):
    """Add a new initialization method compilation rule to the current compilation backend.

    Args:
        func: The initializer compilation rule.
    """
    self._compiler.add_initializer_rule(func)

add_layer_compilation_rule(func) ¤

Add a new layer compilation rule to the current compilation backend.

Parameters:

Name Type Description Default
func LayerCompilationFunc

The layer compilation rule.

required
Source code in cirkit/pipeline.py
109
110
111
112
113
114
115
def add_layer_compilation_rule(self, func: LayerCompilationFunc):
    """Add a new layer compilation rule to the current compilation backend.

    Args:
        func: The layer compilation rule.
    """
    self._compiler.add_layer_rule(func)

add_operator_rule(op, func) ¤

Add a new layer operator to the context.

Parameters:

Name Type Description Default
op LayerOperator

The layer operator.

required
func LayerOperatorFunc

The layer operator implementation.

required
Source code in cirkit/pipeline.py
100
101
102
103
104
105
106
107
def add_operator_rule(self, op: LayerOperator, func: LayerOperatorFunc):
    """Add a new layer operator to the context.

    Args:
        op: The layer operator.
        func: The layer operator implementation.
    """
    self._op_registry.add_rule(op, func)

add_parameter_compilation_rule(func) ¤

Add a new parameter compilation rule to the current compilation backend.

Parameters:

Name Type Description Default
func ParameterCompilationFunc

The parameter compilation rule.

required
Source code in cirkit/pipeline.py
117
118
119
120
121
122
123
def add_parameter_compilation_rule(self, func: ParameterCompilationFunc):
    """Add a new parameter compilation rule to the current compilation backend.

    Args:
        func: The parameter compilation rule.
    """
    self._compiler.add_parameter_rule(func)

compile(sc) ¤

Compile a symbolic circuit.

Parameters:

Name Type Description Default
sc Circuit

The symbolic circuit.

required

Returns:

Type Description
CompiledCircuit

A compiled circuit, whose type depends on the chosen compilation backend.

Source code in cirkit/pipeline.py
133
134
135
136
137
138
139
140
141
142
def compile(self, sc: Circuit) -> CompiledCircuit:
    """Compile a symbolic circuit.

    Args:
        sc: The symbolic circuit.

    Returns:
        A compiled circuit, whose type depends on the chosen compilation backend.
    """
    return self._compiler.compile(sc)

concatenate(*cc) ¤

Circuit concatenation interface for compiled circuits. See concantenate for more details.

Parameters:

Name Type Description Default
*cc CompiledCircuit

A sequence of compiled circuits.

()

Returns:

Type Description
CompiledCircuit

The circuit that encodes the concatenation of the given circuits.

Raises:

Type Description
ValueError

if the given circuits have not been compiled in this context.

Source code in cirkit/pipeline.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
def concatenate(self, *cc: CompiledCircuit) -> CompiledCircuit:
    """Circuit concatenation interface for compiled circuits.
        See [concantenate][cirkit.symbolic.functional.concatenate] for more details.

    Args:
        *cc: A sequence of compiled circuits.

    Returns:
        The circuit that encodes the concatenation of the given circuits.

    Raises:
        ValueError: if the given circuits have not been compiled in this context.
    """
    for i, cci in enumerate(cc):
        if not self._compiler.has_symbolic(cci):
            raise ValueError(f"The {i}-th given compiled circuit is not known in this pipeline")
    sc = [self._compiler.get_symbolic_circuit(cci) for cci in cc]
    cat_sc = SF.concatenate(*sc, registry=self._op_registry)
    return self.compile(cat_sc)

conjugate(cc) ¤

Circuit conjugation interface for compiled circuits. See conjugate for more details.

Parameters:

Name Type Description Default
cc CompiledCircuit

The compiled circuit.

required

Returns:

Type Description
CompiledCircuit

The circuit that encodes the complex conjugation of the given compiled circuit.

Raises:

Type Description
ValueError

if the given circuit has not been compiled in this context.

Source code in cirkit/pipeline.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def conjugate(self, cc: CompiledCircuit) -> CompiledCircuit:
    """Circuit conjugation interface for compiled circuits.
        See [conjugate][cirkit.symbolic.functional.conjugate] for more details.

    Args:
        cc: The compiled circuit.

    Returns:
        The circuit that encodes the complex conjugation of the given compiled circuit.

    Raises:
        ValueError: if the given circuit has not been compiled in this context.
    """
    if not self._compiler.has_symbolic(cc):
        raise ValueError("The given compiled circuit is not known in this pipeline")
    sc = self._compiler.get_symbolic_circuit(cc)
    conj_sc = SF.conjugate(sc, registry=self._op_registry)
    return self.compile(conj_sc)

differentiate(cc, *, order=1) ¤

Circuit differentiation interface for compiled circuits. See differentiate for more details.

Parameters:

Name Type Description Default
cc CompiledCircuit

The compiled circuit.

required
order int

The differentiation order.

1

Returns:

Type Description
CompiledCircuit

The circuit that encodes the differentiation of the given compiled circuit.

Raises:

Type Description
ValueError

if the given circuit has not been compiled in this context.

ValueError

if the differentiation order is not a positive integer.

Source code in cirkit/pipeline.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
def differentiate(self, cc: CompiledCircuit, *, order: int = 1) -> CompiledCircuit:
    """Circuit differentiation interface for compiled circuits.
        See [differentiate][cirkit.symbolic.functional.differentiate] for more details.

    Args:
        cc: The compiled circuit.
        order: The differentiation order.

    Returns:
        The circuit that encodes the differentiation of the given compiled circuit.

    Raises:
        ValueError: if the given circuit has not been compiled in this context.
        ValueError: if the differentiation order is not a positive integer.
    """
    if not self._compiler.has_symbolic(cc):
        raise ValueError("The given compiled circuit is not known in this pipeline")
    if order <= 0:
        raise ValueError("The order of differentiation must be positive.")
    sc = self._compiler.get_symbolic_circuit(cc)
    diff_sc = SF.differentiate(sc, order=order, registry=self._op_registry)
    return self.compile(diff_sc)

from_default_backend() classmethod ¤

Construts a pipeline context from the default backend. The default backend is 'torch'.

Returns:

Type Description
PipelineContext

A pipeline context from the default backend by specifying default values for the compilation flags.

Source code in cirkit/pipeline.py
56
57
58
59
60
61
62
63
64
65
@classmethod
def from_default_backend(cls) -> "PipelineContext":
    """Construts a pipeline context from the default backend.
        The default backend is 'torch'.

    Returns:
        A pipeline context from the default backend by specifying default
            values for the compilation flags.
    """
    return PipelineContext(backend="torch", semiring="lse-sum", fold=True, optimize=True)

get_compiled_circuit(sc) ¤

Retrieves a compiled circuit, given a symbolic one.

Parameters:

Name Type Description Default
sc Circuit

The symbolic circuit.

required

Returns:

Type Description
CompiledCircuit

The circuit compiled from the given symbolic circuit.

Source code in cirkit/pipeline.py
167
168
169
170
171
172
173
174
175
176
def get_compiled_circuit(self, sc: Circuit) -> CompiledCircuit:
    """Retrieves a compiled circuit, given a symbolic one.

    Args:
        sc: The symbolic circuit.

    Returns:
        The circuit compiled from the given symbolic circuit.
    """
    return self._compiler.get_compiled_circuit(sc)

get_symbolic_circuit(cc) ¤

Retrieves a symbolic circuit, given a compiled one.

Parameters:

Name Type Description Default
cc CompiledCircuit

The compiled circuit.

required

Returns:

Type Description
Circuit

The symbolic circuit associated to the given compiled one.

Source code in cirkit/pipeline.py
178
179
180
181
182
183
184
185
186
187
def get_symbolic_circuit(self, cc: CompiledCircuit) -> Circuit:
    """Retrieves a symbolic circuit, given a compiled one.

    Args:
        cc: The compiled circuit.

    Returns:
        The symbolic circuit associated to the given compiled one.
    """
    return self._compiler.get_symbolic_circuit(cc)

has_symbolic(cc) ¤

Check whether a compiled circuit has a corresponding symbolic circuit in this context.

Parameters:

Name Type Description Default
cc CompiledCircuit

The compiled circuit.

required

Returns:

Type Description
bool

False if the given compiled circuit has been compiled in this context, False otherwise.

Source code in cirkit/pipeline.py
155
156
157
158
159
160
161
162
163
164
165
def has_symbolic(self, cc: CompiledCircuit) -> bool:
    """Check whether a compiled circuit has a corresponding symbolic circuit
        in this context.

    Args:
        cc: The compiled circuit.

    Returns:
        False if the given compiled circuit has been compiled in this context, False otherwise.
    """
    return self._compiler.has_symbolic(cc)

integrate(cc, scope=None) ¤

Circuit integration interface for compiled circuits. See concantenate for more details.

Parameters:

Name Type Description Default
cc CompiledCircuit

A compiled circuit.

required
scope Scope | None

The variables scope to integrate. If it is None, then all variables the given circuit is defined on are integrated.

None

Returns:

Type Description
CompiledCircuit

The circuit that encodes the integration over (some) variables of the given circuit.

Raises:

Type Description
ValueError

if the given circuit has not been compiled in this context.

Source code in cirkit/pipeline.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
def integrate(self, cc: CompiledCircuit, scope: Scope | None = None) -> CompiledCircuit:
    """Circuit integration interface for compiled circuits.
        See [concantenate][cirkit.symbolic.functional.integrate] for more details.

    Args:
        cc: A compiled circuit.
        scope: The variables scope to integrate. If it is None, then all variables
            the given circuit is defined on are integrated.

    Returns:
        The circuit that encodes the integration over (some) variables of the given circuit.

    Raises:
        ValueError: if the given circuit has not been compiled in this context.
    """
    if not self._compiler.has_symbolic(cc):
        raise ValueError("The given compiled circuit is not known in this pipeline")
    sc = self._compiler.get_symbolic_circuit(cc)
    int_sc = SF.integrate(sc, scope=scope, registry=self._op_registry)
    return self.compile(int_sc)

is_compiled(sc) ¤

Check whether a symbolic circuit has been compiled in this context.

Parameters:

Name Type Description Default
sc Circuit

The symbolic circuit.

required

Returns:

Type Description
bool

True if the given symbolic circuit has been compiled in this context, False otherwise.

Source code in cirkit/pipeline.py
144
145
146
147
148
149
150
151
152
153
def is_compiled(self, sc: Circuit) -> bool:
    """Check whether a symbolic circuit has been compiled in this context.

    Args:
        sc: The symbolic circuit.

    Returns:
        True if the given symbolic circuit has been compiled in this context, False otherwise.
    """
    return self._compiler.is_compiled(sc)

multiply(cc1, cc2) ¤

Circuit multiplication interface for compiled circuits. See multiply for more details.

Parameters:

Name Type Description Default
cc1 CompiledCircuit

The first compiled circuit.

required
cc2 CompiledCircuit

The second compiled circuit.

required

Returns:

Type Description
CompiledCircuit

The circuit that encodes the multiplicaton between the given circuits.

Raises:

Type Description
ValueError

if the given circuits have not been compiled in this context.

Source code in cirkit/pipeline.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
def multiply(self, cc1: CompiledCircuit, cc2: CompiledCircuit) -> CompiledCircuit:
    """Circuit multiplication interface for compiled circuits.
        See [multiply][cirkit.symbolic.functional.multiply] for more details.

    Args:
        cc1: The first compiled circuit.
        cc2: The second compiled circuit.

    Returns:
        The circuit that encodes the multiplicaton between the given circuits.

    Raises:
        ValueError: if the given circuits have not been compiled in this context.
    """
    if not self._compiler.has_symbolic(cc1):
        raise ValueError("The first compiled circuit is not known in this pipeline")
    if not self._compiler.has_symbolic(cc2):
        raise ValueError("The second compiled circuit is not known in this pipeline")
    sc1 = self._compiler.get_symbolic_circuit(cc1)
    sc2 = self._compiler.get_symbolic_circuit(cc2)
    prod_sc = SF.multiply(sc1, sc2, registry=self._op_registry)
    return self.compile(prod_sc)

compile(sc, ctx=None) ¤

Source code in cirkit/pipeline.py
296
297
298
299
def compile(sc: Circuit, ctx: PipelineContext | None = None) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.compile(sc)

concatenate(*cc, ctx=None) ¤

Source code in cirkit/pipeline.py
302
303
304
305
def concatenate(*cc: CompiledCircuit, ctx: PipelineContext | None = None) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.concatenate(cc)

conjugate(cc, ctx=None) ¤

Source code in cirkit/pipeline.py
334
335
336
337
def conjugate(cc: CompiledCircuit, ctx: PipelineContext | None = None) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.conjugate(cc)

differentiate(cc, ctx=None, *, order=1) ¤

Source code in cirkit/pipeline.py
326
327
328
329
330
331
def differentiate(
    cc: CompiledCircuit, ctx: PipelineContext | None = None, *, order: int = 1
) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.differentiate(cc, order=order)

integrate(cc, scope=None, ctx=None) ¤

Source code in cirkit/pipeline.py
308
309
310
311
312
313
314
315
def integrate(
    cc: CompiledCircuit,
    scope: Iterable[int] | None = None,
    ctx: PipelineContext | None = None,
) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.integrate(cc, scope=scope)

multiply(cc1, cc2, ctx=None) ¤

Source code in cirkit/pipeline.py
318
319
320
321
322
323
def multiply(
    cc1: CompiledCircuit, cc2: CompiledCircuit, ctx: PipelineContext | None = None
) -> CompiledCircuit:
    if ctx is None:
        ctx = _PIPELINE_CONTEXT.get()
    return ctx.multiply(cc1, cc2)

retrieve_compiler(backend, **backend_kwargs) ¤

Source code in cirkit/pipeline.py
340
341
342
343
344
345
346
347
348
def retrieve_compiler(backend: str, **backend_kwargs) -> AbstractCompiler:
    if backend not in SUPPORTED_BACKENDS:
        raise NotImplementedError(f"Backend '{backend}' is not implemented")
    if backend == "torch":
        # pylint: disable-next=import-outside-toplevel
        from cirkit.backend.torch.compiler import TorchCompiler

        return TorchCompiler(**backend_kwargs)
    assert False