Skip to content

Commit

Permalink
Merge pull request #61 from harshangrjn/U_matrix_fixed_idx
Browse files Browse the repository at this point in the history
Fixed unitary matrix elements
  • Loading branch information
harshangrjn committed Oct 4, 2022
2 parents db12d63 + d499e44 commit 15b72d4
Show file tree
Hide file tree
Showing 32 changed files with 785 additions and 435 deletions.
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
QuantumCircuitOpt.jl Change Log
===============================

### v0.5.0
- Minor: Fixed result `primal_status` issue in `log.jl`
- Added helper functions for obtaining fixed indices of `U_var` unitary variables to zeros or constant values. Dropped linearization constraints for fixed `U_var` variables
- Dropped support for `unit_magnitude_constraints`
- Reformulated quadratic objective function of `slack_var` variables into a linear outer-approximation - increases code coverage due to MILP reformulation
- Fixed `slack_var` based on fixed `U_var` variables
- Minor updates in error messages for kron symboled gates
- Changed Cbc test dependency to HiGHS (MIP) solver
- Updated docs and unit tests to reflect above changes

### v0.4.1
- Added support for returning exact feasible decomposition (without optimality certificate) using `exact_feasible`
- Added support for unitary constraints using binary linearizations (speeds up feasiblity problems)
- Added `decompose_W_using_HSTCnot` in examples
- Added `decompose_CNOT_using_GR` in examples (for Rydberg atom array-based simulators)
- Added `W_using_HSTCnot` in examples
- Added `CNOT_using_GR` in examples (for Rydberg atom array-based simulators)
- Added support for `CSGate`, `CSdaggerGate`, `CTGate`, `CTdaggerGate` and `SSwapGate` (sqrt(`SwapGate`))
- Dropped support for `CZRevGate` as it is invariant to qubit flip
- Updated README and docs with the Youtube link for the JuliaCon's presentation
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumCircuitOpt"
uuid = "88128e30-b60a-4e54-ab02-1050a5f92a36"
authors = ["Harsha Nagarajan"]
version = "0.4.1"
version = "0.5.0"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand All @@ -16,8 +16,8 @@ Memento = "~1.0, ~1.1, 1"
julia = "^1"

[extras]
Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"

