from Circuit.Circuit import Circuit
from Code.QuantumCode.MajoranaCSSCode import MajoranaCSSCode


def MajoranaCSSCode2PhenomenologicalCircuit(code,p_noise,p_measure,cycle_number:int):
    assert isinstance(code,MajoranaCSSCode)
    stabilizers_x=code.generators_x
    stabilizers_z=code.generators_z
    logical_x=code.logical_operators_x
    logical_z=code.logical_operators_z
    logical_occupy=[]
    for i in range(len(logical_x)):
        logical_occupy.append(1j*logical_x[i]@logical_z[i])
    logical_string=[]
    for i in range(len(logical_x)):
        if i!=len(logical_x)-1:
            logical_string.append(logical_z[i]@logical_x[i+1])
        else:
            logical_string.append(logical_z[i+1]@logical_x[0])

    majorana_number=code.physical_number
    stabilizer_number = len(stabilizers_x) + len(stabilizers_z)
    circuit_z = Circuit()
    circuit_z.append("FR", range(majorana_number))

    ##  第一轮测量假设没有噪声，相当于完美的初始化
    for stabilizer in stabilizers_x:
        circuit_z.append("MPP", stabilizer)
    for stabilizer in stabilizers_z:
        circuit_z.append("MPP", stabilizer)

    ##  循环多轮，增加多轮测量错误与量子噪声信道
    for _ in range(cycle_number):
        for i in range(majorana_number):
            circuit_z.append("FDEPOLARIZE1", i, p_noise)

        for stabilizer in stabilizers_x:
            circuit_z.append("MPP", stabilizer,p_measure)
        for stabilizer in stabilizers_z:
            circuit_z.append("MPP", stabilizer,p_measure)

        for i in range(stabilizer_number):
            circuit_z.append("DETECTOR", [-i - 1, -i - stabilizer_number-1])

    ##  最后一轮测量假设是没有噪声的
    for stabilizer in stabilizers_x:
        circuit_z.append("MPP", stabilizer)
    for stabilizer in stabilizers_z:
        circuit_z.append("MPP", stabilizer)

    for i in range(stabilizer_number):
        circuit_z.append("DETECTOR", [-i - 1, -i - stabilizer_number - 1])

    ##  测量逻辑算符
    circuit_x=circuit_z.copy()
    circuit_z.append("MPP",logical_occupy)
    for i in range(len(logical_occupy)):
        circuit_z.append("OBSERVABLE_INCLUDE", [-i])
    circuit_x.append("MPP",logical_string)
    for i in range(len(logical_string)):
        circuit_x.append("OBSERVABLE_INCLUDE", [-i])
    return circuit_x, circuit_z


