Skip to content

Commit 0fbdc0b

Browse files
authored
Merge pull request #67 from harshangrjn/log_updates
Log updates
2 parents c23a46d + 08def47 commit 0fbdc0b

File tree

9 files changed

+74
-19
lines changed

9 files changed

+74
-19
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
QuantumCircuitOpt.jl Change Log
22
===============================
33

4+
### v0.5.7
5+
- Clean up in log.jl to validate circuit decomposition upto global phase
6+
- Added `parametrized_hermitian_gates` in examples
7+
48
### v0.5.6
59
- Video link to SC22 presentation added
610

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "QuantumCircuitOpt"
22
uuid = "88128e30-b60a-4e54-ab02-1050a5f92a36"
33
authors = ["Harsha Nagarajan"]
4-
version = "0.5.6"
4+
version = "0.5.7"
55

66
[deps]
77
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"

examples/2qubit_gates.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ function hadamard_coin()
267267
return Dict{String, Any}(
268268

269269
"num_qubits" => 2,
270-
"maximum_depth" => 14,
270+
"maximum_depth" => 12,
271271
"elementary_gates" => ["Y_1", "Y_2", "Z_1", "Z_2", "T_2", "Tdagger_1", "Sdagger_1", "SX_1", "SXdagger_2", "CNot_2_1", "CNot_1_2", "Identity"],
272272
"target_gate" => QCOpt.HCoinGate(),
273273
"objective" => "minimize_depth",
@@ -286,9 +286,10 @@ function GroverDiffusion_using_HX()
286286
"num_qubits" => 2,
287287
"maximum_depth" => 10,
288288
"elementary_gates" => ["X_1", "X_1xX_2", "H_1xH_2", "X_2", "H_1", "H_2", "CNot_1_2", "Identity"],
289+
# "elementary_gates" => ["X_1", "X_2", "H_1", "H_2", "CNot_1_2", "Identity"],
289290
"target_gate" => QCOpt.GroverDiffusionGate(),
290291
"objective" => "minimize_depth",
291-
"decomposition_type" => "exact_optimal",
292+
"decomposition_type" => "optimal_global_phase",
292293
)
293294
end
294295

@@ -303,7 +304,7 @@ function GroverDiffusion_using_Clifford()
303304
"elementary_gates" => ["X_1", "X_2", "H_1", "H_2", "S_1", "S_2", "T_1", "T_2", "Y_1", "Y_2", "CNot_1_2", "Identity"],
304305
"target_gate" => QCOpt.GroverDiffusionGate(),
305306
"objective" => "minimize_depth",
306-
"decomposition_type" => "exact_optimal",
307+
"decomposition_type" => "optimal_global_phase",
307308
)
308309
end
309310

@@ -424,7 +425,7 @@ function CNOT_using_GR()
424425
"elementary_gates" => ["GR", "R_1", "R_2", "CZ_1_2", "Identity"],
425426
"target_gate" => QCOpt.CNotGate(),
426427
"objective" => "minimize_depth",
427-
"decomposition_type" => "exact_optimal",
428+
"decomposition_type" => "optimal_global_phase",
428429
"GR_θ_discretization" => -2π/2:2π,
429430
"GR_ϕ_discretization" => [0],
430431
"R_θ_discretization" => 0:π/4:π,

examples/3qubit_gates.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ function toffoli_left()
147147
"maximum_depth" => 7,
148148
"elementary_gates" => ["H_3", "T_1", "T_2", "T_3", "Tdagger_1", "Tdagger_2", "Tdagger_3", "CNot_1_2", "CNot_2_3", "CNot_1_3", "Identity"],
149149
"target_gate" => target_gate(),
150-
"objective" => "minimize_depth"
150+
"objective" => "minimize_depth",
151+
"decomposition_type" => "exact_optimal"
151152
)
152153
end
153154

examples/decompose_all_gates.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,7 @@ decompose_gates = [
3737
"quantum_fulladder",
3838
"double_toffoli",
3939
#-- 5-qubit gates --#
40-
"RX_on_5qubits"
40+
"RX_on_5qubits",
41+
#-- paramterized gates --#
42+
"parametrized_hermitian_gates"
4143
]

examples/optimizers.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
function get_gurobi()
77
return JuMP.optimizer_with_attributes(Gurobi.Optimizer,
88
MOI.Silent() => false,
9-
# "MIPFocus" => 3, # Focus on optimality over feasibility
9+
# "MIPFocus" => 3, # Focus on optimality over feasibility
1010
"Presolve" => 1)
1111
end
1212

examples/parametrized_gates.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
function parametrized_hermitian_gates()
2+
3+
function target_gate(num_qubits, i, j, t)
4+
A = Array{Complex{Float64},2}(zeros(2^num_qubits, 2^num_qubits))
5+
6+
A[i,j] = 1.0 + 0.0im
7+
A[j,i] = 1.0 + 0.0im
8+
9+
return exp(im*A*t)
10+
end
11+
12+
num_qubits = 2
13+
A_i = 1 # 1 <= i,j <= num_qubits
14+
A_j = 4 # 1 <= i,j <= num_qubits
15+
t = 2.5
16+
17+
return Dict{String, Any}(
18+
"num_qubits" => num_qubits,
19+
"maximum_depth" => 10,
20+
"elementary_gates" => ["RX_1", "RX_2", "CRX_1_2", "CRX_2_1", "CNot_1_2", "CNot_2_1", "Identity"],
21+
# "elementary_gates" => ["RX_1", "RX_2", "RX_3", "CRX_1_2", "CRX_2_1", "CRX_2_3", "CRX_3_2", "CNot_1_2", "CNot_2_1", "CNot_2_3", "CNot_3_2", "Identity"],
22+
"target_gate" => target_gate(num_qubits, A_i, A_j, t),
23+
"objective" => "minimize_depth",
24+
"decomposition_type" => "exact_optimal",
25+
26+
"RX_discretization" => [t*2,-t*2],
27+
"CRX_discretization" => [t*2,-t*2],
28+
)
29+
end

