kaiwu.preprocess._bound 源代码

"""
模块: dynamic_range

功能: 估计Ising模型的上下界
"""

import numpy as np
from kaiwu.classical import SimulatedAnnealingOptimizer
from kaiwu.preprocess._utils import _partial_assignment
from kaiwu.license import track_data


[文档] @track_data() def lower_bound_parameters(ising_mat): """所有系数绝对值的和取负,确定Ising模型哈密顿量的下界 Args: ising_mat (np.ndarray): Ising矩阵 Returns: float: 哈密顿量的下界 Examples: >>> import numpy as np >>> import kaiwu as kw >>> mat = np.array([[0, 18, -12], ... [18, 0, 1], ... [-12, 1, 0]]) >>> lb = kw.preprocess.lower_bound_parameters(mat) >>> lb np.int64(-62) """ return _lower_bound_parameters(ising_mat)
def _lower_bound_parameters(ising_mat): """所有系数绝对值的和取负,确定Ising模型哈密顿量的下界""" return -np.abs(ising_mat).sum()
[文档] @track_data() def upper_bound_sample(ising_matrix, steps=10): """基于采样估计哈密顿量的上界 Args: ising_matrix (np.ndarray): Ising矩阵 steps (int): 步数 Returns: float: 哈密顿量的上界 Examples: >>> import numpy as np >>> import kaiwu as kw >>> mat = np.array([[0, 18, -12], ... [18, 0, 1], ... [-12, 1, 0]]) >>> ub = kw.preprocess.upper_bound_sample(mat) """ return _upper_bound_sample(ising_matrix, steps=steps)
def _upper_bound_sample(ising_matrix, steps=10): """基于采样估计哈密顿量的上界""" solution = np.random.randint(0, 2, (ising_matrix.shape[0],)) * 2 - 1 min_h = -solution.dot(ising_matrix).dot(solution) for _ in range(steps): solution = np.random.randint(0, 2, (ising_matrix.shape[0],)) * 2 - 1 hamilton = -solution.dot(ising_matrix).dot(solution) min_h = min(min_h, hamilton) return min_h
[文档] @track_data() def upper_bound_simulated_annealing(ising_matrix): """基于模拟退火估计哈密顿量的上界 Args: ising_matrix (np.ndarray): Ising矩阵 Returns: float: 哈密顿量的上界 Examples: >>> import numpy as np >>> import kaiwu as kw >>> mat = np.array([[0, 18, -12], ... [18, 0, 1], ... [-12, 1, 0]]) >>> ub = kw.preprocess.upper_bound_simulated_annealing(mat) """ optimizer = SimulatedAnnealingOptimizer(size_limit=1) solution = optimizer.solve(ising_matrix)[0] return -solution.dot(ising_matrix).dot(solution)
LOWER_BOUND = { # 'roof_dual': lower_bound_roof_dual, "min_sum": _lower_bound_parameters } UPPER_BOUND = { "simulated_annealing": upper_bound_simulated_annealing, "sample": _upper_bound_sample, } def _compute_pre_opt_bounds(ising_matrix, i, j): lower_bound = LOWER_BOUND["min_sum"] upper_bound = UPPER_BOUND["sample"] change_diff = 1e-08 # Define sub-qubos ising_matrix = (ising_matrix + ising_matrix.T) / 2 mat_nn, bias_nn = _partial_assignment(ising_matrix, [i, j], [-1, -1]) mat_np, bias_np = _partial_assignment(ising_matrix, [i, j], [-1, 1]) mat_pn, bias_pn = _partial_assignment(ising_matrix, [i, j], [1, -1]) mat_pp, bias_pp = _partial_assignment(ising_matrix, [i, j], [1, 1]) # compute bounds upper_nn = upper_bound(mat_nn) - bias_nn upper_np = upper_bound(mat_np) - bias_np upper_pn = upper_bound(mat_pn) - bias_pn upper_pp = upper_bound(mat_pp) - bias_pp upper_p = min(upper_nn, upper_pp) upper_n = min(upper_np, upper_pn) lower_nn = lower_bound(mat_nn) - bias_nn lower_np = lower_bound(mat_np) - bias_np lower_pn = lower_bound(mat_pn) - bias_pn lower_pp = lower_bound(mat_pp) - bias_pp lower_p = min(lower_nn, lower_pp) lower_n = min(lower_np, lower_pn) coefficient_upper_bound = ( float("inf") if lower_n > upper_p else (lower_p - upper_n - change_diff) / 2 ) coefficient_lower_bound = ( -float("inf") if lower_p > upper_n else (upper_p - lower_n + change_diff) / 2 ) return coefficient_lower_bound, coefficient_upper_bound if __name__ == "__main__": import doctest doctest.testmod()