From 9eb77a22d4cc3c6497e8f0ebba5f64439a74157f Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Wed, 11 Dec 2024 01:21:51 -0800 Subject: [PATCH 1/7] Added Ising model sample --- samples/algorithms/Ising.qs | 106 ++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 samples/algorithms/Ising.qs diff --git a/samples/algorithms/Ising.qs b/samples/algorithms/Ising.qs new file mode 100644 index 0000000000..ff1a19d7bc --- /dev/null +++ b/samples/algorithms/Ising.qs @@ -0,0 +1,106 @@ +/// # Sample +/// Simulation of a simple Ising model evolution on a 2D grid +/// This example can be easily simulated classically +/// with 3x3 grid and about 500 shots. + +operation Main() : Result[] { + // Dimensions of a 2D grid is N1 x N2 + let N1 : Int = 3; + let N2 : Int = 3; + + // Total evolution time + let evolutionTime : Double = 4.0; + // Time step + let stepTime : Double = 0.8; + + // Coefficient for 2-qubit interactions between neighboring qubits + let J : Double = 1.0; + // Coefficient for external field interaction for individual qubits + let g : Double = 1.4; + + // Also try simulating with different strength of external field: + // let g = 0.2; + // let g = 1.0; + // let g = 1.4; + // let g = 2.0; + + // Model evolution + IsingModel2DSim(N1, N2, J, g, evolutionTime, stepTime) +} + +/// # Summary +/// Simulate Ising model evolution +/// +/// # Description +/// Simulates state |𝜓⟩ evolution to find |𝜓(t)⟩=U(t)|𝜓(0)⟩. +/// |𝜓(0)⟩ is taken to be |0...0⟩. +/// U(t)=e⁻ⁱᴴᵗ, where H is an Ising model Hamiltonian H = -J·Σ'ᵢⱼZᵢZⱼ + g·ΣᵢXᵢ +/// Here Σ' is taken over all pairs of neighboring qubits . +/// Simulation is done via K steps assuming U(t)≈U(t/K)^K. +operation IsingModel2DSim( + N1 : Int, + N2 : Int, + J : Double, + g : Double, + evolutionTime : Double, + stepTime : Double) : Result[] { + + // Allocate qubit grid and structure it as a 2D array. + use qubits = Qubit[N1 * N2]; + let qubitsAs2D = Std.Arrays.Chunks(N2, qubits); + + // Compute the number of steps K for evolution + let K = Std.Math.Ceiling(evolutionTime / stepTime); + + let theta_x = - g * stepTime; + let theta_zz = J * stepTime; + + // Perform K steps + for i in 1..K { + + // Single-qubit interaction with external field + for q in qubits { + Rx(2.0 * theta_x, q); + } + + // All Rzz gates applied in the following two loops commute so they can be + // applied in any order. To reduce the depth of the algorithm, Rzz gates + // between horizontal "even" pairs of qubits are applied first - pairs + // that start at even indices. Then Rzz gates between "odd" pairs are + // applied. That way all Rzz between horizontal "even" pairs can potentially + // be done in parallel. Same is true about horizontal "odd" pairs, + // vertical "even" pairs and vertical "odd" pairs. + + // Horizontal two-qubit interactions + for row in 0..N1-1 { + // Horizontal interactions between "even" pairs + for col in 0..2..N2-2 { + Rzz(2.0 * theta_zz, qubitsAs2D[row][col], qubitsAs2D[row][col + 1]); + } + + // Horizontal interactions between "odd" pairs + for col in 1..2..N2-2 { + Rzz(2.0 * theta_zz, qubitsAs2D[row][col], qubitsAs2D[row][col + 1]); + } + } + + // Vertical two-qubit interactions + for col in 0..N2-1 { + + // Vertical interactions between "even" pairs + for row in 0..2..N1-2 { + Rzz(2.0 * theta_zz, qubitsAs2D[row][col], qubitsAs2D[row + 1][col]); + } + + // Vertical interactions between "odd" pairs + for row in 1..2..N1-2 { + Rzz(2.0 * theta_zz, qubitsAs2D[row][col], qubitsAs2D[row + 1][col]); + } + + } + + } + + MResetEachZ(qubits) +} + \ No newline at end of file From 9611a39954cd3ac9188dc0d5b2932f39fb2fce3e Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Wed, 11 Dec 2024 11:13:42 -0800 Subject: [PATCH 2/7] Updated comments and names --- samples/algorithms/Ising.qs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/samples/algorithms/Ising.qs b/samples/algorithms/Ising.qs index ff1a19d7bc..b5e5b75b51 100644 --- a/samples/algorithms/Ising.qs +++ b/samples/algorithms/Ising.qs @@ -1,7 +1,12 @@ /// # Sample /// Simulation of a simple Ising model evolution on a 2D grid +/// +/// # Description +/// This example demonstrates simulation +/// of an Ising model Hamiltonian on an N1xN2 2D grid. /// This example can be easily simulated classically /// with 3x3 grid and about 500 shots. +/// This sample is suitable for Base Profile. operation Main() : Result[] { // Dimensions of a 2D grid is N1 x N2 @@ -25,7 +30,7 @@ operation Main() : Result[] { // let g = 2.0; // Model evolution - IsingModel2DSim(N1, N2, J, g, evolutionTime, stepTime) + IsingModel2DEvolution(N1, N2, J, g, evolutionTime, stepTime) } /// # Summary @@ -36,8 +41,8 @@ operation Main() : Result[] { /// |𝜓(0)⟩ is taken to be |0...0⟩. /// U(t)=e⁻ⁱᴴᵗ, where H is an Ising model Hamiltonian H = -J·Σ'ᵢⱼZᵢZⱼ + g·ΣᵢXᵢ /// Here Σ' is taken over all pairs of neighboring qubits . -/// Simulation is done via K steps assuming U(t)≈U(t/K)^K. -operation IsingModel2DSim( +/// Simulation is done via K steps assuming U(t)≈U(t/K)ᴷ. +operation IsingModel2DEvolution( N1 : Int, N2 : Int, J : Double, From fdbe427bb571b9ebd991a3d82748519ed6651a52 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Thu, 12 Dec 2024 15:43:38 -0800 Subject: [PATCH 3/7] Use number of steps paramter based on feedback from Vadym --- samples/algorithms/Ising.qs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/samples/algorithms/Ising.qs b/samples/algorithms/Ising.qs index b5e5b75b51..d1831ccc16 100644 --- a/samples/algorithms/Ising.qs +++ b/samples/algorithms/Ising.qs @@ -15,8 +15,8 @@ operation Main() : Result[] { // Total evolution time let evolutionTime : Double = 4.0; - // Time step - let stepTime : Double = 0.8; + // Number of steps + let numberOfSteps : Int = 5; // Coefficient for 2-qubit interactions between neighboring qubits let J : Double = 1.0; @@ -30,7 +30,7 @@ operation Main() : Result[] { // let g = 2.0; // Model evolution - IsingModel2DEvolution(N1, N2, J, g, evolutionTime, stepTime) + IsingModel2DEvolution(N1, N2, J, g, evolutionTime, numberOfSteps) } /// # Summary @@ -41,27 +41,28 @@ operation Main() : Result[] { /// |𝜓(0)⟩ is taken to be |0...0⟩. /// U(t)=e⁻ⁱᴴᵗ, where H is an Ising model Hamiltonian H = -J·Σ'ᵢⱼZᵢZⱼ + g·ΣᵢXᵢ /// Here Σ' is taken over all pairs of neighboring qubits . -/// Simulation is done via K steps assuming U(t)≈U(t/K)ᴷ. +/// Simulation is done by performing K steps assuming U(t)≈U(t/K)ᴷ. operation IsingModel2DEvolution( N1 : Int, N2 : Int, J : Double, g : Double, evolutionTime : Double, - stepTime : Double) : Result[] { + numberOfSteps : Int) : Result[] { // Allocate qubit grid and structure it as a 2D array. use qubits = Qubit[N1 * N2]; let qubitsAs2D = Std.Arrays.Chunks(N2, qubits); - // Compute the number of steps K for evolution - let K = Std.Math.Ceiling(evolutionTime / stepTime); + // Compute the step time + import Std.Convert.IntAsDouble; + let stepTime: Double = evolutionTime / IntAsDouble(numberOfSteps); let theta_x = - g * stepTime; let theta_zz = J * stepTime; // Perform K steps - for i in 1..K { + for i in 1..numberOfSteps { // Single-qubit interaction with external field for q in qubits { From db6c1c756a33f57658e32021bc594e22e6efd8f4 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Mon, 16 Dec 2024 00:24:40 -0800 Subject: [PATCH 4/7] Renamed to simple Ising --- samples/algorithms/{Ising.qs => SimpleIsing.qs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/algorithms/{Ising.qs => SimpleIsing.qs} (100%) diff --git a/samples/algorithms/Ising.qs b/samples/algorithms/SimpleIsing.qs similarity index 100% rename from samples/algorithms/Ising.qs rename to samples/algorithms/SimpleIsing.qs From fbf98ce4695d9ef6d53d915d572fca2482c4e8b5 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Mon, 16 Dec 2024 00:36:59 -0800 Subject: [PATCH 5/7] Minor formatting and comments --- samples/algorithms/SimpleIsing.qs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/samples/algorithms/SimpleIsing.qs b/samples/algorithms/SimpleIsing.qs index d1831ccc16..61945ca0eb 100644 --- a/samples/algorithms/SimpleIsing.qs +++ b/samples/algorithms/SimpleIsing.qs @@ -2,12 +2,12 @@ /// Simulation of a simple Ising model evolution on a 2D grid /// /// # Description -/// This example demonstrates simulation -/// of an Ising model Hamiltonian on an N1xN2 2D grid. -/// This example can be easily simulated classically +/// This example demonstrates simulation of an Ising model Hamiltonian +/// on an N1xN2 2D grid. This example can be easily simulated classically /// with 3x3 grid and about 500 shots. /// This sample is suitable for Base Profile. - +/// For the purpose of simplicity this sample intentionally doesn't +/// post-process results or perform eigenvalue estimation. operation Main() : Result[] { // Dimensions of a 2D grid is N1 x N2 let N1 : Int = 3; @@ -17,7 +17,7 @@ operation Main() : Result[] { let evolutionTime : Double = 4.0; // Number of steps let numberOfSteps : Int = 5; - + // Coefficient for 2-qubit interactions between neighboring qubits let J : Double = 1.0; // Coefficient for external field interaction for individual qubits @@ -34,7 +34,7 @@ operation Main() : Result[] { } /// # Summary -/// Simulate Ising model evolution +/// Simulate simple Ising model evolution /// /// # Description /// Simulates state |𝜓⟩ evolution to find |𝜓(t)⟩=U(t)|𝜓(0)⟩. @@ -48,7 +48,8 @@ operation IsingModel2DEvolution( J : Double, g : Double, evolutionTime : Double, - numberOfSteps : Int) : Result[] { + numberOfSteps : Int +) : Result[] { // Allocate qubit grid and structure it as a 2D array. use qubits = Qubit[N1 * N2]; @@ -56,19 +57,19 @@ operation IsingModel2DEvolution( // Compute the step time import Std.Convert.IntAsDouble; - let stepTime: Double = evolutionTime / IntAsDouble(numberOfSteps); + let stepTime : Double = evolutionTime / IntAsDouble(numberOfSteps); let theta_x = - g * stepTime; let theta_zz = J * stepTime; - + // Perform K steps for i in 1..numberOfSteps { - + // Single-qubit interaction with external field for q in qubits { Rx(2.0 * theta_x, q); } - + // All Rzz gates applied in the following two loops commute so they can be // applied in any order. To reduce the depth of the algorithm, Rzz gates // between horizontal "even" pairs of qubits are applied first - pairs @@ -89,7 +90,7 @@ operation IsingModel2DEvolution( Rzz(2.0 * theta_zz, qubitsAs2D[row][col], qubitsAs2D[row][col + 1]); } } - + // Vertical two-qubit interactions for col in 0..N2-1 { From ecdc8f2bc8fc6d813215999fd575ad182f892627 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Mon, 16 Dec 2024 00:54:10 -0800 Subject: [PATCH 6/7] Attempt to figure out the output of a sample --- samples_test/src/tests/algorithms.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/samples_test/src/tests/algorithms.rs b/samples_test/src/tests/algorithms.rs index f2d596881a..6e8e5bcb7f 100644 --- a/samples_test/src/tests/algorithms.rs +++ b/samples_test/src/tests/algorithms.rs @@ -254,6 +254,12 @@ pub const SHOR_EXPECT_DEBUG: Expect = expect![[r#" Found factor=13 Found factorization 143 = 13 * 11 (13, 11)"#]]; +pub const SIMPLEISING_EXPECT: Expect = expect![[r#" + Something. + Something"#]]; +pub const SIMPLEISING_EXPECT_DEBUG: Expect = expect![[r#" + Something. + Something"#]]; pub const SUPERDENSECODING_EXPECT: Expect = expect!["((false, true), (false, true))"]; pub const SUPERDENSECODING_EXPECT_DEBUG: Expect = expect!["((false, true), (false, true))"]; pub const SUPERPOSITION_EXPECT: Expect = expect!["Zero"]; From 42c1f3085128dec61702fc68aee3ce21f08362e1 Mon Sep 17 00:00:00 2001 From: Dmitry Vasilevsky Date: Mon, 16 Dec 2024 01:06:01 -0800 Subject: [PATCH 7/7] Updated output --- samples_test/src/tests/algorithms.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/samples_test/src/tests/algorithms.rs b/samples_test/src/tests/algorithms.rs index 6e8e5bcb7f..413743f010 100644 --- a/samples_test/src/tests/algorithms.rs +++ b/samples_test/src/tests/algorithms.rs @@ -254,12 +254,10 @@ pub const SHOR_EXPECT_DEBUG: Expect = expect![[r#" Found factor=13 Found factorization 143 = 13 * 11 (13, 11)"#]]; -pub const SIMPLEISING_EXPECT: Expect = expect![[r#" - Something. - Something"#]]; -pub const SIMPLEISING_EXPECT_DEBUG: Expect = expect![[r#" - Something. - Something"#]]; +pub const SIMPLEISING_EXPECT: Expect = + expect!["[Zero, Zero, Zero, One, One, Zero, One, One, Zero]"]; +pub const SIMPLEISING_EXPECT_DEBUG: Expect = + expect!["[Zero, Zero, Zero, One, One, Zero, One, One, Zero]"]; pub const SUPERDENSECODING_EXPECT: Expect = expect!["((false, true), (false, true))"]; pub const SUPERDENSECODING_EXPECT_DEBUG: Expect = expect!["((false, true), (false, true))"]; pub const SUPERPOSITION_EXPECT: Expect = expect!["Zero"];