"""""
模块作用：实现Majorana CSS码的距离估计、逻辑算符推导与若干构造器（由线性码/校验矩阵/标准例子）。
"""""
import numpy as np
from extendedstim.Code.LinearCode.LinearCode import LinearCode
from extendedstim.Code.QuantumCode.MajoranaCode import MajoranaCode
from extendedstim.Code.QuantumCode.QuantumCSSCode import QuantumCSSCode
from extendedstim.Physics.MajoranaOperator import MajoranaOperator
from extendedstim.tools.GaloisTools import distance, orthogonalize, occupy


class MajoranaCSSCode(MajoranaCode, QuantumCSSCode):

    # %%  CHAPTER：===构造方法===
    def __init__(self, generators_x, generators_z, physical_number):
        """""
        input.generators_x：X类Majorana稳定子
        input.generators_z：Z类Majorana稳定子
        input.physical_number：费米子位数
        """""
        QuantumCSSCode.__init__(self, generators_x, generators_z, physical_number)

    # %%  CHAPTER：===属性方法===
    ##  SECTION：----求码距----
    @property
    def distance(self):
        """""
        output：int，随机估计（或MIP）
        """""
        return distance(self.check_matrix_x,'mip')

    ##  SECTION：----求码距（x方向）----
    @property
    def distance_x(self):
        """""
        output：int，基于MIP的精确/上界估计
        """""
        return distance(self.check_matrix_x,'mip')

    ##  SECTION：----求码距（z方向）----
    @property
    def distance_z(self):
        """""
        output：int，基于MIP的精确/上界估计
        """""
        return distance(self.check_matrix_z,'mip')

    ##  SECTION：----求逻辑算符----
    @property
    def logical_operators(self)->'list[MajoranaOperator]':
        """""
        output：np.array[MajoranaOperator]，X向和Z向配对拼接
        """""
        _=self._logical_operators_x
        return self._logical_operators_x+self._logical_operators_z

    ##  SECTION：----求逻辑算符（x方向）----
    @property
    def logical_operators_x(self)->'list[MajoranaOperator]':
        """""
        output：np.array[MajoranaOperator]，X向逻辑算符
        """""
        matrix = self.check_matrix_x
        codewords = matrix.null_space()
        independent_null_basis_list = []
        for vec in codewords:
            rank_before = np.linalg.matrix_rank(matrix)
            matrix = np.vstack([matrix, vec])
            if np.linalg.matrix_rank(matrix) == rank_before + 1:
                independent_null_basis_list.append(vec)
        basis_list = orthogonalize(independent_null_basis_list)
        majorana_logical_operators_x = []
        majorana_logical_operators_z = []
        for i in range(len(basis_list)):
            occupy_temp=occupy(basis_list[i])
            temp = MajoranaOperator.HermitianOperatorFromOccupy(occupy_temp,[])
            majorana_logical_operators_x.append(temp)
            temp = MajoranaOperator.HermitianOperatorFromOccupy([],occupy_temp)
            majorana_logical_operators_z.append(temp)
        self._logical_operators_x = majorana_logical_operators_x
        self._logical_operators_z = majorana_logical_operators_z
        return self._logical_operators_x

    ##  SECTION：----求逻辑算符（z方向）----
    @property
    def logical_operators_z(self)->'list[MajoranaOperator]':
        """""
        output：np.array[MajoranaOperator]，Z向逻辑算符
        """""
        _=self._logical_operators_x
        return self._logical_operators_z

    #%%  CHAPTER：===静态方法===
    ##  SECTION：----从校验矩阵构造Majorana CSS code----
    @staticmethod
    def FromCheckMatrix(check_matrix):
        """""
        input.check_matrix：GF(2) (m,2n)
        output：MajoranaCSSCode
        """""
        generators_x = []
        generators_z = []
        for i in range(len(check_matrix)):
            generators_x.append(MajoranaOperator.HermitianOperatorFromVector(check_matrix[i]))
            generators_z.append(MajoranaOperator.HermitianOperatorFromVector(check_matrix[i]))
        physical_number=check_matrix.shape[1]
        return MajoranaCSSCode(generators_x, generators_z, physical_number)

    ##  SECTION：----用一个线性码生成Majorana CSS code----
    @staticmethod
    def FromLinearCode(linear_code):
        """""
        input.linear_code：LinearCode
        output：MajoranaCSSCode
        """""
        assert isinstance(linear_code,LinearCode)
        generators_x = []
        generators_z = []
        check_matrix=linear_code.check_matrix
        for i in range(len(check_matrix)):
            occupy_temp=occupy(check_matrix[i])
            generators_x.append(MajoranaOperator.HermitianOperatorFromOccupy(occupy_temp,[]))
            generators_z.append(MajoranaOperator.HermitianOperatorFromOccupy([],occupy_temp))
        physical_number=check_matrix.shape[1]
        return MajoranaCSSCode(generators_x, generators_z, physical_number)