[targets]
test = ["Cbc", "Test"]
test = ["HiGHS", "Test"]
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Status:
[![CI](https://github.com/harshangrjn/QuantumCircuitOpt.jl/actions/workflows/ci.yml/badge.svg)](https://github.com/harshangrjn/QuantumCircuitOpt.jl/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/harshangrjn/QuantumCircuitOpt.jl/branch/master/graph/badge.svg?token=KGJWIV6QF4)](https://codecov.io/gh/harshangrjn/QuantumCircuitOpt.jl)
[![version][https://juliahub.com/docs/QuantumCircuitOpt/version.svg]][https://juliahub.com/ui/Packages/QuantumCircuitOpt/dwSy1]

<!-- Stable version: [![Documentation](https://github.com/harshangrjn/QuantumCircuitOpt.jl/actions/workflows/documentation.yml/badge.svg)](https://harshangrjn.github.io/QuantumCircuitOpt.jl/stable/) -->
Dev version: [![Documentation](https://github.com/harshangrjn/QuantumCircuitOpt.jl/actions/workflows/documentation.yml/badge.svg)](https://harshangrjn.github.io/QuantumCircuitOpt.jl/dev/)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import Pkg
Pkg.add("QuantumCircuitOpt")
```

At least one mixed-integer programming solver is required for running QuantumCircuitOpt. The well-known [CPLEX](https://github.com/jump-dev/CPLEX.jl) or the [Gurobi](https://github.com/jump-dev/Gurobi.jl) solver is highly recommended, as it is fast, scaleable and can be used to solve on fairly large-scale graphs. However, open-source solvers such as [Cbc](https://github.com/jump-dev/Cbc.jl) or [GLPK](https://github.com/jump-dev/GLPK.jl) is also compatible with QuantumCircuitOpt which can be installed via the package manager with
At least one mixed-integer programming (MIP) solver is required for running QuantumCircuitOpt. The well-known [Gurobi](https://github.com/jump-dev/Gurobi.jl) or IBM's [CPLEX](https://github.com/jump-dev/CPLEX.jl) solver is highly recommended, as it is fast, scaleable and can be used to solve on fairly large-scale circuits. However, the open-source MIP solver [HiGHS](https://github.com/jump-dev/HiGHS.jl) is also compatible with QuantumCircuitOpt. Gurobi (or any other MIP solver) can be installed via the package manager with

```julia
import Pkg
Pkg.add("Cbc")
Pkg.add("Gurobi")
```

## Unit Tests
Expand Down
12 changes: 7 additions & 5 deletions docs/src/quickguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Building on the recent success of [Julia](https://julialang.org), [JuMP](https:/
```

## Getting started
To get started, install [QCOpt](https://github.com/harshangrjn/QuantumCircuitOpt.jl) and [JuMP](https://github.com/jump-dev/JuMP.jl), a modeling language layer for optimization. QCOpt also needs a MIP solver such as [CPLEX](https://github.com/jump-dev/CPLEX.jl) or [Gurobi](https://github.com/jump-dev/Gurobi.jl). If you prefer an open-source MIP solver, install [CBC](https://github.com/jump-dev/Cbc.jl) or [GLPK](https://github.com/jump-dev/GLPK.jl) from the Julia package manager, though be warned that the run times of QCOpt can be substantially slower using these open-source MIP solvers.
To get started, install [QCOpt](https://github.com/harshangrjn/QuantumCircuitOpt.jl) and [JuMP](https://github.com/jump-dev/JuMP.jl), a modeling language layer for optimization. QCOpt also needs a MIP solver such as [Gurobi](https://github.com/jump-dev/Gurobi.jl) or IBM's [CPLEX](https://github.com/jump-dev/CPLEX.jl). If you prefer an open-source MIP solver, install [HiGHS](https://github.com/jump-dev/HiGHS.jl) from the Julia package manager, though be warned that the run times of QCOpt can be substantially slower using any of the open-source MIP solvers.

# User inputs
QCOpt takes two types of user-defined input specifications. The first type of input contains all the necessary circuit specifications. This is given by a dictionary in Julia, which is a collection of key-value pairs, where every key is of the type `String`, which admits values of various types. Below is the list of allowable keys for the dictionary, given in column 1, and it's respective values with descriptions, given in column 2. This input dictionary is represented as `params` in all the [example](https://github.com/harshangrjn/QuantumCircuitOpt.jl/tree/master/examples) circuit decompositions.
Expand Down Expand Up @@ -88,7 +88,7 @@ The second set of inputs for QCOpt contains all the optional specifications for
|`identity_gate_symmetry_constraints`| This option activates the valid constraints to eliminate symmetry in the Identity gate in the decomposition (default: `true`)|
|`idempotent_gate_constraints`| This option activates the valid constraints to eliminate idempotent gates in the elementary (native) gates set (default: `false`)|
|`convex_hull_gate_constraints`| This option activates the valid constraints to apply convex hull of complex entries in the elementary (native) gates set (default: `false`)|
|`unit_magnitude_constraints`| This option activates the valid outer-approximation constraints for unit-valued complex entries of the unitary gates (`U_var`) (default: `false`)|
|`fix_unitary_variables`| This option evaluates all the fixed-valued indices of unitary matrix varaibles (`U_var`) at every depth, and appropriately builds the optimization model (default: `true`)|
|`visualize_solution`| This option activates the visualization of the optimal circuit decomposition (default: `true`)|
| `relax_integrality` | This option transforms integer variables into continuous variables (default: `false`). |
| `optimizer_log` | This option enables or disables console logging for the `optimizer` (default: `true`).|
Expand Down Expand Up @@ -161,23 +161,25 @@ QCOpt.visualize_solution(results, data)
For example, for the above controlled-Z gate decomposition, the processed output of QCOpt is as follows:
```
=============================================================================
QuantumCircuitOpt version: v0.5.0
Quantum Circuit Model Data
Number of qubits: 2
Total number of elementary gates (after presolve): 72
Maximum depth of decomposition: 4
Input elementary gates: ["U3_1", "U3_2", "CNot_1_2", "Identity"]
Elementary gates: ["U3_1", "U3_2", "CNot_1_2", "Identity"]
U3_θ discretization: [-180.0, -90.0, 0.0, 90.0, 180.0]
U3_ϕ discretization: [-180.0, -90.0, 0.0, 90.0, 180.0]
U3_λ discretization: [-180.0, -90.0, 0.0, 90.0, 180.0]
Type of decomposition: exact
Type of decomposition: exact_optimal
MIP optimizer: Gurobi
Optimal Circuit Decomposition
U3_2(-90.0,0.0,0.0) * CNot_1_2 * U3_2(90.0,0.0,0.0) = Target gate
Minimum optimal depth: 3
Optimizer run time: 2.64 sec.
Optimizer run time: 3.01 sec.
=============================================================================
```

58 changes: 29 additions & 29 deletions examples/2qubit_gates.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function decompose_hadamard()
function hadamard()

println(">>>>> Hadamard Gate <<<<<")

Expand All @@ -17,7 +17,7 @@ function decompose_hadamard()
)
end

function decompose_controlled_Z()
function controlled_Z()

println(">>>>> Controlled-Z Gate <<<<<")

Expand All @@ -37,7 +37,7 @@ function decompose_controlled_Z()

end

function decompose_controlled_V()
function controlled_V()

println(">>>>> Controlled-V Gate <<<<<")

Expand All @@ -52,7 +52,7 @@ function decompose_controlled_V()
)
end

function decompose_controlled_H()
function controlled_H()

println(">>>>> Controlled-H Gate <<<<<")

Expand All @@ -71,7 +71,7 @@ function decompose_controlled_H()
)
end

function decompose_controlled_H_with_R()
function controlled_H_with_R()

println(">>>>> Controlled-H with R Gate <<<<<")

Expand All @@ -90,7 +90,7 @@ function decompose_controlled_H_with_R()
)
end

function decompose_magic()
function magic()

println(">>>>> M Gate <<<<<")

Expand All @@ -109,7 +109,7 @@ function decompose_magic()
)
end

function decompose_magic_using_CNOT_1_2()
function magic_using_CNOT_1_2()

println(">>>>> M Gate <<<<<")

Expand All @@ -128,7 +128,7 @@ function decompose_magic_using_CNOT_1_2()
)
end

function decompose_magic_using_SHCnot()
function magic_using_SHCnot()

println(">>>>> M gate using S, H and CNOT Gate <<<<<")

Expand All @@ -143,7 +143,7 @@ function decompose_magic_using_SHCnot()
)
end

function decompose_S()
function S_gate()

println(">>>>> S Gate <<<<<")

Expand All @@ -162,7 +162,7 @@ function decompose_S()
)
end

function decompose_revcnot()
function revcnot()

println(">>>>> Reverse CNOT Gate <<<<<")

Expand All @@ -173,11 +173,11 @@ function decompose_revcnot()
"elementary_gates" => ["H_1", "H_2", "CNot_1_2", "Identity"],
"target_gate" => QCOpt.CNotRevGate(),
"objective" => "minimize_depth",
"decomposition_type" => "exact_optimal"
"decomposition_type" => "exact_optimal"
)
end

function decompose_revcnot_with_U()
function revcnot_with_U()

println(">>>>> Reverse CNOT using U3 and CNOT Gates <<<<<")

Expand All @@ -196,7 +196,7 @@ function decompose_revcnot_with_U()
)
end

