在下文中,我们将回顾一些针对 Codeforces 上的 Microsoft Q# 夏季 2018 和冬季 2019 编码竞赛的 Silq 解决方案。 针对 Q# 程序员的详细解决方案可在 2018 年和 2019 年获得。
# 生成零态和基态的叠加态
任务的原始来源:问题 A2(2018)
给定经典位 且 ,返回态 ,其中 代表使用 位。
# 解决方案
以下解决方案特别有用
- 矢量(
𝔹^n
) - 哈达玛变换(
H
) - 内联条件(
if-then-else
) - 类型注释(
0:𝔹
) - 类型转换(
as int[n]
和as 𝔹^n
) forget
def solve[n: !ℕ](bits: !𝔹^n) { | |
// prepare superposition between 0 and 1 | |
x := H(0: 𝔹); | |
// prepare superposition between bits and 0 | |
qs := if x then bits else (0: int[n]) as 𝔹^n; | |
// uncompute x | |
forget(x=qs[0]); // valid because `bits[0]==1` | |
return qs; | |
} | |
// EXAMPLE CALL | |
def main() { | |
// example usage for bits=1, n=2 | |
x := 1: !int[2]; | |
y := x as !𝔹^2; | |
return solve(y); | |
} |
# 生成 W 态
任务的原始来源:问题 A4(2018)
在量子位 下生成一个广义 W 态:
# 解决方案
以下解决方案特别有用
- λ 抽象(
λ...
)
def solve(k:!ℕ) { | |
// produce uniform superposition over k-bit uints | |
i:=0:uint[k]; | |
for j in [0..k){ i[j]:=H(i[j]); } | |
// invert i-th qubits (results in correct state, but entangled with i) | |
qs:=vector(2^k,0:𝔹); | |
qs[i]=X(qs[i]); | |
// uncompute i | |
forget(i=λ(qs:𝔹^(2^k))lifted{ // function to reconstruct i from qs | |
i:=0:uint[k]; | |
for j in [0..2^k){ | |
if qs[j]{ // in the superposition's summand where qs[j]==1, i==j | |
i=j as uint[k]; | |
} | |
} | |
return i; | |
}(qs)); | |
// return result | |
return qs; | |
} | |
// EXAMPLE CALL | |
def main() { | |
// example usage for k=2 | |
return solve(2); | |
} |
# 区分 3 量子位状态 (Distinguish 3-qubit States)
任务的原始来源:问题 B1(2019)
确定给定的量子位是否处于状态 (返回 )或 (返回 ):
- ,其中 。
- ,其中 。
你可以任意修改给定的量子比特(包括测量值)。
# 解决方案
关键点:
- :这两个态是正交的。
- 可以在 个量子位 上转换为 态。这个过程转换 到某种态 正交于 。
- 我们可以从 生成 (参见上面的问题 A4)。反过来从从 生成 和一个从 到 与之正交的态。
以下解决方案特别是有用:
- 分解列表:(
(head,)~tail:=qs
) - 递归函数 (
reverse
)
def toW[n:!ℕ](qs:𝔹^n)mfree:𝔹^n{ | |
// for a single bit, prepare |1⟩ | |
if n==1{ qs[0]:=X(qs[0]); } | |
else if n>1{ | |
// split qs into head (first element) and tail (rest) | |
(head,)~tail:=qs; | |
// prepare first bit | |
θ:=2·asin(1/sqrt(n)); // sin(θ/2)=1/sqrt(n), cos(θ/2)=sqrt((n-1)/n) | |
head:=rotY(θ,head); // |0⟩ ↦ cos(θ/2)|0⟩ + sin(θ/2)|1⟩ = cos(θ/2) |0⟩ + 1/sqrt(n)|1⟩ | |
// prepare remaining bits | |
if !head { tail := toW(tail); } | |
// combine head and tail again | |
qs:=(head,)~tail; | |
} | |
return qs; | |
} | |
def solve(qs:𝔹^3):!ℕ{ | |
// transform ψ₀ to W₃ | |
if qs[1]{ phase(-2·π/3); } // exp(2*i*π/3)*exp(i*-2*π/3)=1 | |
if qs[2]{ phase(-4·π/3); } // exp(4*i*π/3)*exp(i*-4*π/3)=1 | |
// map W₃ to |000⟩ | |
qs:=reverse(toW[3])(qs); | |
// check if obtained |000⟩ | |
return measure(qs as int[3])!=0; | |
} | |
// EXAMPLE CALL | |
def generate_input_state(state:!𝔹){ | |
// prepare ψ_0 (state=false) or ψ_1 (state=true) | |
qs:=vector(3,0:𝔹); | |
qs:=toW[3](qs); | |
if state{ | |
if qs[1]{ phase(4·π/3); } | |
else if qs[2]{ phase(2·π/3); } | |
}else{ | |
if qs[1]{ phase(2·π/3); } | |
else if qs[2]{ phase(4·π/3); } | |
} | |
return qs; | |
} | |
def main(){ | |
// expected outcome: (0,1) | |
// prepare both states | |
ψ_0:=generate_input_state(false); | |
ψ_1:=generate_input_state(true); | |
check0:=solve(ψ_0); | |
check1:=solve(ψ_1); | |
return (check0,check1); | |
} |
# 检查字符串是否是周期性的
原始任务来源:问题 C2(2019)
实现一个函数 solve
并签名 solve[n:!ℕ](x:𝔹^n):𝔹
,和
一系列长度为 的字符串被认为是周期性的,且周期 ( ) 如果所有 , 。
# 解决方案
- 当
y
和z
是可覆盖的,自动计算它们。
def solve[n:!ℕ](x:𝔹^n)lifted{ | |
y:=0:𝔹; | |
// Check all possible periods. | |
// Periods with P<(n+1)/2 are implicitly detected by period 2P because P<=(n+1)/2-1 implies 2P<=n-1. | |
for p in [(n+1) div 2..n){ | |
// check period p | |
z := 1:𝔹; | |
for i in [0..n-p){ | |
z&=x[i]==x[i+p]; | |
} | |
y|=z; | |
} | |
return y; | |
} | |
// EXAMPLE CALL | |
def main(){ | |
// expected outcome: (0,1) | |
ap:=solve((true,true,false)); | |
p:=solve((false,false,false)); | |
return (ap,p); | |
} |
# X 翼战斗机 (X-wing Fighter)
任务的原始来源:问题 D3(2019)
实现统一操作 个量子位,由主副对角线都是非零元素,而其他任何地方都是零元素的大小为 的方阵表示。
例如,对于 ,操作的矩阵应当有如下形状:
X......X | |
.X....X. | |
..X..X.. | |
...XX... | |
...XX... | |
..X..X.. | |
.X....X. | |
X......X |
这里 X
表示矩阵中的非零元素, .
表示矩阵中的零元素。
矩阵的行和列索引遵循小端格式:索引的最低有效位首先存储在量子位数组中。因此,矩阵的第二列为你提供了基态系数,如果你应用于基态 将会得到。
# 解决方案
关键点:一个可能的解决方案是将 映射到 ,其中 。这是因为从左上角到右下角的对角线捕获标识,而从左下角到右上角的对角线捕获从 到 (其中 可以用倒置所有 的位置算得) 的映射。
以下解决方案特别是有用:
- 将矢量的条目与其他值交换
def solve[n:!ℕ](qs:𝔹^n){ | |
x:=0:𝔹; | |
// swap x with LSB of qs | |
// necessary because Silq would block `qs` in the body of `if qs[0] {...}` | |
(x,qs[0]):=(qs[0],x); | |
if x{ // flip all other bits if LSB=1 | |
for i in [1..n){ | |
qs[i]:=X(qs[i]); | |
} | |
} | |
x:=H(x); // map LSB to 1/√̅2 (|0⟩±|1⟩) | |
if x{ | |
// flip all other bits if LSB=1 | |
// - if LSB was originally 0, this flips the bits iff H flipped the LSB | |
// - if LSB was originally 1, this leaves the other bits flipped | |
// if H flipped the LSB and restores the other bits otherwise | |
for i in [1..n){ | |
qs[i]:=X(qs[i]); | |
} | |
} | |
// swap x back | |
(qs[0],x):=(x,qs[0]); | |
forget(x=0); | |
return qs; | |
} | |
// EXAMPLE CALL | |
def main(){ | |
// example usage for N=3 | |
x := 0:!int[3]; | |
y := x as 𝔹^3; | |
return solve(y); | |
} |