Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand logging configuration support in PennyLane, and also target Catalyst #5528

Merged
merged 72 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
6feac37
Add log-rules for catalyst
mlxd Apr 11, 2024
eb0d72e
Update logging with file and syslog supports
mlxd Apr 12, 2024
9bf93c3
Add support for direct modification of log config
mlxd Apr 16, 2024
c997ed7
Add support for log decorator
mlxd Apr 17, 2024
4eb2aa2
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 6, 2024
886a80a
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 8, 2024
ef129d4
Update logging to latest release
mlxd May 8, 2024
f095479
Run sort n lint
mlxd May 8, 2024
83b3a40
Merge branch 'update/logging_rules_catalyst' into update/logging_rule…
mlxd May 8, 2024
1e4a923
Fix format
mlxd May 8, 2024
e721a39
Pylint adhere
mlxd May 8, 2024
3d1e81c
[WIP] Update PennyLane pipeline logging support (#5534)
mlxd May 8, 2024
a463859
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 8, 2024
e0ae2b5
Listen to codefactor
mlxd May 8, 2024
42ee75f
Ensure Windows function doesn't warn on *nix
mlxd May 8, 2024
8f244ca
Merge branch 'update/logging_rules_pennylane' into update/logging_rul…
mlxd May 8, 2024
8a06f02
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 8, 2024
fb64c3d
Disable extraneous warning
mlxd May 8, 2024
ff9d8b7
Merge branch 'update/logging_rules_catalyst' of github.com:PennyLaneA…
mlxd May 8, 2024
447782b
Apply suggestions from code review
mlxd May 17, 2024
23c5049
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 17, 2024
1c46ff1
Update logging tests for new structure
mlxd May 17, 2024
027fa1e
Update according to reviews
mlxd May 17, 2024
cccc436
Update logging docs
mlxd May 17, 2024
50b764d
Remove unused variable
mlxd May 17, 2024
42a1f21
Spellcheck
mlxd May 17, 2024
3e7ca34
Be more explicit about logging levels in tests
mlxd May 17, 2024
608fa73
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 17, 2024
0205a4d
Forbid pointless warning
mlxd May 17, 2024
e811891
Silence Pylints verbose complaint
mlxd May 17, 2024
a638f36
Silence Pylints verbose complaint +1
mlxd May 17, 2024
1a6c3a7
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 21, 2024
9507454
Update doc/development/guide/logging.rst
mlxd May 23, 2024
c45f765
Update doc/development/guide/logging.rst
mlxd May 23, 2024
76d49a8
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 23, 2024
a8a0c53
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 23, 2024
b8c9a23
Indent and enumerate sphinx list
mlxd May 23, 2024
c1f5b9a
Fix indentation issue
mlxd May 23, 2024
1c36a2b
Update tests/logging/test_logging_autograd.py
mlxd May 24, 2024
bac25c5
Update tests/logging/test_logging_autograd.py
mlxd May 24, 2024
b747d14
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 24, 2024
131b5e9
Add context-manager around test logging
mlxd May 24, 2024
f4ab67b
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 24, 2024
f4dd8a2
Update log rule context manager
mlxd May 24, 2024
b3911d6
Merge branch 'update/logging_rules_catalyst' of github.com:PennyLaneA…
mlxd May 24, 2024
793f150
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 24, 2024
fab9d81
Update config
mlxd May 24, 2024
a9b714e
Explicit remove all loggers from test config after run
mlxd May 24, 2024
a56c174
Update logging to newer format across devices
mlxd May 27, 2024
f25d502
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 27, 2024
40e06ba
Update changelog
mlxd May 27, 2024
6a14487
Merge branch 'update/logging_rules_catalyst' of github.com:PennyLaneA…
mlxd May 27, 2024
811b875
Remove unneeded packages
mlxd May 27, 2024
5fd081c
Remove redundant except
mlxd May 27, 2024
b898b0f
Update logging config
mlxd May 27, 2024
1b5a2fd
Add qutrit mixed log tests to logging module tests
mlxd May 27, 2024
c570cac
Update log tests
mlxd May 28, 2024
f298581
Remove redundant functions in tests
mlxd May 28, 2024
66a5942
Remove unused import
mlxd May 28, 2024
29bad9e
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 28, 2024
ecbe2e2
Update doc/development/guide/logging.rst
mlxd May 28, 2024
42c2511
Update doc/development/guide/logging.rst
mlxd May 28, 2024
44589ad
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 29, 2024
3f3e339
Update pennylane/logging/configuration.py
mlxd May 29, 2024
81dc6e8
Update pennylane/logging/configuration.py
mlxd May 29, 2024
cda291c
Add parenthesis for safety to env var check
mlxd May 29, 2024
25910f6
Disable pylint incorrect parenthesis error
mlxd May 29, 2024
77044d8
Update review feedback
mlxd May 29, 2024
2922292
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 29, 2024
400428d
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 30, 2024
c062986
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 30, 2024
3f44012
Merge branch 'master' into update/logging_rules_catalyst
mlxd May 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions doc/development/guide/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,36 @@ To add logging support to components of PennyLane, we must define a module logge

which will be used within the given module, and track directories,
filenames and function names, as we have defined the appropriate types
within the formatter configuration (see :class:`pennylane.logging.DefaultFormatter`). With the logger defined, we can selectively add to the logger by if-else statements, which compare the given module’s log-level to any log record
message it receives. This step is not necessary, as the message will
only output if the level is enabled, though if an expensive function
call is required to build the string for the log-message, it can be
faster to perform this check:
within the formatter configuration (see :class:`pennylane.logging.DefaultFormatter`). With the logger defined, we can selectively add to the logger via two methods:

.. code:: python
#. Using decorators on the required functions and methods in a given module:

.. code:: python

# debug_logger can be used to decorate any method or free function
# debug_logger_init can be used to decorate class __init__ methods.
from pennylane.logging import debug_logger, debug_logger_init

@debug_logger
def my_func(arg1, arg2):
return arg1 + arg2

if logger.isEnabledFor(logging.DEBUG):
logger.debug(
"""Entry with args=(arg_name_1=%s, arg_name_2=%s, ..., arg_name_n=%s)""",
arg_name_1, arg_name_2, ..., arg_name_n,
)
#. Explicitly by if-else statements, which compare the given module’s log-level to any log record message it receives. This step is not necessary, as the message will
only output if the level is enabled, though if an expensive function
call is required to build the string for the log-message, it can be
faster to perform this check:

The above line can be added below the function/method entry point,
and the provided arguments can be used to populate the log message. This
allows us a way to track the inputs and calls through the stack in the
order they are executed, as is the basis for following a trail of
.. code:: python

if logger.isEnabledFor(logging.DEBUG):
logger.debug(
"""Entry with args=(arg_name_1=%s, arg_name_2=%s, ..., arg_name_n=%s)""",
arg_name_1, arg_name_2, ..., arg_name_n,
)

Both versions provide similar functionality, though the explicit logger call allows more custom message-formatting, such as expanding functions as string representation, filtering of data, and other useful processing for a valid record.

These logging options allow us a way to track the inputs and calls through the stack in the order they are executed, as is the basis for following a trail of
execution as needed.

All debug log-statements currently added to the PennyLane execution
Expand Down Expand Up @@ -82,6 +94,8 @@ messages based on some criteria, we can add these to the respective
handlers. As an example, we can go through the configuration file and
explore the options.

For ease-of-development, the function :func:`pennylane.logging.edit_system_config` opens an editor (if the ``EDITOR`` environment variable is set), or a viewer of the existing file configuration, which can be used to modify the existing options.

Modifying the configuration options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
3 changes: 3 additions & 0 deletions doc/introduction/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ outputs to the default configured handler, which is directed to the standard out
level = "DEBUG" # Set to TRACE for highest verbosity
propagate = false


Viewing the existing logging configuration file is possible by calling the :func:`pennylane.logging.edit_system_config` function which will open the file in an existing browser or editor window.

For more info on the customization of the logging options, please see the logging development guide at :doc:`/development/guide/logging`, and the `Python logging documentation <https://docs.python.org/3/library/logging.html>`_.
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

<h3>Improvements 🛠</h3>

* Logging now allows for an easier opt-in across the stack, and also extends control support to `catalyst`.
[(#5528)](https://github.com/PennyLaneAI/pennylane/pull/5528).

* `ctrl` now works with tuple-valued `control_values` when applied to any already controlled operation.
[(#5725)](https://github.com/PennyLaneAI/pennylane/pull/5725)

Expand Down
12 changes: 12 additions & 0 deletions pennylane/devices/default_mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import functools
import itertools
import logging
from collections import defaultdict
from string import ascii_letters as ABC

Expand All @@ -29,6 +30,7 @@
import pennylane as qml
import pennylane.math as qnp
from pennylane import BasisState, DeviceError, QubitDensityMatrix, QubitDevice, Snapshot, StatePrep
from pennylane.logging import debug_logger, debug_logger_init
from pennylane.measurements import (
CountsMP,
DensityMatrixMP,
Expand All @@ -47,6 +49,9 @@

from .._version import __version__

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

ABC_ARRAY = np.array(list(ABC))
tolerance = 1e-10

Expand Down Expand Up @@ -181,6 +186,7 @@ def _asarray(array, dtype=None):
res = qnp.cast(array, dtype=dtype)
return res

@debug_logger_init
def __init__(
self,
wires,
Expand Down Expand Up @@ -252,6 +258,7 @@ def state(self):
# User obtains state as a matrix
return qnp.reshape(self._pre_rotated_state, (dim, dim))

@debug_logger
def density_matrix(self, wires):
"""Returns the reduced density matrix over the given wires.

Expand All @@ -266,19 +273,22 @@ def density_matrix(self, wires):
wires = self.map_wires(wires)
return qml.math.reduce_dm(state, indices=wires, c_dtype=self.C_DTYPE)

@debug_logger
def purity(self, mp, **kwargs): # pylint: disable=unused-argument
"""Returns the purity of the final state"""
state = getattr(self, "state", None)
wires = self.map_wires(mp.wires)
return qml.math.purity(state, indices=wires, c_dtype=self.C_DTYPE)

@debug_logger
def reset(self):
"""Resets the device"""
super().reset()

self._state = self._create_basis_state(0)
self._pre_rotated_state = self._state

@debug_logger
def analytic_probability(self, wires=None):
if self._state is None:
return None
Expand Down Expand Up @@ -706,6 +716,7 @@ def _apply_operation(self, operation):

# pylint: disable=arguments-differ

@debug_logger
def execute(self, circuit, **kwargs):
"""Execute a queue of quantum operations on the device and then
measure the given observables.
Expand Down Expand Up @@ -760,6 +771,7 @@ def execute(self, circuit, **kwargs):
self.measured_wires = qml.wires.Wires.all_wires(wires_list)
return super().execute(circuit, **kwargs)

@debug_logger
def apply(self, operations, rotations=None, **kwargs):
rotations = rotations or []

Expand Down
22 changes: 13 additions & 9 deletions pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"""

import concurrent.futures
import inspect
import logging
from dataclasses import replace
from functools import partial
Expand All @@ -26,6 +25,7 @@
import numpy as np

import pennylane as qml
from pennylane.logging import debug_logger, debug_logger_init
from pennylane.measurements.mid_measure import MidMeasureMP
from pennylane.ops.op_math.condition import Conditional
from pennylane.tape import QuantumTape
Expand Down Expand Up @@ -419,6 +419,7 @@ def reset_prng_key(self):
"""

# pylint:disable = too-many-arguments
@debug_logger_init
def __init__(
self,
wires=None,
Expand All @@ -439,6 +440,7 @@ def __init__(
self._rng = np.random.default_rng(seed)
self._debugger = None

@debug_logger
def supports_derivatives(
self,
execution_config: Optional[ExecutionConfig] = None,
Expand Down Expand Up @@ -475,6 +477,7 @@ def supports_derivatives(
return _supports_adjoint(circuit=circuit)
return False

@debug_logger
def preprocess(
self,
execution_config: ExecutionConfig = DefaultExecutionConfig,
Expand Down Expand Up @@ -566,20 +569,13 @@ def _setup_execution_config(self, execution_config: ExecutionConfig) -> Executio
updated_values["device_options"][option] = getattr(self, f"_{option}")
return replace(execution_config, **updated_values)

@debug_logger
def execute(
self,
circuits: QuantumTape_or_Batch,
execution_config: ExecutionConfig = DefaultExecutionConfig,
) -> Result_or_ResultBatch:
self.reset_prng_key()
if logger.isEnabledFor(logging.DEBUG):
logger.debug(
"""Entry with args=(circuits=%s) called by=%s""",
circuits,
"::L".join(
str(i) for i in inspect.getouterframes(inspect.currentframe(), 2)[1][1:3]
),
)

max_workers = execution_config.device_options.get("max_workers", self._max_workers)
self._state_cache = {} if execution_config.use_device_jacobian_product else None
Expand Down Expand Up @@ -618,6 +614,7 @@ def execute(

return results

@debug_logger
def compute_derivatives(
self,
circuits: QuantumTape_or_Batch,
Expand All @@ -637,6 +634,7 @@ def compute_derivatives(

return res

@debug_logger
def execute_and_compute_derivatives(
self,
circuits: QuantumTape_or_Batch,
Expand All @@ -659,6 +657,7 @@ def execute_and_compute_derivatives(

return tuple(zip(*results))

@debug_logger
def supports_jvp(
self,
execution_config: Optional[ExecutionConfig] = None,
Expand All @@ -678,6 +677,7 @@ def supports_jvp(
"""
return self.supports_derivatives(execution_config, circuit)

@debug_logger
def compute_jvp(
self,
circuits: QuantumTape_or_Batch,
Expand All @@ -697,6 +697,7 @@ def compute_jvp(

return res

@debug_logger
def execute_and_compute_jvp(
self,
circuits: QuantumTape_or_Batch,
Expand Down Expand Up @@ -724,6 +725,7 @@ def execute_and_compute_jvp(

return tuple(zip(*results))

@debug_logger
def supports_vjp(
self,
execution_config: Optional[ExecutionConfig] = None,
Expand All @@ -743,6 +745,7 @@ def supports_vjp(
"""
return self.supports_derivatives(execution_config, circuit)

@debug_logger
def compute_vjp(
self,
circuits: QuantumTape_or_Batch,
Expand Down Expand Up @@ -810,6 +813,7 @@ def _state(circuit):

return res

@debug_logger
def execute_and_compute_vjp(
self,
circuits: QuantumTape_or_Batch,
Expand Down
10 changes: 10 additions & 0 deletions pennylane/devices/default_qutrit.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@
simulation of qutrit-based quantum computing.
"""
import functools
import logging

import numpy as np

import pennylane as qml # pylint: disable=unused-import
from pennylane import DeviceError, QutritBasisState, QutritDevice
from pennylane.devices.default_qubit_legacy import _get_slice
from pennylane.logging import debug_logger, debug_logger_init
from pennylane.wires import WireError

from .._version import __version__

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

# tolerance for numerical errors
tolerance = 1e-10

Expand Down Expand Up @@ -118,6 +123,7 @@ def _asarray(array, dtype=None):
res = qml.math.cast(array, dtype=dtype)
return res

@debug_logger_init
def __init__(
self,
wires,
Expand Down Expand Up @@ -165,6 +171,7 @@ def define_wire_map(self, wires):
wire_map = zip(wires, consecutive_wires)
return dict(wire_map)

@debug_logger
def apply(self, operations, rotations=None, **kwargs): # pylint: disable=arguments-differ
rotations = rotations or []

Expand Down Expand Up @@ -403,6 +410,7 @@ def _create_basis_state(self, index):
def state(self):
return self._flatten(self._pre_rotated_state)

@debug_logger
def density_matrix(self, wires):
"""Returns the reduced density matrix of a given set of wires.

Expand Down Expand Up @@ -460,6 +468,7 @@ def _apply_unitary(self, state, mat, wires):
inv_perm = np.argsort(perm) # argsort gives inverse permutation
return self._transpose(tdot, inv_perm)

@debug_logger
def reset(self):
"""Reset the device"""
super().reset()
Expand All @@ -468,6 +477,7 @@ def reset(self):
self._state = self._create_basis_state(0)
self._pre_rotated_state = self._state

@debug_logger
def analytic_probability(self, wires=None):
if self._state is None:
return None
Expand Down
Loading
Loading