Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions analysis/config_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self):
self.max_bosons_per_state = None
def _only_once(self):
if self.source is not None:
print("Already set Hamiltonian source to {self.source}.")
logger.error(f"Already set Hamiltonian source to {self.source}.")
assert self.source is None
def load_second_quantization(self,
filename,
Expand Down Expand Up @@ -118,7 +118,7 @@ def __init__(self):
self.method = None
def _only_once(self):
if self.method is not None:
print("Already set unitary method to {self.method}.")
logger.error(f"Already set unitary method to {self.method}.")
assert self.method is None
def encode_ramped_trotter(self, **kwargs):
self._only_once()
Expand Down Expand Up @@ -538,7 +538,7 @@ def _format_results(self, obj, indent=0, max_line_length=100):

def show_results(self):
formatted = self._format_results(self.results, indent=0)
logger.warning(f"results:\n{formatted}")
logger.results(f"results:\n{formatted}")

def _filter_for_toml(self, obj):
"""Recursively filter out numpy arrays and other non-serializable objects from results."""
Expand Down
2 changes: 1 addition & 1 deletion analysis/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def run():
state.show_results()
state.save_summary()

logger.warning("Analysis complete.")
logger.results("Analysis complete.")

# =================================================================================================

Expand Down
2 changes: 1 addition & 1 deletion analysis/error_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def _compute_state_dependent_errors(exact_unitary_matrix, approx_unitary_matrix,
try:
initial_state = load_state(state_file)
except Exception as e:
logger.error(f"ERROR: Failed to load state from {state_file}: {e}")
logger.error(f"Failed to load state from {state_file}: {e}")
raise

# Apply exact time evolution operator: U_exact |ψ⟩
Expand Down
6 changes: 3 additions & 3 deletions analysis/matrix_eigendecomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def compute_unitary_matrix(bloq):
try:
return bloq.tensor_contract()
except Exception as e:
logger.info(
f"ERROR: Failed to compute unitary matrix: {e}\n"
logger.error(
f"Failed to compute unitary matrix: {e}\n"
"This may indicate a bug in the bloq's tensor_contract() implementation."
)
raise
Expand Down Expand Up @@ -114,7 +114,7 @@ def output_unitary_matrix(filename, unitary_matrix) -> dict:
logger.verbose(f"Matrix Frobenius norm: {matrix_norm:.6e}")
logger.verbose(f"Unitarity error ||U†U - I||_F: {unitarity_error:.6e}")
except Exception as e:
logger.info(f"WARNING: Could not compute unitarity check: {e}")
logger.warning(f"Could not compute unitarity check: {e}")
matrix_norm = None
unitarity_error = None

Expand Down
4 changes: 2 additions & 2 deletions analysis/numerical_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def numerical_simulation(
try:
initial_state = load_state(input_file)
except Exception as e:
logger.info(f"ERROR: Failed to load state from {input_file}: {e}")
logger.error(f"Failed to load state from {input_file}: {e}")
raise

# Validate dimensions
Expand Down Expand Up @@ -82,7 +82,7 @@ def numerical_simulation(
try:
save_state(output_file, final_state)
except Exception as e:
logger.info(f"ERROR: Failed to save state to {output_file}: {e}")
logger.error(f"Failed to save state to {output_file}: {e}")
raise

logger.info(f" Simulation complete: {input_file} -> {output_file}")
Expand Down
6 changes: 0 additions & 6 deletions analysis/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,6 @@ def _apply_energy_shift(self, eigenvalues: np.ndarray, operator_type: str) -> np
return eigenvalues + self.energy_shift
else: # time_evolution
phase_factor = np.exp(-1j * self.energy_shift * self.tevol_hbar)
print(f"phase factor = {phase_factor}")
print(f"energy shift = {self.energy_shift}")
print(f"time step / hbar = {self.tevol_hbar}")
return phase_factor * eigenvalues

def _remove_energy_shift(self, eigenvalues: np.ndarray, operator_type: str) -> np.ndarray:
Expand All @@ -456,7 +453,4 @@ def _remove_energy_shift(self, eigenvalues: np.ndarray, operator_type: str) -> n
return eigenvalues - self.energy_shift
else: # time_evolution
phase_factor = np.exp(1j * self.energy_shift * self.tevol_hbar)
print(f"phase factor = {phase_factor}")
print(f"energy shift = {self.energy_shift}")
print(f"time step / hbar = {self.tevol_hbar}")
return phase_factor * eigenvalues
9 changes: 6 additions & 3 deletions analysis/trotter_coefficients.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
For production use, prefer trotter_coefficients_fast.py which is 100-150x faster.
"""

import logging
import time
import numpy as np
import math

logger = logging.getLogger(__name__)

# --------------------------------------------------
# Helper functions for Pauli string arithmetic
# --------------------------------------------------
Expand Down Expand Up @@ -163,7 +166,7 @@ def trotter_error_estimator(pauli_terms, time_limit, batch_size=100):
break
total_C1 = N * (N - 1)/2 # Total number of distinct pairs (i < j)
C1_est = C1_sum * (total_C1 / samples_C1) if samples_C1 > 0 else 0.0
print(f" C1: {samples_C1} samples")
logger.debug(f"C1: {samples_C1} samples")

# ---------------------------
# Estimate C21 = sum_{k<j, k<i} ||[H_i, [H_j, H_k]]||
Expand Down Expand Up @@ -196,7 +199,7 @@ def trotter_error_estimator(pauli_terms, time_limit, batch_size=100):
# Total number of valid triples: for each k, there are C(N-k-1, 2) choices of (i,j).
total_C21 = sum(math.comb(N - k - 1, 2) for k in range(N - 1))
C21_est = C21_sum * (total_C21 / samples_C21) if samples_C21 > 0 else 0.0
print(f" C21: {samples_C21} samples")
logger.debug(f"C21: {samples_C21} samples")

# ---------------------------
# Estimate C22 = sum_{k<j} ||[H_k, [H_k, H_j]]||
Expand Down Expand Up @@ -224,7 +227,7 @@ def trotter_error_estimator(pauli_terms, time_limit, batch_size=100):
break
total_C22 = N * (N - 1) / 2 # Total number of (k, j) pairs with k < j
C22_est = C22_sum * (total_C22 / samples_C22) if samples_C22 > 0 else 0.0
print(f" C22: {samples_C22} samples")
logger.debug(f"C22: {samples_C22} samples")

# ---------------------------
# Final output
Expand Down
6 changes: 0 additions & 6 deletions analysis/unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ def __init__(self, hamiltonian, prepare_type=None, probability_eps=0.002, **kwar
n_terms = len(pauli_terms)
n_tot = 2**(int(np.ceil(np.log2(n_terms))))
n_pad = n_tot - n_terms
# print(f"-- n_terms={n_terms}")
# print(f"-- n_tot={n_tot}")
# for i in range(n_terms):
# print(f"-- getTerms[{i}]={pauli_terms[i]}")

alphas = [np.sqrt(np.abs(t.coefficient)) for t in pauli_terms]
alpha = np.sum([a**2 for a in alphas])
# print(f"-- alpha={alpha}")
alphas_scaled = [a/np.sqrt(alpha) for a in alphas]
alphas_scaled.extend([0.0 for i in range(n_pad)])
# print(f"-- alphas_scaled={alphas_scaled}")

selection_bitsize = int(np.ceil(np.log2(n_tot)))

Expand Down
51 changes: 29 additions & 22 deletions common/logging_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,43 @@
from typing import Optional


# Custom log level between INFO and DEBUG
VERBOSE = 25 # logging.INFO=20, logging.WARNING=30
# Custom log levels
# Lower values = more verbose in Python logging
VERBOSE = 15 # Between DEBUG (10) and INFO (20)
RESULTS = 45 # Between ERROR (40) and CRITICAL (50) - for critical output that should almost always be shown


def add_verbose_level():
def add_custom_levels():
"""
Add VERBOSE log level to logging module.
Add custom log levels to logging module.

This creates a new log level between INFO and WARNING for
moderately detailed logging that's more than INFO but not as
verbose as DEBUG.
VERBOSE: Between DEBUG and INFO for moderately detailed logging.
RESULTS: Between ERROR and CRITICAL for critical output (results, completion)
that should be shown unless user explicitly sets level to CRITICAL.
"""
# Only add if not already present
if hasattr(logging, 'VERBOSE'):
return
# Add VERBOSE level
if not hasattr(logging, 'VERBOSE'):
logging.addLevelName(VERBOSE, "VERBOSE")

logging.addLevelName(VERBOSE, "VERBOSE")
def verbose(self, message, *args, **kwargs):
if self.isEnabledFor(VERBOSE):
self._log(VERBOSE, message, args, **kwargs)

def verbose(self, message, *args, **kwargs):
if self.isEnabledFor(VERBOSE):
self._log(VERBOSE, message, args, **kwargs)
logging.Logger.verbose = verbose
logging.verbose = lambda msg, *args, **kwargs: logging.log(VERBOSE, msg, *args, **kwargs)
logging.VERBOSE = VERBOSE

# Add verbose() method to Logger class
logging.Logger.verbose = verbose
# Add RESULTS level
if not hasattr(logging, 'RESULTS'):
logging.addLevelName(RESULTS, "RESULTS")

# Add module-level verbose() function
logging.verbose = lambda msg, *args, **kwargs: logging.log(VERBOSE, msg, *args, **kwargs)
def results(self, message, *args, **kwargs):
if self.isEnabledFor(RESULTS):
self._log(RESULTS, message, args, **kwargs)

# Add VERBOSE constant
logging.VERBOSE = VERBOSE
logging.Logger.results = results
logging.results = lambda msg, *args, **kwargs: logging.log(RESULTS, msg, *args, **kwargs)
logging.RESULTS = RESULTS


def configure_logging(
Expand Down Expand Up @@ -89,8 +96,8 @@ def configure_logging(
>>> logger = logging.getLogger(__name__)
>>> logger.info("Application started")
"""
# Add custom VERBOSE level
add_verbose_level()
# Add custom levels (VERBOSE and RESULTS)
add_custom_levels()

# Parse level string
level_map = {
Expand Down