Skip to content

Advanced Usage

Running with Jupyter Notebook

The Classiq SDK automatically identifies whether it runs in Jupyter Notebook, and adjusts accordingly. However, if Classiq does not identify Jupyter, you can execute this code snippet:

import classiq

classiq.enable_jupyter_notebook()

Configuration

There are multiple ways to configure the SDK.

  • Configuration file: A file with .ini or .yaml style syntax. For example:
    classiq-host: "https://myclassiqbackend.com"
    
    Multiple locations are checked1 according to the following order:
    • /etc/classiq/config.ini
    • /etc/classiq.conf
    • ~/.config/classiq/config.ini
    • ~/.config/classiq.conf
    • classiq/config.ini
  • Command line argument
  • Environment variables
  • Dynamic configuration: You can configure the SDK within the Python script. Create a Configuration object (defined in classiq.config) and pass it on as an argument to the function classiq.configure, as in the example below.

    import classiq
    
    conf = classiq.Configuration(host="https://myclassiqbackend.com")
    classiq.configure(conf=conf)
    

These configuration options are supported:

  • classiq-host - This flag determines the backend host URL. By default, the SDK works against the Classiq public domain, but you might want to reconfigure it to work against a different URL.
  • classiq-config-file - This flag determines the configuration file used by the SDK. By default, the SDK looks for a configuration file under /classiq/config.ini, but you can configure a different path using either command line arguments or environment variables.
  • classiq-skip-check-host - This flag disables the validation of the SDK version. By default, the SDK checks that it is compatible with the backend version when the connection between them is established. If this flag is present, this check is suppressed.

Concurrent Programming

All the Python SDK functions have both synchronous (sync) and asynchronous (async) versions. The async versions are named function_async. For example, model.synthesize is the sync version, and model.synthesize_async is the async version.

Synchronous functions work like typical Python functions, and block the execution until they finish. Asynchronous functions can be executed concurrently for increased efficiency. Refer to Python docs - asyncio.

Example

This example generates and executes multiple circuits concurrently, cutting execution time by half:

  • Synchronous code executes the second circuit only after the first one finishes.
  • Asynchronous code runs them in parallel.
import asyncio

from classiq import Model, RegisterUserInput, Executor
from classiq.builtin_functions import ArithmeticOracle, GroverOperator

from classiq.execution import (
    ExecutionPreferences,
    AmplitudeAmplification,
)


async def execute_circuit(expression, preferences):
    print(f"Setting up circuit: {expression=}")
    oracle_params = ArithmeticOracle(
        expression=expression,
        definitions=dict(
            a=RegisterUserInput(size=4),
            b=RegisterUserInput(size=4, is_signed=True),
        ),
        uncomputation_method="optimized",
        qubit_count=25,
    )
    grover_params = GroverOperator(oracle_params=oracle_params)

    model = Model()
    model.GroverOperator(grover_params)

    circuit = await model.synthesize_async()
    print(f"Circuit generation complete! {expression=}")

    result = await Executor(preferences=preferences).execute_async(circuit)
    print(f"Circuit execution done! {expression=}")
    print(f"\tResult: {result.result}")


async def main():
    expressions = [
        "a + b == 7 and a & b == 8",
        "a + b == 5 and a & b == 2",
    ]

    preferences = ExecutionPreferences(
        amplitude_amplification=AmplitudeAmplification(
            growth_rate=2, sample_from_iterations=False
        )
    )

    all_circuit_executors = await asyncio.gather(
        *[execute_circuit(expression, preferences) for expression in expressions]
    )

    print("Done!")


asyncio.run(main())

Possible output:

Setting up circuit: expression='a + b == 7 and a & b == 8'
Setting up circuit: expression='a + b == 5 and a & b == 2'
Circuit generation complete! expression='a + b == 7 and a & b == 8'
Circuit generation complete! expression='a + b == 5 and a & b == 2'
Circuit execution done! expression='a + b == 7 and a & b == 8'
    Result: {'a': 14.0, 'b': -7.0}
Circuit execution done! expression='a + b == 5 and a & b == 2'
    Result: {'a': 2.0, 'b': 3.0}
Done!

  1. The /etc folder is commonly used for system-wide configuration, ~/.config is for user-wide configuration, and classiq/config.ini is relative to the current working directory.