File size: 3,994 Bytes
eef9104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// *******************************************************************************
// Copyright (c) 2026 Ahmad Ali Parr and others.
//
// This program and the accompanying materials are made available under the
// terms of the CPSC Eclipse Strict Copyleft License, Version 1.0, which is
// available in LICENSES/CPSC-ESCL-1.0.txt, or, at your option, under the
// GNU Affero General Public License, Version 3 only, which is available in
// LICENSES/AGPL-3.0.txt. Both options are strict copyleft. There is no
// classpath exception and no permissive relicensing.
//
// SPDX-License-Identifier: LicenseRef-CPSC-ESCL-1.0 OR AGPL-3.0-only
// *******************************************************************************

namespace ConservationPreservingScattering {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Arrays;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Convert;

    /// Ising bond orbit. Calls the ZZ axiom on every cyclic image.
    operation ApplyZZRing(register : Qubit[], angle : Double) : Unit is Adj + Ctl {
        let n = Length(register);
        for i in 0 .. n - 1 {
            Axiom_ApplyZZ(register[i], register[(i + 1) % n], angle);
        }
    }

    /// Full transverse orbit. Legal only as a spin-flip schedule, not as one site.
    operation ApplyTransverseField(register : Qubit[], angle : Double) : Unit is Adj + Ctl {
        for q in register {
            Axiom_ApplyFlip(q, angle);
        }
    }

    operation RequireAdmitted(admitted : Bool, reason : String) : Unit {
        if not admitted {
            fail $"CPSC rejected the schedule: {reason}";
        }
    }

    /// λ = 0. Bonds only. Magnetization is the active invariant.
    operation IsingEvolution(register : Qubit[], steps : Int, dt : Double, j : Double) : Unit is Adj + Ctl {
        let schedule = Lemma_BondOrbit(Length(register));
        RequireAdmitted(Lemma_AllAdmitted(0, schedule), "ising ring");
        for _ in 1 .. steps {
            Lemma_Interpret(register, 0, schedule, j * dt);
        }
    }

    /// λ ≠ 0. Bond orbit plus transverse orbit. ∏ X is the active invariant.
    operation SpinFlipEvolution(
        register : Qubit[],
        steps : Int,
        dt : Double,
        j : Double,
        lam : Double
    ) : Unit is Adj + Ctl {
        let n = Length(register);
        let bonds = Lemma_BondOrbit(n);
        let field = Lemma_TransverseOrbit(n);
        RequireAdmitted(Lemma_AllAdmitted(1, bonds + field), "spin-flip orbit");
        for _ in 1 .. steps {
            Lemma_Interpret(register, 1, bonds, j * dt);
            Lemma_Interpret(register, 1, field, lam * dt);
        }
    }

    /// Refused schedule. Present so a host can see the lemma fail closed.
    operation RejectedIsingFlip(register : Qubit[], site : Int, angle : Double) : Unit is Adj + Ctl {
        let bad = [TransverseFlip(site)];
        RequireAdmitted(Lemma_AllAdmitted(0, bad), "single X breaks Ising magnetization");
        Lemma_Interpret(register, 0, bad, angle);
    }

    operation RejectedSpinFlipZ(register : Qubit[], site : Int, angle : Double) : Unit is Adj + Ctl {
        let bad = [LoneZ(site)];
        RequireAdmitted(Lemma_AllAdmitted(1, bad), "lone Z breaks prod X");
        Lemma_Interpret(register, 1, bad, angle);
    }

    /// Diagnostic, not a compiler filter.
    operation MeasureZParity(register : Qubit[]) : Int {
        mutable parity = 0;
        for q in register {
            if M(q) == One {
                set parity = (parity + 1) % 2;
            }
        }
        return parity;
    }

    /// Diagnostic for the spin-flip sector: measure every qubit in X and return the parity.
    operation MeasureXParity(register : Qubit[]) : Int {
        mutable parity = 0;
        for q in register {
            H(q);
            if M(q) == One {
                set parity = (parity + 1) % 2;
            }
        }
        return parity;
    }
}