PySparQ.pysparq.dynamic_operator¶
PySparQ dynamic operator extension module - provides runtime compilation and loading of custom C++ operators.
Warning
compile_operator() merely compiles the user-provided operator()/dag()
into a shared library and calls it via ctypes; a successful compilation only means
the code passes C++ type checking. It does not imply, and cannot statically
or dynamically prove, that the operator is unitary or that operator()/dag()
are inverses of each other. Any implementation that overwrites registers on its
own, implements dag() by zeroing registers, or destroys information in some
other way will compile without complaint.
Therefore, the QCFD paths supported by this repository (QECC.Lang-driven
qfvm/qnls/qham) are forbidden from using dynamic operators compiled via
compile_operator. All semantics must be expressed through named, statically
checkable PySparQ built-in operators (or Python composite operators built from
built-in operators), and validated with the conformance test matrix provided by
pysparq.conformance (arbitrary non-zero outputs, exhaustive/sampled basis
states, collision detection, linearity on superpositions, positive/negative/
multiple controls, and forward+dagger and dagger+forward identity).
compile_operator remains a general-purpose (not QCFD-specific) runtime
operator compilation tool that can be used for prototyping, teaching, or
experiments unrelated to QCFD, but it must not be treated as having passed any
unitarity proof.
Submodules¶
Exceptions¶
Compilation error exception. |
|
Dynamic operator error. |
|
Factory function invocation error. |
|
Dynamic library load error. |
Classes¶
Compiler configuration. |
|
C++ operator wrapper |
Functions¶
Clean up all active dynamic operator instances |
|
|
Clear the compilation cache |
|
Compile C++ code into a shared library |
|
Compile C++ code into a dynamic operator class. |
|
Compute the code hash used for caching |
|
Create a dynamic operator Python class |
|
Locate the project root directory or the installed package directory |
|
Format compiler error output |
|
Generate the complete C++ source file |
|
Get cache information |
|
Quickly compile C++ operator code |
Package Contents¶
- exception PySparQ.pysparq.dynamic_operator.CompilationError(message: str, stderr: str = '', returncode: int = 0)[source]¶
Bases:
ExceptionCompilation error exception.
Initialize self. See help(type(self)) for accurate signature.
- returncode = 0¶
- stderr = ''¶
- exception PySparQ.pysparq.dynamic_operator.DynamicOperatorError[source]¶
Bases:
ExceptionDynamic operator error.
Initialize self. See help(type(self)) for accurate signature.
- exception PySparQ.pysparq.dynamic_operator.DynamicOperatorFactoryError[source]¶
Bases:
DynamicOperatorErrorFactory function invocation error.
Initialize self. See help(type(self)) for accurate signature.
- exception PySparQ.pysparq.dynamic_operator.DynamicOperatorLoadError[source]¶
Bases:
DynamicOperatorErrorDynamic library load error.
Initialize self. See help(type(self)) for accurate signature.
- class PySparQ.pysparq.dynamic_operator.CompilerConfig(cxx: str = 'g++', std: str = 'c++17', opt_level: str = 'O2', include_paths: list | None = None, lib_paths: list | None = None, libraries: list | None = None, extra_flags: list | None = None, template: str | None = None)[source]¶
Compiler configuration.
Initialize the compiler configuration
- Parameters:
cxx – C++ compiler command (default g++)
std – C++ standard version (default c++17)
opt_level – Optimization level (default O2)
include_paths – Extra header search paths
lib_paths – Extra library search paths
libraries – Libraries to link against
extra_flags – Extra compiler flags
template – Custom code template
- DEFAULT_TEMPLATE = Multiline-String¶
Show Value
"""#include "basic_components.h" #include <vector> #include <complex> using namespace qram_simulator; {USER_CPP_CODE} extern "C" BaseOperator* create_operator({CTOR_PARAMS}) {{ return new {CLASS_NAME}({CTOR_ARGS}); }} extern "C" void destroy_operator(BaseOperator* op) {{ delete op; }} extern "C" const char* get_operator_name() {{ return "{CLASS_NAME}"; }} """
- PYTHON_TEMPLATE = Multiline-String¶
Show Value
"""#include "basic_components.h" #include <vector> #include <complex> using namespace qram_simulator; {USER_CPP_CODE} extern "C" BaseOperator* create_operator({CTOR_PARAMS}) {{ return new {CLASS_NAME}({CTOR_ARGS}); }} extern "C" void destroy_operator(BaseOperator* op) {{ delete op; }} extern "C" const char* get_operator_name() {{ return "{CLASS_NAME}"; }} // Python call helper - applies the operator to a SparseState // The Python side obtains the C++ SparseState* pointer via state._cpp_ptr(), // which ctypes passes as ctypes.c_void_p. extern "C" void apply_operator(BaseOperator* op, SparseState* state) {{ if (op && state) {{ (*op)(*state); }} }} // Python call helper - applies the dagger extern "C" void apply_operator_dag(BaseOperator* op, SparseState* state) {{ if (op && state) {{ op->dag(*state); }} }} // Returns the base class type extern "C" const char* get_base_class() {{ return "{BASE_CLASS}"; }} """
- cxx = 'g++'¶
- extra_flags = []¶
- include_paths = []¶
- lib_paths = []¶
- libraries = []¶
- opt_level = 'O2'¶
- std = 'c++17'¶
- template = Multiline-String¶
Show Value
"""#include "basic_components.h" #include <vector> #include <complex> using namespace qram_simulator; {USER_CPP_CODE} extern "C" BaseOperator* create_operator({CTOR_PARAMS}) {{ return new {CLASS_NAME}({CTOR_ARGS}); }} extern "C" void destroy_operator(BaseOperator* op) {{ delete op; }} extern "C" const char* get_operator_name() {{ return "{CLASS_NAME}"; }} """
- class PySparQ.pysparq.dynamic_operator.CppOperatorWrapper(lib_path: str)[source]¶
C++ operator wrapper
Loads the dynamic library and invokes the factory functions to create/destroy C++ operator objects
Initialize the wrapper
- Parameters:
lib_path – Dynamic library path
- apply(ptr: int, state_cpp_ptr: int)[source]¶
Apply the operator to a SparseState
- Parameters:
ptr – Operator object address
state_cpp_ptr – C++ SparseState* pointer (obtained via state._cpp_ptr())
- apply_dag(ptr: int, state_cpp_ptr: int)[source]¶
Apply the dagger to a SparseState
- Parameters:
ptr – Operator object address
state_cpp_ptr – C++ SparseState* pointer (obtained via state._cpp_ptr())
- close()[source]¶
Close the dynamic library and release resources
Note: on Windows, all C++ objects must already be destroyed before the dynamic library file can be deleted successfully
- create(*args) int[source]¶
Create a C++ operator instance
- Parameters:
*args – Constructor arguments
- Returns:
C++ object address (as a Python int)
- load(arg_types: List[str] = None)[source]¶
Load the dynamic library
- Parameters:
arg_types – List of constructor argument types
- Raises:
DynamicOperatorLoadError – Load failed
- lib_path¶
- PySparQ.pysparq.dynamic_operator.cleanup_all_instances()[source]¶
Clean up all active dynamic operator instances
- PySparQ.pysparq.dynamic_operator.clear_cache(cache_dir: str | None = None) int[source]¶
Clear the compilation cache
- Parameters:
cache_dir – Cache directory (defaults to the system temporary directory)
- Returns:
The number of deleted files
- PySparQ.pysparq.dynamic_operator.compile_cpp_code(cpp_code: str, class_name: str, cache_dir: str | None = None, ctor_params: str = '', ctor_args: str = '', config: CompilerConfig | None = None, project_root: str | None = None, verbose: bool = False) str[source]¶
Compile C++ code into a shared library
- Parameters:
cpp_code – User-provided C++ code (containing the class definition)
class_name – Operator class name
cache_dir – Cache directory (defaults to the system temporary directory)
ctor_params – Constructor parameter declarations
ctor_args – Constructor call arguments
config – Compiler configuration
project_root – Project root directory (auto-detected)
verbose – Whether to print verbose logs
- Returns:
Path of the compiled shared library (.so file)
- Raises:
CompilationError – Compilation failed
FileNotFoundError – Compiler not found
- PySparQ.pysparq.dynamic_operator.compile_operator(name: str, cpp_code: str, base_class: str = 'BaseOperator', extra_includes: List[str] = None, extra_libs: List[str] = None, constructor_args: List[Tuple[str, str]] = None, cache_dir: str | None = None, verbose: bool = False) Type[source]¶
Compile C++ code into a dynamic operator class.
This is a high-level function that compiles user-provided C++ code into a shared library and wraps it into an operator class that can be used directly from Python. A dynamic operator can be applied to a SparseState just like a native PySparQ operator.
Warning
A successful compilation only means
operator()/dag()passed C++ type checking; it constitutes no unitarity proof whatsoever: this function neither statically nor dynamically verifies that the generated operator is unitary, or thatdag()is actually the inverse ofoperator(). Hence the supported QCFD paths (QECC.Lang-driven qfvm/qnls/qham) forbid the use of dynamic operators compiled by this function; QCFD semantics must use named PySparQ built-in operators and be validated with thepysparq.conformanceconformance test matrix.- Parameters:
name – Operator class name. Must be a valid Python class name and must match the class name in the C++ code.
cpp_code – C++ source code, containing only the class definition part. The code must inherit from BaseOperator or SelfAdjointOperator and implement the operator() method.
base_class – Base class name, determines dagger behavior. Allowed values: - “BaseOperator”: general operator, requires a manually implemented dag() method - “SelfAdjointOperator”: Hermitian operator, dag() automatically equals operator() Defaults to “BaseOperator”.
extra_includes – List of extra header search paths. PySparQ headers are included automatically.
extra_libs – List of extra libraries to link. Most operators need no extra libraries.
constructor_args – List of constructor arguments in the form [(type, name), …]. Supported types: size_t, int, long, double, float, bool, uint64_t. Example: [(“size_t”, “reg_id”), (“double”, “phase”)]
cache_dir – Cache directory path. Defaults to pysparq_dynamic_ops/ under the system temporary directory.
verbose – Whether to print verbose compilation logs, useful for debugging.
- Returns:
The dynamically generated operator class. Instances are created with keyword arguments, e.g.: OpClass(reg_id=0, phase=1.0)
- Raises:
CompilationError – C++ compilation failed. The error message contains detailed compiler output.
DynamicOperatorLoadError – Failed to load the dynamic library.
ValueError – Invalid arguments (e.g. empty name, invalid base class, etc.).
Example
Create a simple flip operator:
>>> from pysparq.dynamic_operator import compile_operator >>> >>> cpp_code = ''' ... class FlipOp : public SelfAdjointOperator { ... size_t reg_id; ... public: ... FlipOp(size_t r) : reg_id(r) {} ... void operator()(std::vector<System>& state) const override { ... for (auto& s : state) { ... s.get(reg_id).value ^= 1; ... } ... } ... }; ... ''' >>> >>> FlipOp = compile_operator( ... name="FlipOp", ... cpp_code=cpp_code, ... base_class="SelfAdjointOperator", ... constructor_args=[("size_t", "reg_id")] ... ) >>> >>> # Create an instance >>> op = FlipOp(reg_id=0) >>> print(repr(op)) # FlipOp(reg_id=0)
Note
Compiled libraries are cached by code hash to avoid redundant compilation.
ABI compatibility issues may exist on Windows (MSVC vs MinGW).
The C++ class name must match the Python name parameter.
State access inside operators: s.get(reg_id).value gets the value, s.amplitude gets the amplitude.
See also
get_cache_info: Query the compilation cache status. clear_cache: Clear the compilation cache. CompilerConfig: Advanced compiler configuration.
- PySparQ.pysparq.dynamic_operator.compute_code_hash(cpp_code: str, class_name: str, config: CompilerConfig) str[source]¶
Compute the code hash used for caching
The hash covers: code content, class name, compiler version, and configuration
- Parameters:
cpp_code – User C++ code
class_name – Operator class name
config – Compiler configuration
- Returns:
A 16-character hexadecimal hash string
- PySparQ.pysparq.dynamic_operator.create_operator_class(name: str, lib_path: str, base_class: str = 'BaseOperator', constructor_args: List[Tuple[str, str]] = None) Type[source]¶
Create a dynamic operator Python class
- Parameters:
name – Operator class name
lib_path – Dynamic library path
base_class – Base class name (“BaseOperator” or “SelfAdjointOperator”)
constructor_args – List of constructor arguments [(type, name), …]
- Returns:
The dynamically created operator class
- PySparQ.pysparq.dynamic_operator.find_project_root() pathlib.Path | None[source]¶
Locate the project root directory or the installed package directory
For an installed package, the directory layout is: - site-packages/pysparq/ (Python package) - site-packages/include/ (headers, including basic_components.h)
For a source checkout (the SparQSim repository): - The project root contains extern/qram-simulator/ (C++ core submodule) and PySparQ/
- Returns:
The project root path or the installed package directory; None if not found
- PySparQ.pysparq.dynamic_operator.format_compile_error(stderr: str, source_path: str) str[source]¶
Format compiler error output
Simplifies file paths
Highlights error lines
Extracts the key error information
- Parameters:
stderr – Compiler standard error output
source_path – Source file path
- Returns:
The formatted error message
- PySparQ.pysparq.dynamic_operator.generate_cpp_source(cpp_code: str, class_name: str, ctor_params: str = '', ctor_args: str = '', config: CompilerConfig | None = None) str[source]¶
Generate the complete C++ source file
- Parameters:
cpp_code – User-provided C++ code (containing the class definition)
class_name – Operator class name
ctor_params – Constructor parameter declarations (e.g. “int n, double theta”)
ctor_args – Constructor call arguments (e.g. “n, theta”)
config – Compiler configuration (provides the template)
- Returns:
The complete C++ source code string
- PySparQ.pysparq.dynamic_operator.get_cache_info(cache_dir: str | None = None) dict[source]¶
Get cache information
- Parameters:
cache_dir – Cache directory
- Returns:
A dictionary with cache statistics
- PySparQ.pysparq.dynamic_operator.quick_compile(class_code: str, class_name: str, verbose: bool = False) str[source]¶
Quickly compile C++ operator code
- Parameters:
class_code – C++ code containing the class definition
class_name – Class name
verbose – Whether to print verbose logs
- Returns:
The shared library file path