function decompose_swap()
function swap()

println(">>>>> SWAP Gate <<<<<")

Expand All @@ -211,7 +211,7 @@ function decompose_swap()
)
end

function decompose_W()
function W_gate()

println(">>>>> W Gate <<<<<")

Expand All @@ -230,7 +230,7 @@ function decompose_W()
)
end

function decompose_W_using_HSTCnot()
function W_using_HSTCnot()

println(">>>>> W Gate using H, S, T and CNOT gates <<<<<")

Expand All @@ -245,7 +245,7 @@ function decompose_W_using_HSTCnot()
)
end

function decompose_W_using_HCnot()
function W_using_HCnot()

println(">>>>> W Gate using H and CNOT gates <<<<<")

Expand All @@ -260,7 +260,7 @@ function decompose_W_using_HCnot()
)
end

function decompose_HCoinGate()
function HCoinGate()

println(">>>>> Hadamard Coin gate <<<<<")

Expand All @@ -275,7 +275,7 @@ function decompose_HCoinGate()
)
end

function decompose_GroverDiffusion_using_HX()
function GroverDiffusion_using_HX()

println(">>>>> Grover's Diffusion Operator <<<<<")

Expand All @@ -292,7 +292,7 @@ function decompose_GroverDiffusion_using_HX()
)
end