examples/run_examples.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include("2qubit_gates.jl")
1010
include("3qubit_gates.jl")
1111
include("4qubit_gates.jl")
1212
include("5qubit_gates.jl")
13+
include("parametrized_gates.jl")
1314
include("decompose_all_gates.jl")
1415

1516
# decompose_gates = ["iSwap"]
@@ -26,6 +27,7 @@ for gates = 1:length(decompose_gates)
2627
params = getfield(Main, Symbol(decompose_gates[gates]))()
2728

2829
model_options = Dict{Symbol, Any}(
30+
:model_type => "compact_formulation",
2931
:convex_hull_gate_constraints => false,
3032
:idempotent_gate_constraints => false,
3133
:unitary_constraints => false,

src/log.jl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,12 @@ end
113113
function get_postprocessed_circuit(results::Dict{String, Any}, data::Dict{String, Any})
114114

115115
gates_sol = Array{String,1}()
116-
id_sequence = Array{Int64,1}()
116+
id_sequence = QCO._gate_id_sequence(results["solution"]["z_bin_var"], data["maximum_depth"])
117+
(data["decomposition_type"] in ["exact_optimal", "exact_feasible", "optimal_global_phase"]) && QCO.validate_circuit_decomposition(data, id_sequence)
117118

118119
for d = 1:data["maximum_depth"]
119-
id = findall(isone.(round.(abs.(results["solution"]["z_bin_var"][:,d]), digits=3)))[1]
120-
push!(id_sequence, id)
121-
122-
gate_id = data["gates_dict"]["$id"]
120+
121+
gate_id = data["gates_dict"]["$(id_sequence[d])"]
123122

124123
if !("Identity" in gate_id["type"])
125124

@@ -165,8 +164,6 @@ function get_postprocessed_circuit(results::Dict{String, Any}, data::Dict{String
165164
end
166165
end
167166
end
168-
169-
(data["decomposition_type"] in ["exact_optimal", "exact_feasible", "optimal_global_phase"]) && QCO.validate_circuit_decomposition(data, id_sequence)
170167

171168
gates_sol_compressed = QCO.get_depth_compressed_circuit(data["num_qubits"], gates_sol)
172169

@@ -178,8 +175,9 @@ end
178175
179176
This function validates the circuit decomposition if it is indeed exact with respect to the specified target gate.
180177
"""
181-
function validate_circuit_decomposition(data::Dict{String, Any}, id_sequence::Array{Int64,1})
182-
178+
function validate_circuit_decomposition(data::Dict{String, Any}, id_sequence::Array{Int64,1}; error_message = true)
179+
valid_status = false
180+
183181
M_sol = Array{Complex{Float64},2}(Matrix(LA.I, 2^(data["num_qubits"]), 2^(data["num_qubits"])))
184182

185183
for i in id_sequence
@@ -193,8 +191,15 @@ function validate_circuit_decomposition(data::Dict{String, Any}, id_sequence::Ar
193191
target_gate = QCO.real_to_complex_gate(data["target_gate"])
194192
end
195193

196-
(!QCO.isapprox_global_phase(M_sol, convert(Array{Complex{Float64},2}, target_gate))) &&
197-
Memento.error(_LOGGER, "Decomposition is not valid: Problem may be infeasible")
194+
if data["decomposition_type"] in ["exact_optimal", "exact_feasible"]
195+
(QCO.isapprox(M_sol, convert(Array{Complex{Float64},2}, target_gate), atol = 1E-4)) && (valid_status = true)
196+
elseif data["decomposition_type"] in ["optimal_global_phase"]
197+
(QCO.isapprox_global_phase(M_sol, convert(Array{Complex{Float64},2}, target_gate))) && (valid_status = true)
198+
end
199+
200+
(!(valid_status) && error_message) && Memento.error(_LOGGER, "Decomposition is not valid: Problem may be infeasible")
201+
202+
return valid_status
198203
end
199204

200205
"""
@@ -279,3 +284,14 @@ function get_depth_compressed_circuit(num_qubits::Int64, gates_sol::Array{String
279284

280285
return gates_sol_compressed
281286
end
287+
288+
function _gate_id_sequence(z_val::Matrix{<:Number}, maximum_depth::Int64)
289+
id_sequence = Array{Int64,1}()
290+
291+
for d = 1:maximum_depth
292+
id = findall(isone.(round.(abs.(z_val[:,d]), digits=3)))[1]
293+
push!(id_sequence, id)
294+
end
295+
296+
return id_sequence
297+
end

0 commit comments

Comments
 (0)