"""
模块: SubsystemCode
定义了子系统量子码，也就是可以具有gauge degree of freedom的quantum codes
------------------------------------------------------------------------------------------------
属性：
    SubsystemCode的属性：
        self.code：中心子码
        self.bare_logical_operators：选定的logical operator
-------------------------------------------------------------------------
方法：
    SubsystemCode的方法：
        __init__（魔法方法）：构造一个subsystem code
       logical_operators（属性方法）：返回已经给定的bare logical operators
       distance（属性方法）：返回subsystem code distance
-------------------------------------------------------------------------
例子：
    $S_0=i\\hat X_0\\hat X_1\\hat X_2\\hat X_3$
    $S_1=i\\hat X_1\\hat X_2\\hat X_5\\hat X_6$
    $S_2=i\\hat X_0\\hat X_2\\hat X_4\\hat X_6$
    $S_3=i\\hat Z_0\\hat Z_1\\hat Z_2\\hat Z_3$
    $G=i\\hat Z_1\\hat Z_2\\hat Z_5\\hat Z_6$
    n=7
"""
import copy
from typing import Iterable
from clifforder.Code.QuantumCode import MajoranaCode, PauliCode
from clifforder.Code.Operator import MajoranaOperator, PauliOperator, Operator
from clifforder.Code.tools import mip_distance_caculator


class SubsystemCode:

    ##  SECTION: ----构造函数----
    def __init__(self, code: MajoranaCode | PauliCode, bare_logical_operators: list[MajoranaOperator | PauliOperator]):
        """
        input.code: 中心子码
        input.bare_logical_operators：规定真实的logical operator是哪些
        output: None
        """

        ##  输入检查
        self.code = code
        self.bare_logical_operators = bare_logical_operators


    ##  SECTION: ----获得逻辑算符----
    @property
    def logical_operators(self) -> list[MajoranaOperator | PauliOperator]:
        """
        output: 返回选定的logical operators
        """
        return self.bare_logical_operators


    ##  SECTION: ----获得subsystem code distance----
    @property
    def distance(self) -> int:
        """
        output: 返回subsystem code distance
        """

        return mip_distance_caculator(self.code.check_matrix, Operator.get_matrix(self.logical_operators, self.code.physical_number))


    ##  SECTION：----变换当前的规范----
    def gauge_fix(self, bare_logical_operators: Iterable[MajoranaOperator | PauliOperator]):
        self.bare_logical_operators = bare_logical_operators
