kaiwu.core._matrix_converter 源代码

# -*- coding: utf-8 -*-
"""
模块: qubo

功能: QUBO矩阵和Ising矩阵相关转化
"""
from decimal import Decimal
import numpy as np


[文档] def ising_matrix_to_qubo_matrix(ising_mat, remove_linear_bit=True, decimal=False): """Ising矩阵转QUBO矩阵 Args: ising_mat (np.ndarray): Ising矩阵 remove_linear_bit (bool): QUBO转Ising时会增加一个辅助变量表示线性项。是否移除最后一个自旋变量。默认为True。 decimal (bool): 是否使用Decimal进行高精度计算,默认为False。 Returns: tuple: QUBO矩阵和bias - qubo_mat (np.ndarray): QUBO矩阵 - bias (float): QUBO与Ising相差的常数项 Examples: >>> import numpy as np >>> import kaiwu as kw >>> matrix = -np.array([[ 0. , 1. , 0. , 1. , 1. ], ... [ 1. , 0. , 0. , 1., 1. ], ... [ 0. , 0. , 0. , 1., 1. ], ... [ 1. , 1., 1. , 0. , 1. ], ... [ 1. , 1., 1. , 1. , 0. ]]) >>> _qubo_mat, _ = kw.core.ising_matrix_to_qubo_matrix(matrix) >>> _qubo_mat array([[-4., 8., 0., 8.], [-0., -4., 0., 8.], [-0., -0., -0., 8.], [-0., -0., -0., -8.]]) """ if decimal: ising_mat = np.vectorize(str)(ising_mat) ising_mat = np.vectorize(Decimal)(ising_mat) ising_mat = (ising_mat + ising_mat.T) / 2 ising_mat_linear = None if remove_linear_bit: ising_mat_linear = ising_mat[-1, :-1] * 2 ising_mat = ising_mat[:-1, :-1] qubo_mat = ising_mat * 4 diag_vec = -4 * np.sum(ising_mat, axis=0) bias = np.sum(ising_mat) if remove_linear_bit: bias -= np.sum(ising_mat_linear) diag_vec += 2 * ising_mat_linear qubo_mat = np.triu(qubo_mat * 2) np.fill_diagonal(qubo_mat, diag_vec) qubo_mat = np.array(qubo_mat, dtype=np.float64) return -qubo_mat, -float(bias)
[文档] def qubo_matrix_to_ising_matrix(qubo_mat, decimal=False): """QUBO矩阵转Ising矩阵 Args: qubo_mat (np.ndarray): QUBO矩阵 decimal (bool): 是否使用Decimal进行高精度计算,默认为False。 Returns: tuple: Ising矩阵和bias - ising_mat (np.ndarray): Ising矩阵 - bias (float): QUBO与Ising相差的常数项 Examples: >>> import numpy as np >>> import kaiwu as kw >>> matrix = -np.array([[-4., 8., 0., 8.], ... [-0., -4., 0., 8.], ... [-0., -0., -0., 8.], ... [-0., -0., -0., -8.]]) >>> _ising_mat, _ = kw.core.qubo_matrix_to_ising_matrix(matrix) >>> _ising_mat array([[-0., 1., -0., 1., 1.], [ 1., -0., -0., 1., 1.], [-0., -0., -0., 1., 1.], [ 1., 1., 1., -0., 1.], [ 1., 1., 1., 1., -0.]]) """ if decimal: qubo_mat = np.vectorize(str)(qubo_mat) qubo_mat = np.vectorize(Decimal)(qubo_mat) ising_size = qubo_mat.shape[0] + 1 ising_mat = np.zeros((ising_size, ising_size)) qubo_mat = (qubo_mat + qubo_mat.T) / 8 qubo_div_4_diagoal = np.diagonal(qubo_mat).copy() qubo_div_4 = qubo_mat np.fill_diagonal(qubo_div_4, 0) ising_mat[:-1, :-1] = qubo_div_4 ising_mat[-1, :-1] = np.sum(qubo_div_4, axis=0) + qubo_div_4_diagoal ising_mat[:-1, -1] = np.sum(qubo_div_4, axis=0) + qubo_div_4_diagoal bias = np.sum(qubo_div_4) + np.sum(qubo_div_4_diagoal) * 2 ising_mat = np.array(ising_mat, dtype=np.float64) return -ising_mat, float(bias)
if __name__ == "__main__": import doctest doctest.testmod()