-
Notifications
You must be signed in to change notification settings - Fork 9
/
find_circuit.m
106 lines (97 loc) · 3.26 KB
/
find_circuit.m
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
106
function circuit = find_circuit(F)
% Function to find a circuit for the given symplectic transformation F
% Uses Trung Can's algorithm to decompose F into elementary forms
% Author: Narayanan Rengaswamy, Date: Mar. 1, 2018
m = size(F,1)/2;
I = eye(m);
O = zeros(m);
Omega = [O, I; I, O];
if (~all(all(mod(F * Omega * F', 2) == Omega)))
fprintf('\nInvalid symplectic matrix!\n');
circuit = [];
return;
end
if (all(all(F == eye(2*m))))
circuit = [];
return;
end
Decomp = symp_mat_decompose(F); % Trung Can's decomposition
circuit = cell(1,2);
ckt_ind = 1;
for i = 1:size(Decomp,1)
if (all(all(Decomp{i} == eye(2*m))))
continue;
elseif (all(all(Decomp{i} == Omega)))
% Transversal Hadamard
circuit{ckt_ind,1} = 'H';
circuit{ckt_ind,2} = 1:m;
ckt_ind = ckt_ind + 1;
continue;
end
A = Decomp{i}(1:m,1:m);
B = Decomp{i}(1:m,m+(1:m));
C = Decomp{i}(m+(1:m),1:m);
D = Decomp{i}(m+(1:m),m+(1:m));
if (all(A(:) == I(:)) && all(C(:) == O(:)) && all(D(:) == I(:)))
% CZs and Phase
P_ind = find(diag(B) == 1)';
if (~isempty(P_ind))
circuit{ckt_ind,1} = 'P';
circuit{ckt_ind,2} = P_ind;
ckt_ind = ckt_ind + 1;
end
% Clear diagonal entries, extract upper triangular part as B = B'
B = triu(mod(B + diag(diag(B)), 2));
for j = 1:m
CZ_ind = find(B(j,:) == 1);
for k = 1:length(CZ_ind)
circuit{ckt_ind,1} = 'CZ';
circuit{ckt_ind,2} = [j CZ_ind(k)];
ckt_ind = ckt_ind + 1;
end
end
elseif (all(B(:) == O(:)) && all(C(:) == O(:)))
% CNOTs and Permutations
% CAUTION: For qubits that act as both control and target, first
% implement the CNOTs where they act as control!
% To ensure this, we use LU decomposition over GF(2).
[L, U, P] = gf2lu(A); % P' * L * U = A (P is a permutation matrix)
if (~all(P(:) == I(:)))
circuit{ckt_ind,1} = 'Permute';
circuit{ckt_ind,2} = (1:m)*P';
ckt_ind = ckt_ind + 1;
end
for j = 1:m
inds = setdiff(find(L(j,:) == 1), j);
for k = 1:length(inds)
circuit{ckt_ind,1} = 'CNOT';
circuit{ckt_ind,2} = [j inds(k)]; % CNOT_{j->inds(k)}
ckt_ind = ckt_ind + 1;
end
end
for j = m:-1:1
inds = setdiff(find(U(j,:) == 1), j);
for k = 1:length(inds)
circuit{ckt_ind,1} = 'CNOT';
circuit{ckt_ind,2} = [j inds(k)]; % CNOT_{j->inds(k)}
ckt_ind = ckt_ind + 1;
end
end
else
% Partial Hadamards
k = m - sum(diag(A));
Uk = blkdiag(eye(k), zeros(m-k));
Lmk = blkdiag(zeros(k), eye(m-k));
if (all(A(:) == Lmk(:)) && all(B(:) == Uk(:)) && ...
all(C(:) == Uk(:)) && all(D(:) == Lmk(:)))
circuit{ckt_ind,1} = 'H';
circuit{ckt_ind,2} = 1:k;
ckt_ind = ckt_ind + 1;
else
fprintf('\nUnknown elementary symplectic form!\n');
circuit = [];
break;
end
end
end
end