function decompose_GroverDiffusion_using_Clifford()
function GroverDiffusion_using_Clifford()

println(">>>>> Grover's Diffusion Operator <<<<<")

Expand All @@ -308,7 +308,7 @@ function decompose_GroverDiffusion_using_Clifford()
end


function decompose_GroverDiffusion_using_U3()
function GroverDiffusion_using_U3()

println(">>>>> Grover's Diffusion Operator using U3 gate <<<<<")

Expand All @@ -327,7 +327,7 @@ function decompose_GroverDiffusion_using_U3()
)
end

function decompose_iSwap()
function iSwap()

println(">>>>> iSwap Gate <<<<<")

Expand All @@ -339,11 +339,11 @@ function decompose_iSwap()
# "elementary_gates" => ["S_1", "S_2", "Sdagger_1", "Sdagger_2", "H_1", "H_2", "CNot_1_2", "CNot_2_1", "Identity"],
"target_gate" => QCOpt.iSwapGate(),
"objective" => "minimize_depth",
"decomposition_type" => "exact_optimal",
"decomposition_type" => "exact_optimal",
)
end

function decompose_qft2_using_R()
function qft2_using_R()
println(">>>>> QFT2 Gate using R and CNOT gates <<<<<")

return Dict{String, Any}(
Expand All @@ -353,14 +353,14 @@ function decompose_qft2_using_R()
"elementary_gates" => ["RX_1", "RZ_1", "RZ_2", "CNot_1_2", "CNot_2_1", "Identity"],
"target_gate" => QCOpt.QFT2Gate(),
"objective" => "minimize_depth",
"decomposition_type" => "approximate",
"decomposition_type" => "exact_feasible",

"RX_discretization" =>/2],
"RZ_discretization" => [-π/4, π/2, 3*π/4, 7*π/4],
)
end

function decompose_qft2_using_HT()
function qft2_using_HT()
println(">>>>> QFT2 Gate using H, T, CNOT gates <<<<<")

return Dict{String, Any}(
Expand All @@ -374,11 +374,11 @@ function decompose_qft2_using_HT()
)
end

function decompose_GRGate()
function GRGate()
println(">>>>> GRGate testing <<<<<")

GR1 = QCOpt.get_full_sized_gate("GR", 2; angle =/6, π/3])
GR2 = QCOpt.get_full_sized_gate("GR", 2; angle =/3, π/6])
# GR2 = QCOpt.get_full_sized_gate("GR", 2; angle = [π/3, π/6])
CNot_1_2 = QCOpt.get_full_sized_gate("CNot_1_2", 2)
T = QCOpt.round_complex_values(GR1 * CNot_1_2)

Expand All @@ -395,7 +395,7 @@ function decompose_GRGate()
)
end

function decompose_X_using_GR()
function X_using_GR()

println(">>>>> Pauli-X Gate using global rotation <<<<<")

Expand All @@ -415,7 +415,7 @@ function decompose_X_using_GR()
)
end

function decompose_CNOT_using_GR()
function CNOT_using_GR()
println(">>>>> CNOT Gate using global rotation <<<<<")

return Dict{String, Any}(
Expand Down
Loading

0 comments on commit 15b72d4

Please sign in to comment.