microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/paulimer/src/pauli/operators.rs

222lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4// fn is_sorted<Items: Iterator<Item = usize>>(items: Items) -> bool {
5// let vec_items: Vec<usize> = items.collect();
6// equal(sorted(vec_items.iter()), vec_items.iter())
7// }
8
9// MulAssign for PauliUnitary and PauliUnitaryAbs with rhs that implements Pauli or PauliAbs
10
11use std::ops::{Mul, MulAssign, Neg};
12
13use crate::NeutralElement;
14
15use super::{
16 generic::{PhaseExponent, PhaseExponentMutable},
17 Pauli, PauliBinaryOps, PauliBits, PauliMutable, PauliNeutralElement, PauliUnitary,
18 PauliUnitaryProjective,
19};
20
21impl<BitsLeft, PhaseLeft, PauliRight: Pauli<PhaseExponentValue = u8>> MulAssign<&PauliRight>
22 for PauliUnitary<BitsLeft, PhaseLeft>
23where
24 PauliUnitary<BitsLeft, PhaseLeft>: PauliBinaryOps<PauliRight>,
25 BitsLeft: PauliBits,
26 PhaseLeft: PhaseExponent,
27{
28 fn mul_assign(&mut self, other: &PauliRight) {
29 self.mul_assign_right(other);
30 }
31}
32
33impl<BitsLeft, PauliRight: Pauli<PhaseExponentValue = u8>> MulAssign<&PauliRight>
34 for PauliUnitaryProjective<BitsLeft>
35where
36 PauliUnitaryProjective<BitsLeft>: PauliBinaryOps<PauliRight>,
37 BitsLeft: PauliBits,
38{
39 fn mul_assign(&mut self, other: &PauliRight) {
40 self.mul_assign_right(other);
41 }
42}
43
44pub struct Phase<Exponent: PhaseExponent>(Exponent);
45
46impl<Exponent: PhaseExponent> Phase<Exponent> {
47 pub fn from_exponent(exponent: Exponent) -> Self {
48 Self(exponent)
49 }
50}
51
52// Multiply an object by a reference on the right, consume the object return multiplication result
53impl<BitsLeft, PhaseLeft, PauliRight: Pauli<PhaseExponentValue = u8>> Mul<&PauliRight>
54 for PauliUnitary<BitsLeft, PhaseLeft>
55where
56 PauliUnitary<BitsLeft, PhaseLeft>: for<'a> MulAssign<&'a PauliRight>,
57 BitsLeft: PauliBits,
58 PhaseLeft: PhaseExponent,
59{
60 type Output = PauliUnitary<BitsLeft, PhaseLeft>;
61
62 fn mul(mut self, other: &PauliRight) -> Self::Output {
63 self *= other;
64 self
65 }
66}
67
68impl<BitsLeft, PauliRight: Pauli<PhaseExponentValue = u8>> Mul<&PauliRight>
69 for PauliUnitaryProjective<BitsLeft>
70where
71 PauliUnitaryProjective<BitsLeft>: for<'a> MulAssign<&'a PauliRight>,
72 BitsLeft: PauliBits,
73{
74 type Output = PauliUnitaryProjective<BitsLeft>;
75
76 fn mul(mut self, other: &PauliRight) -> Self::Output {
77 self *= other;
78 self
79 }
80}
81
82// Multiply an object by a reference on the left, consume the object return multiplication result
83
84impl<BitsLeft, PhaseLeft, PauliRight: Pauli<PhaseExponentValue = u8>> Mul<PauliRight>
85 for &PauliUnitary<BitsLeft, PhaseLeft>
86where
87 PauliRight: PauliBinaryOps<PauliUnitary<BitsLeft, PhaseLeft>>,
88 BitsLeft: PauliBits,
89 PhaseLeft: PhaseExponent,
90{
91 type Output = PauliRight;
92
93 fn mul(self, mut other: PauliRight) -> Self::Output {
94 other.mul_assign_left(self);
95 other
96 }
97}
98
99impl<BitsLeft, PauliRight: Pauli<PhaseExponentValue = ()>> Mul<PauliRight>
100 for &PauliUnitaryProjective<BitsLeft>
101where
102 PauliRight: PauliBinaryOps<PauliUnitaryProjective<BitsLeft>>,
103 BitsLeft: PauliBits,
104{
105 type Output = PauliRight;
106
107 fn mul(self, mut other: PauliRight) -> Self::Output {
108 other.mul_assign_left(self);
109 other
110 }
111}
112
113// Multiplying by a phase
114
115impl<Bits: PauliBits, _Phase: PhaseExponentMutable, Exponent: PhaseExponent>
116 MulAssign<Phase<Exponent>> for PauliUnitary<Bits, _Phase>
117where
118 PauliUnitary<Bits, _Phase>: PauliMutable + Pauli<PhaseExponentValue = u8>,
119{
120 fn mul_assign(&mut self, phase: Phase<Exponent>) {
121 self.add_assign_phase_exp(phase.0.raw_value());
122 }
123}
124
125impl<Bits: PauliBits, _Phase: PhaseExponentMutable, Exponent: PhaseExponent> Mul<Phase<Exponent>>
126 for PauliUnitary<Bits, _Phase>
127where
128 PauliUnitary<Bits, _Phase>: PauliMutable + Pauli<PhaseExponentValue = u8>,
129{
130 type Output = PauliUnitary<Bits, _Phase>;
131
132 fn mul(mut self, phase: Phase<Exponent>) -> Self::Output {
133 self.add_assign_phase_exp(phase.0.raw_value());
134 self
135 }
136}
137
138impl<BitsLeft, PhaseLeft, BitsRight, PhaseRight> Mul<&PauliUnitary<BitsRight, PhaseRight>>
139 for &PauliUnitary<BitsLeft, PhaseLeft>
140where
141 PauliUnitary<BitsLeft, PhaseLeft>: PauliNeutralElement,
142 <PauliUnitary<BitsLeft, PhaseLeft> as NeutralElement>::NeutralElementType:
143 PauliBinaryOps<PauliUnitary<BitsRight, PhaseRight>>,
144 BitsRight: PauliBits,
145 PhaseRight: PhaseExponent,
146 BitsLeft: PauliBits,
147 PhaseLeft: PhaseExponent,
148{
149 type Output = <PauliUnitary<BitsLeft, PhaseLeft> as NeutralElement>::NeutralElementType;
150
151 fn mul(self, other: &PauliUnitary<BitsRight, PhaseRight>) -> Self::Output {
152 let mut res = <PauliUnitary<BitsLeft, PhaseLeft> as NeutralElement>::neutral_element(self);
153 res.assign(self);
154 res.mul_assign_right(other);
155 res
156 }
157}
158
159impl<BitsLeft, BitsRight> Mul<&PauliUnitaryProjective<BitsRight>>
160 for &PauliUnitaryProjective<BitsLeft>
161where
162 PauliUnitaryProjective<BitsLeft>: PauliNeutralElement,
163 <PauliUnitaryProjective<BitsLeft> as NeutralElement>::NeutralElementType:
164 PauliBinaryOps<PauliUnitaryProjective<BitsRight>>,
165 BitsRight: PauliBits,
166 BitsLeft: PauliBits,
167{
168 type Output = <PauliUnitaryProjective<BitsLeft> as NeutralElement>::NeutralElementType;
169
170 fn mul(self, other: &PauliUnitaryProjective<BitsRight>) -> Self::Output {
171 let mut res = <PauliUnitaryProjective<BitsLeft> as NeutralElement>::neutral_element(self);
172 res.assign(self);
173 res.mul_assign_right(other);
174 res
175 }
176}
177
178// negating object consumes it and returns the negation
179impl<Bits: PauliBits, Phase: PhaseExponentMutable> Neg for PauliUnitary<Bits, Phase>
180where
181 PauliUnitary<Bits, Phase>: PauliMutable + Pauli<PhaseExponentValue = u8>,
182{
183 type Output = Self;
184 fn neg(mut self) -> Self::Output {
185 self.add_assign_phase_exp(2u8);
186 self
187 }
188}
189
190impl<Bits: PauliBits> Neg for PauliUnitaryProjective<Bits>
191where
192 PauliUnitaryProjective<Bits>: PauliMutable,
193{
194 type Output = Self;
195 fn neg(self) -> Self::Output {
196 self
197 }
198}
199
200// negating object consumes it and returns the negation
201impl<Bits: PauliBits + Clone, Phase: PhaseExponentMutable + Clone> Neg
202 for &PauliUnitary<Bits, Phase>
203where
204 PauliUnitary<Bits, Phase>: PauliMutable + Pauli<PhaseExponentValue = u8>,
205{
206 type Output = PauliUnitary<Bits, Phase>;
207 fn neg(self) -> Self::Output {
208 let mut res = self.clone();
209 res.add_assign_phase_exp(2u8);
210 res
211 }
212}
213
214impl<Bits: PauliBits + Clone> Neg for &PauliUnitaryProjective<Bits>
215where
216 PauliUnitaryProjective<Bits>: PauliMutable,
217{
218 type Output = PauliUnitaryProjective<Bits>;
219 fn neg(self) -> Self::Output {
220 self.clone()
221 }
222}