From f1bbf837eab013ca022b97b65365b5fa84fc1a68 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Wed, 10 Jul 2024 19:42:30 -0700 Subject: [PATCH 01/44] working --- samples/testing/dump_operation/README.md | 3 + samples/testing/dump_operation/qsharp.json | 1 + .../testing/dump_operation/src/BellState.qs | 17 +++++ samples/testing/dump_operation/src/SWAP.qs | 16 +++++ .../dump_operation/test_dump_operation.py | 69 +++++++++++++++++++ 5 files changed, 106 insertions(+) create mode 100644 samples/testing/dump_operation/README.md create mode 100644 samples/testing/dump_operation/qsharp.json create mode 100644 samples/testing/dump_operation/src/BellState.qs create mode 100644 samples/testing/dump_operation/src/SWAP.qs create mode 100644 samples/testing/dump_operation/test_dump_operation.py diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md new file mode 100644 index 0000000000..2fe9211169 --- /dev/null +++ b/samples/testing/dump_operation/README.md @@ -0,0 +1,3 @@ +# Various examples to test operations using `dump_operation` python API + + diff --git a/samples/testing/dump_operation/qsharp.json b/samples/testing/dump_operation/qsharp.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/samples/testing/dump_operation/qsharp.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs new file mode 100644 index 0000000000..d73c5685d0 --- /dev/null +++ b/samples/testing/dump_operation/src/BellState.qs @@ -0,0 +1,17 @@ +/// # Sample +/// Multi File Testing Project +/// +/// # Description +/// Organizing code into multiple Q# source files is an important part of +/// writing readable and maintainable code. In this project, we have `SWAP.qs`, +/// and `Particle.qs`, which defines a new namespace for particle operations. +/// The presence of a Q# manifest file (`qsharp.json`) tells the compiler +/// to include all Q# files under `src/`. + +namespace BellState { + operation PrepareBellState(qs : Qubit[]) : Unit is Ctl + Adj { + H(qs[0]); + CNOT(qs[0], qs[1]); + } +} + diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/SWAP.qs new file mode 100644 index 0000000000..3e75f64ca2 --- /dev/null +++ b/samples/testing/dump_operation/src/SWAP.qs @@ -0,0 +1,16 @@ +/// # Sample +/// Multi File Testing Project +/// +/// # Description +/// Organizing code into multiple Q# source files is an important part of +/// writing readable and maintainable code. In this project, we have `SWAP.qs`, +/// and `Particle.qs`, which defines a new namespace for particle operations. +/// The presence of a Q# manifest file (`qsharp.json`) tells the compiler +/// to include all Q# files under `src/`. + +namespace SWAP { + operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { + SWAP(qs[0], qs[1]); + } +} + diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py new file mode 100644 index 0000000000..751e7bc6d0 --- /dev/null +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -0,0 +1,69 @@ +import qsharp +from qsharp.utils import dump_operation + +def test_empty_operation() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + res = dump_operation("qs => ()", 1) + assert res == [ + [complex(1.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(1.0, 0.0)], + ] + + +def test_single_qubit_not_gate() -> None: + res = dump_operation("qs => X(qs[0])", 1) + assert res == [ + [complex(0.0, 0.0), complex(1.0, 0.0)], + [complex(1.0, 0.0), complex(0.0, 0.0)], + ] + +def test_single_qubit_superposition() -> None: + res = dump_operation("qs => H(qs[0])", 1) + assert res == [ + [complex(0.707107, 0.0), complex(0.707107, 0.0)], + [complex(0.707107, 0.0), complex(-0.707107, 0.0)], + ] + +def test_two_qubit_cnot_gate() -> None: + res = dump_operation("qs => CNOT(qs[0], qs[1])", 2) + assert res == [ + [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], + ] + +def test_custom_operation() -> None: + qsharp.eval( + "operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }" + ) + res = dump_operation("ApplySWAP", 2) + + assert res == [ + [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], + ] + +def test_swap_operation_in_qsharp_file() -> None: + qsharp.init(project_root='.') + res = dump_operation("SWAP.ApplySWAP", 2) + + assert res == [ + [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], + ] + +def test_bell_state_operation_in_qsharp_file() -> None: + qsharp.init(project_root='.') + res = dump_operation("BellState.PrepareBellState", 2) + + assert res == [ + [(0.707107+0j), 0j, (0.707107+0j), 0j], + [0j, (0.707107+0j), 0j, (0.707107+0j)], + [0j, (0.707107+0j), 0j, (-0.707107-0j)], + [(0.707107+0j), 0j, (-0.707107-0j), 0j], + ], f"Got {res}" From 0786c0b1baa25706ca36ede8d3c924695658d695 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 13:25:34 -0700 Subject: [PATCH 02/44] modify tests for bell state --- .../testing/dump_operation/src/BellState.qs | 14 +++++- .../dump_operation/test_dump_operation.py | 46 +++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index d73c5685d0..66ad4a5942 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -9,9 +9,21 @@ /// to include all Q# files under `src/`. namespace BellState { - operation PrepareBellState(qs : Qubit[]) : Unit is Ctl + Adj { + operation AllBellStates(qs : Qubit[], choice: Int) : Unit is Ctl + Adj { + open Microsoft.Quantum.Convert; + H(qs[0]); CNOT(qs[0], qs[1]); + + let bitmask = IntAsBoolArray(choice, 2); + if bitmask[1] { + X(qs[1]); + } + + if bitmask[0] { + Z(qs[0]); + } + } } diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 751e7bc6d0..0f57726a0c 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -46,7 +46,7 @@ def test_custom_operation() -> None: [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], ] -def test_swap_operation_in_qsharp_file() -> None: +def test_operation_no_args_in_qsharp_file() -> None: qsharp.init(project_root='.') res = dump_operation("SWAP.ApplySWAP", 2) @@ -57,13 +57,41 @@ def test_swap_operation_in_qsharp_file() -> None: [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], ] -def test_bell_state_operation_in_qsharp_file() -> None: +def test_operation_with_args_in_qsharp_file() -> None: qsharp.init(project_root='.') - res = dump_operation("BellState.PrepareBellState", 2) - assert res == [ - [(0.707107+0j), 0j, (0.707107+0j), 0j], - [0j, (0.707107+0j), 0j, (0.707107+0j)], - [0j, (0.707107+0j), 0j, (-0.707107-0j)], - [(0.707107+0j), 0j, (-0.707107-0j), 0j], - ], f"Got {res}" + res0 = dump_operation("BellState.AllBellStates(_, 0)", 2) + + assert res0 == [ + [complex(0.707107, 0.0), complex(0.0,0.0), complex(0.707107, 0.0), complex(0.0,0.0)], + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0)], + [complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0)], + ] + + res1 = dump_operation("BellState.AllBellStates(_, 1)", 2) + + assert res1 == [ + [complex(0.707107, 0.0), complex(0.0,0.0), complex(0.707107, 0.0), complex(0.0,0.0)], + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], + ] + + res2 = dump_operation("BellState.AllBellStates(_, 2)", 2) + + assert res2 == [ + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], + [complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0)], + ], f"got {res2}" + + res3 = dump_operation("BellState.AllBellStates(_, 3)", 2) + + assert res3 == [ + [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], + [complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], + [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + ] From fd689dcdf3dd04597efb352da37c85bfc3c5a34f Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 13:38:48 -0700 Subject: [PATCH 03/44] update doc comments --- samples/testing/dump_operation/src/BellState.qs | 7 +++++-- samples/testing/dump_operation/src/SWAP.qs | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index 66ad4a5942..bb558fd0c8 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -1,12 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + /// # Sample /// Multi File Testing Project /// /// # Description /// Organizing code into multiple Q# source files is an important part of /// writing readable and maintainable code. In this project, we have `SWAP.qs`, -/// and `Particle.qs`, which defines a new namespace for particle operations. +/// and `BellState.qs`, which contain the operation to be tested. /// The presence of a Q# manifest file (`qsharp.json`) tells the compiler /// to include all Q# files under `src/`. +/// These will be tested by Python wrapper, `test_dump_operation.py` namespace BellState { operation AllBellStates(qs : Qubit[], choice: Int) : Unit is Ctl + Adj { @@ -26,4 +30,3 @@ namespace BellState { } } - diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/SWAP.qs index 3e75f64ca2..e2c18bc7ea 100644 --- a/samples/testing/dump_operation/src/SWAP.qs +++ b/samples/testing/dump_operation/src/SWAP.qs @@ -1,16 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + /// # Sample /// Multi File Testing Project /// /// # Description /// Organizing code into multiple Q# source files is an important part of /// writing readable and maintainable code. In this project, we have `SWAP.qs`, -/// and `Particle.qs`, which defines a new namespace for particle operations. +/// and `BellState.qs`, which contain the operation to be tested. /// The presence of a Q# manifest file (`qsharp.json`) tells the compiler /// to include all Q# files under `src/`. +/// These will be tested by Python wrapper, `test_dump_operation.py` namespace SWAP { operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); } } - From 8033c9f8427da61bc2575089556660e5e0b072a8 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 13:39:05 -0700 Subject: [PATCH 04/44] Add copyright header --- samples/testing/dump_operation/test_dump_operation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 0f57726a0c..56da3bda06 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -1,3 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + import qsharp from qsharp.utils import dump_operation From 10c1f2c5b2c9b8a63a9b319d9e7873448514af40 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 13:40:37 -0700 Subject: [PATCH 05/44] Add README for testing operations --- samples/testing/dump_operation/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 2fe9211169..70e61aa2e9 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -1,3 +1,18 @@ +### Copyright (c) Microsoft Corporation. All rights reserved. +### Licensed under the MIT License. + # Various examples to test operations using `dump_operation` python API +Testing operations in Q# can be done in Python using `dump_operation` API. +Modern QDK doesn't support native Q# tests unlike classic QDK, so we need a Python wrapper. + +This sample outlines a multi-file Q# project that can be tested using Q#. This is organised as follows: +- src + - BellState.qs + - SWAP.qs +- qsharp.json +- README.md +- test_dump_operation.py +Reference Links: +- [Q# Testing guide](https://learn.microsoft.com/en-us/azure/quantum/user-guide/testing-debugging) From d68302ed986fad3c267ef16764cc1c2aadc74aee Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 14:01:55 -0700 Subject: [PATCH 06/44] Add example of using CheckOperationsAreEqual --- .../testing/dump_operation/src/OperationEquivalence.qs | 10 ++++++++++ samples/testing/dump_operation/test_dump_operation.py | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 samples/testing/dump_operation/src/OperationEquivalence.qs diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs new file mode 100644 index 0000000000..b8ed7d743e --- /dev/null +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -0,0 +1,10 @@ +namespace OperationEquivalence { + open Microsoft.Quantum.Diagnostics; + open SWAP; + + operation TestEquivalence(): Unit { + let actual = qs => SWAP.ApplySWAP(qs); + let expected = qs => SWAP.ApplySWAP(qs); + Fact(CheckOperationsAreEqual(2, actual, expected)==true, "Actual and expected operation should be same"); + } +} diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 56da3bda06..51347ac160 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -98,3 +98,8 @@ def test_operation_with_args_in_qsharp_file() -> None: [complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], ] + +def test_operation_equivalence_using_fact() -> None: + qsharp.eval( + "OperationEquivalence.TestEquivalence()" + ) From f769a7171273b6a8bb89baf982841c933acb8569 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 14:05:02 -0700 Subject: [PATCH 07/44] Minor edit --- samples/testing/dump_operation/src/OperationEquivalence.qs | 4 ++-- samples/testing/dump_operation/src/SWAP.qs | 5 ++++- samples/testing/dump_operation/test_dump_operation.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index b8ed7d743e..1f3071c1cb 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -3,8 +3,8 @@ namespace OperationEquivalence { open SWAP; operation TestEquivalence(): Unit { - let actual = qs => SWAP.ApplySWAP(qs); - let expected = qs => SWAP.ApplySWAP(qs); + let actual = qs => SWAP.ApplySWAP1(qs); + let expected = qs => SWAP.ApplySWAP2(qs); Fact(CheckOperationsAreEqual(2, actual, expected)==true, "Actual and expected operation should be same"); } } diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/SWAP.qs index e2c18bc7ea..d0b57a14cb 100644 --- a/samples/testing/dump_operation/src/SWAP.qs +++ b/samples/testing/dump_operation/src/SWAP.qs @@ -13,7 +13,10 @@ /// These will be tested by Python wrapper, `test_dump_operation.py` namespace SWAP { - operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { + operation ApplySWAP1(qs : Qubit[]) : Unit is Ctl + Adj { + SWAP(qs[0], qs[1]); + } + operation ApplySWAP2(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); } } diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 51347ac160..843571510e 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -51,7 +51,7 @@ def test_custom_operation() -> None: def test_operation_no_args_in_qsharp_file() -> None: qsharp.init(project_root='.') - res = dump_operation("SWAP.ApplySWAP", 2) + res = dump_operation("SWAP.ApplySWAP1", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], From 70ff1603ce081798028031cd758636546c5f6c11 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 14:31:32 -0700 Subject: [PATCH 08/44] Update README --- samples/testing/dump_operation/README.md | 47 +++++++++++++++++------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 70e61aa2e9..1cd9a19649 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -1,18 +1,37 @@ -### Copyright (c) Microsoft Corporation. All rights reserved. -### Licensed under the MIT License. +**Copyright (c) Microsoft Corporation. All rights reserved.** +**Licensed under the MIT License.** -# Various examples to test operations using `dump_operation` python API +# Testing Operations in Modern QDK +This sample project demonstrates different approaches to testing operations in Modern QDK, which unlike Classic QDK, doesn't support native Q# tests. -Testing operations in Q# can be done in Python using `dump_operation` API. -Modern QDK doesn't support native Q# tests unlike classic QDK, so we need a Python wrapper. +## Testing Methods + +There are two primary ways to test operations in Modern QDK: + +1. **Dumping Operation Output:** + - Use the `dump_operation` Python API to retrieve the operation's representation and compare it against the expected output. + +2. **Q# `Fact` Assertions:** + - Define a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical. The `Fact` function asserts that the check returns `true`. + +## Project Structure +This sample project is a multi-file Q# project that showcases both testing methods. The project structure is as follows: -This sample outlines a multi-file Q# project that can be tested using Q#. This is organised as follows: - src - - BellState.qs - - SWAP.qs -- qsharp.json -- README.md -- test_dump_operation.py - -Reference Links: -- [Q# Testing guide](https://learn.microsoft.com/en-us/azure/quantum/user-guide/testing-debugging) + - "BellState.qs": Q# file containing the `AllBellStates` operation to be tested + - "SWAP.qs": Q# file containing the `ApplySWAP` operation to be tested + - "OperationEquivalence.qs": Q# file containing the `TestEquivalence` operation to be called in python wrapper +- "qsharp.json": Q# project configuration file +- test_dump_operation.py: "Python wrapper containing tests" + +## Installation +- Install the `qsharp` python package by following the instructions mentioned [here](https://learn.microsoft.com/azure/quantum/install-overview-qdk#add-support-for-python-and-jupyter-notebooks). +- Install `pytest` python package. + +## Running the sample +Open the `samples/testing/dump_operation` directory, and run `pytest` command. + +## Reference Links: +- [Q# Testing guide](https://learn.microsoft.com/azure/quantum/user-guide/testing-debugging). +- [Getting started with modern QDK](https://learn.microsoft.com/azure/quantum/install-overview-qdk) +- [Getting started with Pytest](https://docs.pytest.org/en/stable/getting-started.html) From 6b56785dc9ae71fe9268412e83f5b064c9084079 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 14:55:21 -0700 Subject: [PATCH 09/44] improve doc comment --- .../testing/dump_operation/src/BellState.qs | 31 ++++++++++++++----- .../src/OperationEquivalence.qs | 22 ++++++++++++- samples/testing/dump_operation/src/SWAP.qs | 17 ++++++++-- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index bb558fd0c8..005aa92640 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -2,17 +2,34 @@ // Licensed under the MIT License. /// # Sample -/// Multi File Testing Project +/// Multi File Testing Project (Refer to README for Project Overview) /// /// # Description -/// Organizing code into multiple Q# source files is an important part of -/// writing readable and maintainable code. In this project, we have `SWAP.qs`, -/// and `BellState.qs`, which contain the operation to be tested. -/// The presence of a Q# manifest file (`qsharp.json`) tells the compiler -/// to include all Q# files under `src/`. -/// These will be tested by Python wrapper, `test_dump_operation.py` +/// This code builds upon the concepts explained in the README file, +/// demonstrating how to organize Q# code into multiple files for testing. +/// Here, we have separate files (`BellState.qs`, `SWAP.qs`, and `OperationEquivalence.qs`) +/// containing individual operations under test. + +/// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler +/// to include all Q# files within the `src` directory. These operations are tested +/// by the Python wrapper script, `test_dump_operation.py`. + namespace BellState { + /// # Summary + /// Operation that generates all bell states for testing with `dump_operation.py`. + /// + /// # Input + /// ## qs + /// Input qubit register + /// + /// ## choice + /// Bell state to construct. + /// 0: |Φ+〉(PhiPlus) + /// 1: |Φ-〉(PhiMinus) + /// 2: |Ψ+〉(PsiPlus) + /// 3: |Ψ-〉(PsiMinus) + operation AllBellStates(qs : Qubit[], choice: Int) : Unit is Ctl + Adj { open Microsoft.Quantum.Convert; diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index 1f3071c1cb..70bed2f611 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -1,7 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +/// # Sample +/// Multi File Testing Project (Refer to README for Project Overview) +/// +/// # Description +/// This code builds upon the concepts explained in the README file, +/// demonstrating how to organize Q# code into multiple files for testing. +/// Here, we have separate files (`BellState.qs`, `SWAP.qs`, and `OperationEquivalence.qs`) +/// containing individual operations under test. + +/// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler +/// to include all Q# files within the `src` directory. These operations are tested +/// by the Python wrapper script, `test_dump_operation.py`. + + + namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; open SWAP; - + /// # Summary + /// Verifies the equivalence of quantum operations using `Fact` function + /// and the `CheckOperationsAreEqual` operation. operation TestEquivalence(): Unit { let actual = qs => SWAP.ApplySWAP1(qs); let expected = qs => SWAP.ApplySWAP2(qs); diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/SWAP.qs index d0b57a14cb..d2aee82b33 100644 --- a/samples/testing/dump_operation/src/SWAP.qs +++ b/samples/testing/dump_operation/src/SWAP.qs @@ -6,16 +6,29 @@ /// /// # Description /// Organizing code into multiple Q# source files is an important part of -/// writing readable and maintainable code. In this project, we have `SWAP.qs`, -/// and `BellState.qs`, which contain the operation to be tested. +/// writing readable and maintainable code. In this project, we have `BellState.qs`, `SWAP.qs`, +/// and `OperationEquivalence.qs`, which contain the operation to be tested. /// The presence of a Q# manifest file (`qsharp.json`) tells the compiler /// to include all Q# files under `src/`. /// These will be tested by Python wrapper, `test_dump_operation.py` namespace SWAP { + /// # Summary + /// Operation for testing with `dump_operation.py` and `TestEquivalence` operation. + /// + /// # Input + /// ## qs + /// Input qubit register operation ApplySWAP1(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); } + + // # Summary + /// Operation for testing with `TestEquivalence` operation. + /// + /// # Input + /// ## qs + /// Input qubit register operation ApplySWAP2(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); } From de8ff4f15a0431afedd4b66bde785c35129d274b Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 14:59:47 -0700 Subject: [PATCH 10/44] Run Q# formatter --- samples/testing/dump_operation/src/BellState.qs | 4 ++-- samples/testing/dump_operation/src/OperationEquivalence.qs | 4 ++-- samples/testing/dump_operation/src/SWAP.qs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index 005aa92640..99d4121165 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -30,8 +30,8 @@ namespace BellState { /// 2: |Ψ+〉(PsiPlus) /// 3: |Ψ-〉(PsiMinus) - operation AllBellStates(qs : Qubit[], choice: Int) : Unit is Ctl + Adj { - open Microsoft.Quantum.Convert; + operation AllBellStates(qs : Qubit[], choice : Int) : Unit is Ctl + Adj { + open Microsoft.Quantum.Convert; H(qs[0]); CNOT(qs[0], qs[1]); diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index 70bed2f611..04ae618133 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -22,9 +22,9 @@ namespace OperationEquivalence { /// # Summary /// Verifies the equivalence of quantum operations using `Fact` function /// and the `CheckOperationsAreEqual` operation. - operation TestEquivalence(): Unit { + operation TestEquivalence() : Unit { let actual = qs => SWAP.ApplySWAP1(qs); let expected = qs => SWAP.ApplySWAP2(qs); - Fact(CheckOperationsAreEqual(2, actual, expected)==true, "Actual and expected operation should be same"); + Fact(CheckOperationsAreEqual(2, actual, expected) == true, "Actual and expected operation should be same"); } } diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/SWAP.qs index d2aee82b33..bdb5c9b827 100644 --- a/samples/testing/dump_operation/src/SWAP.qs +++ b/samples/testing/dump_operation/src/SWAP.qs @@ -20,7 +20,7 @@ namespace SWAP { /// ## qs /// Input qubit register operation ApplySWAP1(qs : Qubit[]) : Unit is Ctl + Adj { - SWAP(qs[0], qs[1]); + SWAP(qs[0], qs[1]); } // # Summary @@ -30,6 +30,6 @@ namespace SWAP { /// ## qs /// Input qubit register operation ApplySWAP2(qs : Qubit[]) : Unit is Ctl + Adj { - SWAP(qs[0], qs[1]); + SWAP(qs[0], qs[1]); } } From 26b7174f62e6cd246f5325b5759c554af32d5be6 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Thu, 11 Jul 2024 15:10:02 -0700 Subject: [PATCH 11/44] restore new line --- samples/testing/dump_operation/qsharp.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/testing/dump_operation/qsharp.json b/samples/testing/dump_operation/qsharp.json index 9e26dfeeb6..0967ef424b 100644 --- a/samples/testing/dump_operation/qsharp.json +++ b/samples/testing/dump_operation/qsharp.json @@ -1 +1 @@ -{} \ No newline at end of file +{} From ae48a1fa870e0e31e5515494bf44981485bdb2a7 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 18:45:52 -0700 Subject: [PATCH 12/44] Run testing samples in CI --- build.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/build.py b/build.py index 4bffd4733c..5214f0eb83 100755 --- a/build.py +++ b/build.py @@ -410,6 +410,26 @@ def run_python_integration_tests(cwd, interpreter): ) step_end() + step_start("Running qsharp testing samples") + + test_projects_directories = [ dir + for dir, _, _ in project_directories + if dir.find("testing") != -1 + ] + + interpreter = use_python_env(pip_src) + + command_args = [interpreter, "-m", "pytest"] + + for test_project_dir in test_projects_directories: + subprocess.run( + command_args, + check=True, + text=True, + cwd=test_project_dir, + ) + step_end() + if build_npm: step_start("Building the npm package") # Copy the wasm build files over for web and node targets From d27b39e76284422f79dc7c3d1a4c6630d58ae292 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 18:49:25 -0700 Subject: [PATCH 13/44] cleanup --- samples/testing/dump_operation/test_dump_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 843571510e..2e94b32aa9 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -88,7 +88,7 @@ def test_operation_with_args_in_qsharp_file() -> None: [complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], [complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0)], - ], f"got {res2}" + ] res3 = dump_operation("BellState.AllBellStates(_, 3)", 2) From 678a7698991a467e091e17cf085b7943576e9dd1 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 19:10:38 -0700 Subject: [PATCH 14/44] whitespace fix --- samples/testing/dump_operation/src/BellState.qs | 1 - samples/testing/dump_operation/src/OperationEquivalence.qs | 2 -- 2 files changed, 3 deletions(-) diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index 99d4121165..f0a70e8450 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -14,7 +14,6 @@ /// to include all Q# files within the `src` directory. These operations are tested /// by the Python wrapper script, `test_dump_operation.py`. - namespace BellState { /// # Summary /// Operation that generates all bell states for testing with `dump_operation.py`. diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index 04ae618133..c557a4f30b 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -14,8 +14,6 @@ /// to include all Q# files within the `src` directory. These operations are tested /// by the Python wrapper script, `test_dump_operation.py`. - - namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; open SWAP; From 6c9d70cb8838b9a1ceb5678bf1a59edfc0df41fe Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 20:03:19 -0700 Subject: [PATCH 15/44] try to fix ci --- build.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/build.py b/build.py index 5214f0eb83..449dd61f00 100755 --- a/build.py +++ b/build.py @@ -412,22 +412,18 @@ def run_python_integration_tests(cwd, interpreter): step_start("Running qsharp testing samples") + python_bin = use_python_env(pip_src) + + install_python_test_requirements(pip_src, python_bin) + install_qsharp_python_package(pip_src, wheels_dir, python_bin) + test_projects_directories = [ dir for dir, _, _ in project_directories if dir.find("testing") != -1 ] - interpreter = use_python_env(pip_src) - - command_args = [interpreter, "-m", "pytest"] - for test_project_dir in test_projects_directories: - subprocess.run( - command_args, - check=True, - text=True, - cwd=test_project_dir, - ) + run_python_tests(test_project_dir, python_bin) step_end() if build_npm: From c65b04dfe647e4fb77aebc8dad6410f5ad465ccc Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 20:09:00 -0700 Subject: [PATCH 16/44] add test_requirements.txt --- samples/testing/dump_operation/test_requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 samples/testing/dump_operation/test_requirements.txt diff --git a/samples/testing/dump_operation/test_requirements.txt b/samples/testing/dump_operation/test_requirements.txt new file mode 100644 index 0000000000..e079f8a603 --- /dev/null +++ b/samples/testing/dump_operation/test_requirements.txt @@ -0,0 +1 @@ +pytest From c9d9f020af93a715b819005e71aced3abcbd89f7 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 12 Jul 2024 20:10:12 -0700 Subject: [PATCH 17/44] Dont execute samples for testing from Q# cmd line --- build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.py b/build.py index 449dd61f00..05a16a16e9 100755 --- a/build.py +++ b/build.py @@ -394,7 +394,7 @@ def run_python_integration_tests(cwd, interpreter): os.path.join(dp, f) for dp, _, filenames in project_directories for f in filenames - if f == "qsharp.json" + if f == "qsharp.json" and dp.find("testing") == -1 ] cargo_args = ["cargo", "run", "--bin", "qsc"] if build_type == "release": From 636df45e38d6307be8031ce26b56616576e91b93 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Sat, 13 Jul 2024 23:09:00 -0700 Subject: [PATCH 18/44] Move to integration tests step in CI --- build.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/build.py b/build.py index 05a16a16e9..50e86486bc 100755 --- a/build.py +++ b/build.py @@ -410,22 +410,6 @@ def run_python_integration_tests(cwd, interpreter): ) step_end() - step_start("Running qsharp testing samples") - - python_bin = use_python_env(pip_src) - - install_python_test_requirements(pip_src, python_bin) - install_qsharp_python_package(pip_src, wheels_dir, python_bin) - - test_projects_directories = [ dir - for dir, _, _ in project_directories - if dir.find("testing") != -1 - ] - - for test_project_dir in test_projects_directories: - run_python_tests(test_project_dir, python_bin) - step_end() - if build_npm: step_start("Building the npm package") # Copy the wasm build files over for web and node targets @@ -577,3 +561,17 @@ def run_python_integration_tests(cwd, interpreter): raise Exception(f"Error running {notebook}") step_end() + + step_start("Running qsharp testing samples") + project_directories = [ + dir for dir in os.walk(samples_src) if "qsharp.json" in dir[2] + ] + + test_projects_directories = [ dir + for dir, _, _ in project_directories + if dir.find("testing") != -1 + ] + + for test_project_dir in test_projects_directories: + run_python_tests(test_project_dir, python_bin) + step_end() From a5e1779021094054bad639e9a330b973acb3c855 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Sat, 13 Jul 2024 23:31:23 -0700 Subject: [PATCH 19/44] whitespace --- samples/testing/dump_operation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 1cd9a19649..40337387a0 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -1,4 +1,4 @@ -**Copyright (c) Microsoft Corporation. All rights reserved.** +**Copyright (c) Microsoft Corporation. All rights reserved.** **Licensed under the MIT License.** # Testing Operations in Modern QDK From 6f9a0fd1de02f5e6348ad98b7f63c185ffb14865 Mon Sep 17 00:00:00 2001 From: Manvi-Agrawal <40084144+Manvi-Agrawal@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:38:20 -0700 Subject: [PATCH 20/44] Apply suggestions from code review Co-authored-by: Stefan J. Wernli --- samples/testing/dump_operation/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 40337387a0..0e0adaf502 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -1,12 +1,12 @@ **Copyright (c) Microsoft Corporation. All rights reserved.** **Licensed under the MIT License.** -# Testing Operations in Modern QDK -This sample project demonstrates different approaches to testing operations in Modern QDK, which unlike Classic QDK, doesn't support native Q# tests. +# Testing Operations in the QDK +This sample project demonstrates different approaches to testing operations in the QDK, both via Python and within Q# itself. ## Testing Methods -There are two primary ways to test operations in Modern QDK: +There are two primary ways to test operations in the QDK: 1. **Dumping Operation Output:** - Use the `dump_operation` Python API to retrieve the operation's representation and compare it against the expected output. @@ -33,5 +33,5 @@ Open the `samples/testing/dump_operation` directory, and run `pytest` command. ## Reference Links: - [Q# Testing guide](https://learn.microsoft.com/azure/quantum/user-guide/testing-debugging). -- [Getting started with modern QDK](https://learn.microsoft.com/azure/quantum/install-overview-qdk) +- [Getting started with the QDK](https://learn.microsoft.com/azure/quantum/install-overview-qdk) - [Getting started with Pytest](https://docs.pytest.org/en/stable/getting-started.html) From b12b0a356f86cfdb982d6c13e7155f3831bea632 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 16 Jul 2024 22:53:42 -0700 Subject: [PATCH 21/44] PR feedback --- samples/testing/dump_operation/src/OperationEquivalence.qs | 6 +++--- .../testing/dump_operation/src/{SWAP.qs => Test_SWAP.qs} | 6 ++++-- samples/testing/dump_operation/test_dump_operation.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) rename samples/testing/dump_operation/src/{SWAP.qs => Test_SWAP.qs} (88%) diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index c557a4f30b..8aadb0ebff 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -16,13 +16,13 @@ namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; - open SWAP; + open Test_SWAP; /// # Summary /// Verifies the equivalence of quantum operations using `Fact` function /// and the `CheckOperationsAreEqual` operation. operation TestEquivalence() : Unit { - let actual = qs => SWAP.ApplySWAP1(qs); - let expected = qs => SWAP.ApplySWAP2(qs); + let actual = qs => Test_SWAP.ApplySWAP1(qs); + let expected = qs => Test_SWAP.ApplySWAP2(qs); Fact(CheckOperationsAreEqual(2, actual, expected) == true, "Actual and expected operation should be same"); } } diff --git a/samples/testing/dump_operation/src/SWAP.qs b/samples/testing/dump_operation/src/Test_SWAP.qs similarity index 88% rename from samples/testing/dump_operation/src/SWAP.qs rename to samples/testing/dump_operation/src/Test_SWAP.qs index bdb5c9b827..566365fd41 100644 --- a/samples/testing/dump_operation/src/SWAP.qs +++ b/samples/testing/dump_operation/src/Test_SWAP.qs @@ -12,7 +12,7 @@ /// to include all Q# files under `src/`. /// These will be tested by Python wrapper, `test_dump_operation.py` -namespace SWAP { +namespace Test_SWAP { /// # Summary /// Operation for testing with `dump_operation.py` and `TestEquivalence` operation. /// @@ -30,6 +30,8 @@ namespace SWAP { /// ## qs /// Input qubit register operation ApplySWAP2(qs : Qubit[]) : Unit is Ctl + Adj { - SWAP(qs[0], qs[1]); + CNOT(qs[0], qs[1]); // a, a xor b + CNOT(qs[1], qs[0]); // b, a xor b + CNOT(qs[0], qs[1]); // b, a } } diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 2e94b32aa9..3dc02fa68c 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -51,7 +51,7 @@ def test_custom_operation() -> None: def test_operation_no_args_in_qsharp_file() -> None: qsharp.init(project_root='.') - res = dump_operation("SWAP.ApplySWAP1", 2) + res = dump_operation("Test_SWAP.ApplySWAP1", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], From 98310be01c32272e9543314d381b288f572e1f33 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 16 Jul 2024 22:54:06 -0700 Subject: [PATCH 22/44] doc comment update --- samples/testing/dump_operation/README.md | 2 +- samples/testing/dump_operation/src/BellState.qs | 2 +- samples/testing/dump_operation/src/OperationEquivalence.qs | 2 +- samples/testing/dump_operation/src/Test_SWAP.qs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 40337387a0..5e4931598a 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -19,7 +19,7 @@ This sample project is a multi-file Q# project that showcases both testing metho - src - "BellState.qs": Q# file containing the `AllBellStates` operation to be tested - - "SWAP.qs": Q# file containing the `ApplySWAP` operation to be tested + - "Test_SWAP.qs": Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested - "OperationEquivalence.qs": Q# file containing the `TestEquivalence` operation to be called in python wrapper - "qsharp.json": Q# project configuration file - test_dump_operation.py: "Python wrapper containing tests" diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/dump_operation/src/BellState.qs index f0a70e8450..b380f4b71a 100644 --- a/samples/testing/dump_operation/src/BellState.qs +++ b/samples/testing/dump_operation/src/BellState.qs @@ -7,7 +7,7 @@ /// # Description /// This code builds upon the concepts explained in the README file, /// demonstrating how to organize Q# code into multiple files for testing. -/// Here, we have separate files (`BellState.qs`, `SWAP.qs`, and `OperationEquivalence.qs`) +/// Here, we have separate files (`BellState.qs`, `Test_SWAP.qs`, and `OperationEquivalence.qs`) /// containing individual operations under test. /// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/dump_operation/src/OperationEquivalence.qs index 8aadb0ebff..eb287ae88b 100644 --- a/samples/testing/dump_operation/src/OperationEquivalence.qs +++ b/samples/testing/dump_operation/src/OperationEquivalence.qs @@ -7,7 +7,7 @@ /// # Description /// This code builds upon the concepts explained in the README file, /// demonstrating how to organize Q# code into multiple files for testing. -/// Here, we have separate files (`BellState.qs`, `SWAP.qs`, and `OperationEquivalence.qs`) +/// Here, we have separate files (`BellState.qs`, `Test_SWAP.qs`, and `OperationEquivalence.qs`) /// containing individual operations under test. /// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler diff --git a/samples/testing/dump_operation/src/Test_SWAP.qs b/samples/testing/dump_operation/src/Test_SWAP.qs index 566365fd41..b7587433f9 100644 --- a/samples/testing/dump_operation/src/Test_SWAP.qs +++ b/samples/testing/dump_operation/src/Test_SWAP.qs @@ -6,7 +6,7 @@ /// /// # Description /// Organizing code into multiple Q# source files is an important part of -/// writing readable and maintainable code. In this project, we have `BellState.qs`, `SWAP.qs`, +/// writing readable and maintainable code. In this project, we have `BellState.qs`, `Test_SWAP.qs`, /// and `OperationEquivalence.qs`, which contain the operation to be tested. /// The presence of a Q# manifest file (`qsharp.json`) tells the compiler /// to include all Q# files under `src/`. From f89dea38a5984b4a4fcb37fefbb3f046db40be39 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 16 Jul 2024 22:58:59 -0700 Subject: [PATCH 23/44] minor edit --- .../dump_operation/test_dump_operation.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index 3dc02fa68c..f23acc971d 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -6,6 +6,7 @@ def test_empty_operation() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + res = dump_operation("qs => ()", 1) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0)], @@ -14,6 +15,8 @@ def test_empty_operation() -> None: def test_single_qubit_not_gate() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + res = dump_operation("qs => X(qs[0])", 1) assert res == [ [complex(0.0, 0.0), complex(1.0, 0.0)], @@ -21,6 +24,8 @@ def test_single_qubit_not_gate() -> None: ] def test_single_qubit_superposition() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + res = dump_operation("qs => H(qs[0])", 1) assert res == [ [complex(0.707107, 0.0), complex(0.707107, 0.0)], @@ -28,6 +33,8 @@ def test_single_qubit_superposition() -> None: ] def test_two_qubit_cnot_gate() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + res = dump_operation("qs => CNOT(qs[0], qs[1])", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], @@ -37,11 +44,13 @@ def test_two_qubit_cnot_gate() -> None: ] def test_custom_operation() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + qsharp.eval( "operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }" ) - res = dump_operation("ApplySWAP", 2) + res = dump_operation("ApplySWAP", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], @@ -50,9 +59,10 @@ def test_custom_operation() -> None: ] def test_operation_no_args_in_qsharp_file() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') - res = dump_operation("Test_SWAP.ApplySWAP1", 2) + res = dump_operation("Test_SWAP.ApplySWAP1", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], @@ -61,6 +71,7 @@ def test_operation_no_args_in_qsharp_file() -> None: ] def test_operation_with_args_in_qsharp_file() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') res0 = dump_operation("BellState.AllBellStates(_, 0)", 2) @@ -100,6 +111,9 @@ def test_operation_with_args_in_qsharp_file() -> None: ] def test_operation_equivalence_using_fact() -> None: + qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + qsharp.init(project_root='.') + qsharp.eval( "OperationEquivalence.TestEquivalence()" ) From 5b4d0498c42ddd6fb010abaf75d17ced3a1d643a Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Sat, 20 Jul 2024 20:32:15 -0700 Subject: [PATCH 24/44] identation fix --- build.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build.py b/build.py index 50e86486bc..4ed2f5e52a 100755 --- a/build.py +++ b/build.py @@ -563,15 +563,15 @@ def run_python_integration_tests(cwd, interpreter): step_end() step_start("Running qsharp testing samples") - project_directories = [ - dir for dir in os.walk(samples_src) if "qsharp.json" in dir[2] - ] + project_directories = [ + dir for dir in os.walk(samples_src) if "qsharp.json" in dir[2] + ] - test_projects_directories = [ dir - for dir, _, _ in project_directories - if dir.find("testing") != -1 - ] + test_projects_directories = [ dir + for dir, _, _ in project_directories + if dir.find("testing") != -1 + ] - for test_project_dir in test_projects_directories: - run_python_tests(test_project_dir, python_bin) + for test_project_dir in test_projects_directories: + run_python_tests(test_project_dir, python_bin) step_end() From f23b9b727cc9149ec0635b56691557f6fdb43a63 Mon Sep 17 00:00:00 2001 From: Manvi-Agrawal <40084144+Manvi-Agrawal@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:19:50 -0700 Subject: [PATCH 25/44] Apply suggestions from code review Co-authored-by: Mariia Mykhailova --- samples/testing/dump_operation/README.md | 6 +++--- samples/testing/dump_operation/test_dump_operation.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 982bb94d68..b935e90c38 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -8,11 +8,11 @@ This sample project demonstrates different approaches to testing operations in t There are two primary ways to test operations in the QDK: -1. **Dumping Operation Output:** - - Use the `dump_operation` Python API to retrieve the operation's representation and compare it against the expected output. +1. **Using Operation Matrix Representation:** + - Use the `dump_operation` Python API to retrieve the operation's representation as a matrix and compare it against the expected matrix. 2. **Q# `Fact` Assertions:** - - Define a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical. The `Fact` function asserts that the check returns `true`. + - Use a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical. The `Fact` function asserts that the check returns `true`. ## Project Structure This sample project is a multi-file Q# project that showcases both testing methods. The project structure is as follows: diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/dump_operation/test_dump_operation.py index f23acc971d..a0574439c2 100644 --- a/samples/testing/dump_operation/test_dump_operation.py +++ b/samples/testing/dump_operation/test_dump_operation.py @@ -23,7 +23,7 @@ def test_single_qubit_not_gate() -> None: [complex(1.0, 0.0), complex(0.0, 0.0)], ] -def test_single_qubit_superposition() -> None: +def test_single_qubit_hadamard_gate() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) res = dump_operation("qs => H(qs[0])", 1) From a64d6d8d9e0c3a333893ea8ea9bc8bb0c6956cb9 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:18:56 -0700 Subject: [PATCH 26/44] remove copyright from readme --- samples/testing/dump_operation/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 982bb94d68..fe3d067bed 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -1,6 +1,3 @@ -**Copyright (c) Microsoft Corporation. All rights reserved.** -**Licensed under the MIT License.** - # Testing Operations in the QDK This sample project demonstrates different approaches to testing operations in the QDK, both via Python and within Q# itself. From a7d7a4655e75ef24863e3aac0bfcee60dd92d86d Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:21:34 -0700 Subject: [PATCH 27/44] polish readme --- samples/testing/dump_operation/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 84555a6d27..4d3c45bfd9 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -15,9 +15,9 @@ There are two primary ways to test operations in the QDK: This sample project is a multi-file Q# project that showcases both testing methods. The project structure is as follows: - src - - "BellState.qs": Q# file containing the `AllBellStates` operation to be tested - - "Test_SWAP.qs": Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested - - "OperationEquivalence.qs": Q# file containing the `TestEquivalence` operation to be called in python wrapper + - `BellState.qs`: Q# file containing the `AllBellStates` operation to be tested + - `Test_SWAP.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested + - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in python wrapper - "qsharp.json": Q# project configuration file - test_dump_operation.py: "Python wrapper containing tests" From 7b121ebf29a01bdf8df553d2a32257316e2f7967 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:23:33 -0700 Subject: [PATCH 28/44] polish readme.. --- samples/testing/dump_operation/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/dump_operation/README.md index 4d3c45bfd9..037cef1bf0 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/dump_operation/README.md @@ -18,8 +18,8 @@ This sample project is a multi-file Q# project that showcases both testing metho - `BellState.qs`: Q# file containing the `AllBellStates` operation to be tested - `Test_SWAP.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in python wrapper -- "qsharp.json": Q# project configuration file -- test_dump_operation.py: "Python wrapper containing tests" +- `qsharp.json`: Q# project configuration file +- `test_dump_operation.py`: Python wrapper containing tests. ## Installation - Install the `qsharp` python package by following the instructions mentioned [here](https://learn.microsoft.com/azure/quantum/install-overview-qdk#add-support-for-python-and-jupyter-notebooks). From d500517909caf0527520ddf793ec015b4ffc937f Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:27:13 -0700 Subject: [PATCH 29/44] rename dir --- samples/testing/{dump_operation => operations}/README.md | 2 +- samples/testing/{dump_operation => operations}/qsharp.json | 0 samples/testing/{dump_operation => operations}/src/BellState.qs | 0 .../{dump_operation => operations}/src/OperationEquivalence.qs | 0 samples/testing/{dump_operation => operations}/src/Test_SWAP.qs | 0 .../test_dump_operation.py => operations/test_operations.py} | 0 .../{dump_operation => operations}/test_requirements.txt | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename samples/testing/{dump_operation => operations}/README.md (95%) rename samples/testing/{dump_operation => operations}/qsharp.json (100%) rename samples/testing/{dump_operation => operations}/src/BellState.qs (100%) rename samples/testing/{dump_operation => operations}/src/OperationEquivalence.qs (100%) rename samples/testing/{dump_operation => operations}/src/Test_SWAP.qs (100%) rename samples/testing/{dump_operation/test_dump_operation.py => operations/test_operations.py} (100%) rename samples/testing/{dump_operation => operations}/test_requirements.txt (100%) diff --git a/samples/testing/dump_operation/README.md b/samples/testing/operations/README.md similarity index 95% rename from samples/testing/dump_operation/README.md rename to samples/testing/operations/README.md index 037cef1bf0..024c521652 100644 --- a/samples/testing/dump_operation/README.md +++ b/samples/testing/operations/README.md @@ -26,7 +26,7 @@ This sample project is a multi-file Q# project that showcases both testing metho - Install `pytest` python package. ## Running the sample -Open the `samples/testing/dump_operation` directory, and run `pytest` command. +Open the `samples/testing/operations` directory, and run `pytest` command. ## Reference Links: - [Q# Testing guide](https://learn.microsoft.com/azure/quantum/user-guide/testing-debugging). diff --git a/samples/testing/dump_operation/qsharp.json b/samples/testing/operations/qsharp.json similarity index 100% rename from samples/testing/dump_operation/qsharp.json rename to samples/testing/operations/qsharp.json diff --git a/samples/testing/dump_operation/src/BellState.qs b/samples/testing/operations/src/BellState.qs similarity index 100% rename from samples/testing/dump_operation/src/BellState.qs rename to samples/testing/operations/src/BellState.qs diff --git a/samples/testing/dump_operation/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs similarity index 100% rename from samples/testing/dump_operation/src/OperationEquivalence.qs rename to samples/testing/operations/src/OperationEquivalence.qs diff --git a/samples/testing/dump_operation/src/Test_SWAP.qs b/samples/testing/operations/src/Test_SWAP.qs similarity index 100% rename from samples/testing/dump_operation/src/Test_SWAP.qs rename to samples/testing/operations/src/Test_SWAP.qs diff --git a/samples/testing/dump_operation/test_dump_operation.py b/samples/testing/operations/test_operations.py similarity index 100% rename from samples/testing/dump_operation/test_dump_operation.py rename to samples/testing/operations/test_operations.py diff --git a/samples/testing/dump_operation/test_requirements.txt b/samples/testing/operations/test_requirements.txt similarity index 100% rename from samples/testing/dump_operation/test_requirements.txt rename to samples/testing/operations/test_requirements.txt From 3a80844f805f6fcc6e8758f505e46eabdd56357b Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:33:36 -0700 Subject: [PATCH 30/44] Doc comment --- samples/testing/operations/README.md | 2 +- samples/testing/operations/src/BellState.qs | 6 ------ samples/testing/operations/src/OperationEquivalence.qs | 6 ------ samples/testing/operations/src/Test_SWAP.qs | 8 ++------ 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/samples/testing/operations/README.md b/samples/testing/operations/README.md index 024c521652..607599fb26 100644 --- a/samples/testing/operations/README.md +++ b/samples/testing/operations/README.md @@ -18,7 +18,7 @@ This sample project is a multi-file Q# project that showcases both testing metho - `BellState.qs`: Q# file containing the `AllBellStates` operation to be tested - `Test_SWAP.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in python wrapper -- `qsharp.json`: Q# project configuration file +- `qsharp.json`: Q# project manifest file, instructing compiler to include all files in `src` directory. - `test_dump_operation.py`: Python wrapper containing tests. ## Installation diff --git a/samples/testing/operations/src/BellState.qs b/samples/testing/operations/src/BellState.qs index b380f4b71a..35c47795e8 100644 --- a/samples/testing/operations/src/BellState.qs +++ b/samples/testing/operations/src/BellState.qs @@ -7,12 +7,6 @@ /// # Description /// This code builds upon the concepts explained in the README file, /// demonstrating how to organize Q# code into multiple files for testing. -/// Here, we have separate files (`BellState.qs`, `Test_SWAP.qs`, and `OperationEquivalence.qs`) -/// containing individual operations under test. - -/// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler -/// to include all Q# files within the `src` directory. These operations are tested -/// by the Python wrapper script, `test_dump_operation.py`. namespace BellState { /// # Summary diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index eb287ae88b..a299e99826 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -7,12 +7,6 @@ /// # Description /// This code builds upon the concepts explained in the README file, /// demonstrating how to organize Q# code into multiple files for testing. -/// Here, we have separate files (`BellState.qs`, `Test_SWAP.qs`, and `OperationEquivalence.qs`) -/// containing individual operations under test. - -/// The presence of a Q# manifest file (`qsharp.json`) instructs the compiler -/// to include all Q# files within the `src` directory. These operations are tested -/// by the Python wrapper script, `test_dump_operation.py`. namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; diff --git a/samples/testing/operations/src/Test_SWAP.qs b/samples/testing/operations/src/Test_SWAP.qs index b7587433f9..762e56bf65 100644 --- a/samples/testing/operations/src/Test_SWAP.qs +++ b/samples/testing/operations/src/Test_SWAP.qs @@ -5,12 +5,8 @@ /// Multi File Testing Project /// /// # Description -/// Organizing code into multiple Q# source files is an important part of -/// writing readable and maintainable code. In this project, we have `BellState.qs`, `Test_SWAP.qs`, -/// and `OperationEquivalence.qs`, which contain the operation to be tested. -/// The presence of a Q# manifest file (`qsharp.json`) tells the compiler -/// to include all Q# files under `src/`. -/// These will be tested by Python wrapper, `test_dump_operation.py` +/// This code builds upon the concepts explained in the README file, +/// demonstrating how to organize Q# code into multiple files for testing. namespace Test_SWAP { /// # Summary From bc6cd108996cc63689346389a4066f02dc7c4483 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 12:42:57 -0700 Subject: [PATCH 31/44] minor edit --- samples/testing/operations/src/OperationEquivalence.qs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index a299e99826..4733304591 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -13,10 +13,12 @@ namespace OperationEquivalence { open Test_SWAP; /// # Summary /// Verifies the equivalence of quantum operations using `Fact` function - /// and the `CheckOperationsAreEqual` operation. + /// and the `CheckOperationsAreEqual` operation. You can either run this here, + /// by clicking `Run` in VsCode or call `TestEquivalence` operation in python. + @EntryPoint() operation TestEquivalence() : Unit { let actual = qs => Test_SWAP.ApplySWAP1(qs); let expected = qs => Test_SWAP.ApplySWAP2(qs); - Fact(CheckOperationsAreEqual(2, actual, expected) == true, "Actual and expected operation should be same"); + Fact(CheckOperationsAreEqual(2, actual, expected), "Actual and expected operation should be same"); } } From 9ea3cd3f3a6415c7da1a065a0f4eb9e54c78b3c8 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 13:08:04 -0700 Subject: [PATCH 32/44] use lambda appropriately --- .../operations/src/OperationEquivalence.qs | 4 +-- samples/testing/operations/src/Test_SWAP.qs | 26 +++++++------------ samples/testing/operations/test_operations.py | 5 ++-- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index 4733304591..a8103fa538 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -17,8 +17,8 @@ namespace OperationEquivalence { /// by clicking `Run` in VsCode or call `TestEquivalence` operation in python. @EntryPoint() operation TestEquivalence() : Unit { - let actual = qs => Test_SWAP.ApplySWAP1(qs); - let expected = qs => Test_SWAP.ApplySWAP2(qs); + let actual = qs => Test_SWAP.ApplySWAP(qs[0], qs[1]); + let expected = qs => SWAP(qs[0], qs[1]); Fact(CheckOperationsAreEqual(2, actual, expected), "Actual and expected operation should be same"); } } diff --git a/samples/testing/operations/src/Test_SWAP.qs b/samples/testing/operations/src/Test_SWAP.qs index 762e56bf65..7809ab3d5c 100644 --- a/samples/testing/operations/src/Test_SWAP.qs +++ b/samples/testing/operations/src/Test_SWAP.qs @@ -9,25 +9,17 @@ /// demonstrating how to organize Q# code into multiple files for testing. namespace Test_SWAP { - /// # Summary - /// Operation for testing with `dump_operation.py` and `TestEquivalence` operation. - /// - /// # Input - /// ## qs - /// Input qubit register - operation ApplySWAP1(qs : Qubit[]) : Unit is Ctl + Adj { - SWAP(qs[0], qs[1]); - } - // # Summary - /// Operation for testing with `TestEquivalence` operation. + /// CNOT based operation for testing with `TestEquivalence` operation. /// /// # Input - /// ## qs - /// Input qubit register - operation ApplySWAP2(qs : Qubit[]) : Unit is Ctl + Adj { - CNOT(qs[0], qs[1]); // a, a xor b - CNOT(qs[1], qs[0]); // b, a xor b - CNOT(qs[0], qs[1]); // b, a + /// ## q1 + /// First input qubit + /// ## q2 + /// Second input qubit + operation ApplySWAP(q1: Qubit, q2: Qubit) : Unit is Ctl + Adj { + CNOT(q1, q2); // q1, q1 xor q2 + CNOT(q2, q1); // q2, q1 xor q2 + CNOT(q1, q2); // q2, q1 } } diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index a0574439c2..9451d27c9b 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -6,7 +6,7 @@ def test_empty_operation() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) - + res = dump_operation("qs => ()", 1) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0)], @@ -62,7 +62,7 @@ def test_operation_no_args_in_qsharp_file() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') - res = dump_operation("Test_SWAP.ApplySWAP1", 2) + res = dump_operation("qs => Test_SWAP.ApplySWAP(qs[0], qs[1])", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], @@ -110,6 +110,7 @@ def test_operation_with_args_in_qsharp_file() -> None: [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], ] + def test_operation_equivalence_using_fact() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') From 8b24e209816c2b41f5defd16820638ecc40119b8 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 13:14:10 -0700 Subject: [PATCH 33/44] fix merge conflict --- build.py | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/build.py b/build.py index 977aebaa9e..ae188c9c65 100755 --- a/build.py +++ b/build.py @@ -363,43 +363,6 @@ def run_python_integration_tests(cwd, interpreter): ) step_end() -if build_samples: - step_start("Building qsharp samples") - project_directories = [ - dir for dir in os.walk(samples_src) if "qsharp.json" in dir[2] - ] - single_file_directories = [ - candidate - for candidate in os.walk(samples_src) - if all([not proj_dir[0] in candidate[0] for proj_dir in project_directories]) - ] - - files = [ - os.path.join(dp, f) - for dp, _, filenames in single_file_directories - for f in filenames - if os.path.splitext(f)[1] == ".qs" - ] - projects = [ - os.path.join(dp, f) - for dp, _, filenames in project_directories - for f in filenames - if f == "qsharp.json" - ] - cargo_args = ["cargo", "run", "--bin", "qsc"] - if build_type == "release": - cargo_args.append("--release") - for file in files: - subprocess.run((cargo_args + ["--", file]), check=True, text=True, cwd=root_dir) - for project in projects: - subprocess.run( - (cargo_args + ["--", "--qsharp-json", project]), - check=True, - text=True, - cwd=root_dir, - ) - step_end() - if build_npm: step_start("Building the npm package") # Copy the wasm build files over for web and node targets From 74a462284335402fb45dd77f1efaaf388110796a Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 13:40:25 -0700 Subject: [PATCH 34/44] rename --- .../operations/src/{Test_SWAP.qs => CustomOperation.qs} | 2 +- samples/testing/operations/src/OperationEquivalence.qs | 4 ++-- samples/testing/operations/test_operations.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename samples/testing/operations/src/{Test_SWAP.qs => CustomOperation.qs} (96%) diff --git a/samples/testing/operations/src/Test_SWAP.qs b/samples/testing/operations/src/CustomOperation.qs similarity index 96% rename from samples/testing/operations/src/Test_SWAP.qs rename to samples/testing/operations/src/CustomOperation.qs index 7809ab3d5c..db38bf3115 100644 --- a/samples/testing/operations/src/Test_SWAP.qs +++ b/samples/testing/operations/src/CustomOperation.qs @@ -8,7 +8,7 @@ /// This code builds upon the concepts explained in the README file, /// demonstrating how to organize Q# code into multiple files for testing. -namespace Test_SWAP { +namespace CustomOperation { // # Summary /// CNOT based operation for testing with `TestEquivalence` operation. /// diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index a8103fa538..1f837a5cc5 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -10,14 +10,14 @@ namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; - open Test_SWAP; + open CustomOperation; /// # Summary /// Verifies the equivalence of quantum operations using `Fact` function /// and the `CheckOperationsAreEqual` operation. You can either run this here, /// by clicking `Run` in VsCode or call `TestEquivalence` operation in python. @EntryPoint() operation TestEquivalence() : Unit { - let actual = qs => Test_SWAP.ApplySWAP(qs[0], qs[1]); + let actual = qs => CustomOperation.ApplySWAP(qs[0], qs[1]); let expected = qs => SWAP(qs[0], qs[1]); Fact(CheckOperationsAreEqual(2, actual, expected), "Actual and expected operation should be same"); } diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index 9451d27c9b..1c61d3d7a0 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -62,7 +62,7 @@ def test_operation_no_args_in_qsharp_file() -> None: qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') - res = dump_operation("qs => Test_SWAP.ApplySWAP(qs[0], qs[1])", 2) + res = dump_operation("qs => CustomOperation.ApplySWAP(qs[0], qs[1])", 2) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], From cf50eb62b6bfca69de622568439832490589860c Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 13:50:47 -0700 Subject: [PATCH 35/44] move setting profile to setup function --- samples/testing/operations/test_operations.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index 1c61d3d7a0..c24701bd4c 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -1,12 +1,19 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +import pytest import qsharp from qsharp.utils import dump_operation -def test_empty_operation() -> None: +@pytest.fixture(autouse=True) +def setup(): + """Fixture to execute asserts before a test is run""" + # You can set the target profile here if you want + # By default, it uses "Unrestricted" profile qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + yield # this is where the testing happens +def test_empty_operation() -> None: res = dump_operation("qs => ()", 1) assert res == [ [complex(1.0, 0.0), complex(0.0, 0.0)], From 27800e931b3f6f9ee8aed7f29659df461f15a2a5 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 14:07:17 -0700 Subject: [PATCH 36/44] remove complex dtype in tests --- samples/testing/operations/test_operations.py | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index c24701bd4c..bf68dc1752 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -10,14 +10,14 @@ def setup(): """Fixture to execute asserts before a test is run""" # You can set the target profile here if you want # By default, it uses "Unrestricted" profile - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) + qsharp.init(target_profile=qsharp.TargetProfile.Base) yield # this is where the testing happens def test_empty_operation() -> None: res = dump_operation("qs => ()", 1) assert res == [ - [complex(1.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(1.0, 0.0)], + [1.0, 0.0], + [0.0, 1.0], ] @@ -26,8 +26,8 @@ def test_single_qubit_not_gate() -> None: res = dump_operation("qs => X(qs[0])", 1) assert res == [ - [complex(0.0, 0.0), complex(1.0, 0.0)], - [complex(1.0, 0.0), complex(0.0, 0.0)], + [0.0, 1.0], + [1.0, 0.0], ] def test_single_qubit_hadamard_gate() -> None: @@ -35,8 +35,8 @@ def test_single_qubit_hadamard_gate() -> None: res = dump_operation("qs => H(qs[0])", 1) assert res == [ - [complex(0.707107, 0.0), complex(0.707107, 0.0)], - [complex(0.707107, 0.0), complex(-0.707107, 0.0)], + [0.707107, 0.707107], + [0.707107, -0.707107], ] def test_two_qubit_cnot_gate() -> None: @@ -44,10 +44,10 @@ def test_two_qubit_cnot_gate() -> None: res = dump_operation("qs => CNOT(qs[0], qs[1])", 2) assert res == [ - [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], + [1.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + [0.0, 0.0, 1.0, 0.0], ] def test_custom_operation() -> None: @@ -59,10 +59,10 @@ def test_custom_operation() -> None: res = dump_operation("ApplySWAP", 2) assert res == [ - [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], + [1.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], ] def test_operation_no_args_in_qsharp_file() -> None: @@ -71,10 +71,10 @@ def test_operation_no_args_in_qsharp_file() -> None: res = dump_operation("qs => CustomOperation.ApplySWAP(qs[0], qs[1])", 2) assert res == [ - [complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(1.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.0, 0.0), complex(0.0, 0.0), complex(1.0, 0.0)], + [1.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], + [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], ] def test_operation_with_args_in_qsharp_file() -> None: @@ -84,37 +84,37 @@ def test_operation_with_args_in_qsharp_file() -> None: res0 = dump_operation("BellState.AllBellStates(_, 0)", 2) assert res0 == [ - [complex(0.707107, 0.0), complex(0.0,0.0), complex(0.707107, 0.0), complex(0.0,0.0)], - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0)], - [complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0)], + [0.707107, 0.0, 0.707107, 0.0], + [0.0, 0.707107, 0.0, 0.707107], + [0.0, 0.707107, 0.0, -0.707107], + [0.707107, 0.0, -0.707107, 0.0], ] res1 = dump_operation("BellState.AllBellStates(_, 1)", 2) assert res1 == [ - [complex(0.707107, 0.0), complex(0.0,0.0), complex(0.707107, 0.0), complex(0.0,0.0)], - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], - [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], - [complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], + [0.707107, 0.0, 0.707107, 0.0], + [0.0, 0.707107, 0.0, 0.707107], + [0.0, -0.707107, 0.0, 0.707107], + [-0.707107, 0.0, 0.707107, 0.0], ] res2 = dump_operation("BellState.AllBellStates(_, 2)", 2) assert res2 == [ - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], - [complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], - [complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(-0.707107, 0.0)], + [0.0, 0.707107, 0.0, 0.707107], + [0.707107, 0.0, 0.707107, 0.0], + [0.707107, 0.0, -0.707107, 0.0], + [0.0, 0.707107, 0.0, -0.707107], ] res3 = dump_operation("BellState.AllBellStates(_, 3)", 2) assert res3 == [ - [complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], - [complex(0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], - [complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0), complex(0.0, 0.0)], - [complex(0.0, 0.0), complex(-0.707107, 0.0), complex(0.0, 0.0), complex(0.707107, 0.0)], + [0.0, 0.707107, 0.0, 0.707107], + [0.707107, 0.0, 0.707107, 0.0], + [-0.707107, 0.0, 0.707107, 0.0], + [0.0, -0.707107, 0.0, 0.707107], ] From e69e594c15505f268a1280643bf8eed54ab119a4 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Tue, 23 Jul 2024 14:12:44 -0700 Subject: [PATCH 37/44] minor edit --- samples/testing/operations/test_operations.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index bf68dc1752..e94dd0ba22 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -16,8 +16,8 @@ def setup(): def test_empty_operation() -> None: res = dump_operation("qs => ()", 1) assert res == [ - [1.0, 0.0], - [0.0, 1.0], + [1, 0], + [0, 1], ] @@ -26,8 +26,8 @@ def test_single_qubit_not_gate() -> None: res = dump_operation("qs => X(qs[0])", 1) assert res == [ - [0.0, 1.0], - [1.0, 0.0], + [0, 1], + [1, 0], ] def test_single_qubit_hadamard_gate() -> None: @@ -44,10 +44,10 @@ def test_two_qubit_cnot_gate() -> None: res = dump_operation("qs => CNOT(qs[0], qs[1])", 2) assert res == [ - [1.0, 0.0, 0.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0], - [0.0, 0.0, 1.0, 0.0], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 0, 1], + [0, 0, 1, 0], ] def test_custom_operation() -> None: @@ -59,10 +59,10 @@ def test_custom_operation() -> None: res = dump_operation("ApplySWAP", 2) assert res == [ - [1.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 1.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0], + [1, 0, 0, 0], + [0, 0, 1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1], ] def test_operation_no_args_in_qsharp_file() -> None: @@ -71,10 +71,10 @@ def test_operation_no_args_in_qsharp_file() -> None: res = dump_operation("qs => CustomOperation.ApplySWAP(qs[0], qs[1])", 2) assert res == [ - [1.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 1.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0], + [1, 0, 0, 0], + [0, 0, 1, 0], + [0, 1, 0, 0], + [0, 0, 0, 1], ] def test_operation_with_args_in_qsharp_file() -> None: From 9d84a37db5b69b41e942a92fc60a0e3c64fbb9a7 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Wed, 24 Jul 2024 18:05:44 -0700 Subject: [PATCH 38/44] Q# formatter fix --- samples/testing/operations/src/CustomOperation.qs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/testing/operations/src/CustomOperation.qs b/samples/testing/operations/src/CustomOperation.qs index db38bf3115..fc86dd36c0 100644 --- a/samples/testing/operations/src/CustomOperation.qs +++ b/samples/testing/operations/src/CustomOperation.qs @@ -17,7 +17,7 @@ namespace CustomOperation { /// First input qubit /// ## q2 /// Second input qubit - operation ApplySWAP(q1: Qubit, q2: Qubit) : Unit is Ctl + Adj { + operation ApplySWAP(q1 : Qubit, q2 : Qubit) : Unit is Ctl + Adj { CNOT(q1, q2); // q1, q1 xor q2 CNOT(q2, q1); // q2, q1 xor q2 CNOT(q1, q2); // q2, q1 From dbf1504ede76b63dbc0ca25eaddf32057bab51b6 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 26 Jul 2024 08:36:18 -0700 Subject: [PATCH 39/44] remove target profile from tests --- samples/testing/operations/test_operations.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index e94dd0ba22..e917e7413e 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -22,8 +22,6 @@ def test_empty_operation() -> None: def test_single_qubit_not_gate() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) - res = dump_operation("qs => X(qs[0])", 1) assert res == [ [0, 1], @@ -31,8 +29,6 @@ def test_single_qubit_not_gate() -> None: ] def test_single_qubit_hadamard_gate() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) - res = dump_operation("qs => H(qs[0])", 1) assert res == [ [0.707107, 0.707107], @@ -40,8 +36,6 @@ def test_single_qubit_hadamard_gate() -> None: ] def test_two_qubit_cnot_gate() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) - res = dump_operation("qs => CNOT(qs[0], qs[1])", 2) assert res == [ [1, 0, 0, 0], @@ -51,8 +45,6 @@ def test_two_qubit_cnot_gate() -> None: ] def test_custom_operation() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) - qsharp.eval( "operation ApplySWAP(qs : Qubit[]) : Unit is Ctl + Adj { SWAP(qs[0], qs[1]); }" ) @@ -66,7 +58,6 @@ def test_custom_operation() -> None: ] def test_operation_no_args_in_qsharp_file() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') res = dump_operation("qs => CustomOperation.ApplySWAP(qs[0], qs[1])", 2) @@ -78,7 +69,6 @@ def test_operation_no_args_in_qsharp_file() -> None: ] def test_operation_with_args_in_qsharp_file() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') res0 = dump_operation("BellState.AllBellStates(_, 0)", 2) @@ -119,7 +109,6 @@ def test_operation_with_args_in_qsharp_file() -> None: def test_operation_equivalence_using_fact() -> None: - qsharp.init(target_profile=qsharp.TargetProfile.Unrestricted) qsharp.init(project_root='.') qsharp.eval( From 00b8276329ff4d65f509b0ce964c672ee0433c55 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 26 Jul 2024 09:04:59 -0700 Subject: [PATCH 40/44] PR feedback --- samples/testing/operations/README.md | 8 ++++---- samples/testing/operations/src/BellState.qs | 7 ------- samples/testing/operations/src/CustomOperation.qs | 7 ------- samples/testing/operations/src/OperationEquivalence.qs | 9 +-------- samples/testing/operations/test_operations.py | 7 +++---- 5 files changed, 8 insertions(+), 30 deletions(-) diff --git a/samples/testing/operations/README.md b/samples/testing/operations/README.md index 607599fb26..528de87ceb 100644 --- a/samples/testing/operations/README.md +++ b/samples/testing/operations/README.md @@ -16,14 +16,14 @@ This sample project is a multi-file Q# project that showcases both testing metho - src - `BellState.qs`: Q# file containing the `AllBellStates` operation to be tested - - `Test_SWAP.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested - - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in python wrapper + - `CustomOperation.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested + - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in Python wrapper - `qsharp.json`: Q# project manifest file, instructing compiler to include all files in `src` directory. - `test_dump_operation.py`: Python wrapper containing tests. ## Installation -- Install the `qsharp` python package by following the instructions mentioned [here](https://learn.microsoft.com/azure/quantum/install-overview-qdk#add-support-for-python-and-jupyter-notebooks). -- Install `pytest` python package. +- Install the `qsharp` Python package by following the instructions mentioned [here](https://learn.microsoft.com/azure/quantum/install-overview-qdk#add-support-for-python-and-jupyter-notebooks). +- Install `pytest` Python package. ## Running the sample Open the `samples/testing/operations` directory, and run `pytest` command. diff --git a/samples/testing/operations/src/BellState.qs b/samples/testing/operations/src/BellState.qs index 35c47795e8..4fe9753739 100644 --- a/samples/testing/operations/src/BellState.qs +++ b/samples/testing/operations/src/BellState.qs @@ -1,13 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -/// # Sample -/// Multi File Testing Project (Refer to README for Project Overview) -/// -/// # Description -/// This code builds upon the concepts explained in the README file, -/// demonstrating how to organize Q# code into multiple files for testing. - namespace BellState { /// # Summary /// Operation that generates all bell states for testing with `dump_operation.py`. diff --git a/samples/testing/operations/src/CustomOperation.qs b/samples/testing/operations/src/CustomOperation.qs index fc86dd36c0..8e2bf3a010 100644 --- a/samples/testing/operations/src/CustomOperation.qs +++ b/samples/testing/operations/src/CustomOperation.qs @@ -1,13 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -/// # Sample -/// Multi File Testing Project -/// -/// # Description -/// This code builds upon the concepts explained in the README file, -/// demonstrating how to organize Q# code into multiple files for testing. - namespace CustomOperation { // # Summary /// CNOT based operation for testing with `TestEquivalence` operation. diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index 1f837a5cc5..30f48ef502 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -1,20 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -/// # Sample -/// Multi File Testing Project (Refer to README for Project Overview) -/// -/// # Description -/// This code builds upon the concepts explained in the README file, -/// demonstrating how to organize Q# code into multiple files for testing. - namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; open CustomOperation; /// # Summary /// Verifies the equivalence of quantum operations using `Fact` function /// and the `CheckOperationsAreEqual` operation. You can either run this here, - /// by clicking `Run` in VsCode or call `TestEquivalence` operation in python. + /// by clicking `Run` in VsCode or call `TestEquivalence` operation in Python. @EntryPoint() operation TestEquivalence() : Unit { let actual = qs => CustomOperation.ApplySWAP(qs[0], qs[1]); diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index e917e7413e..89379bb672 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -7,10 +7,9 @@ @pytest.fixture(autouse=True) def setup(): - """Fixture to execute asserts before a test is run""" - # You can set the target profile here if you want - # By default, it uses "Unrestricted" profile - qsharp.init(target_profile=qsharp.TargetProfile.Base) + """Fixture to execute before a test is run""" + # Setting the project root to current folder. + qsharp.init(project_root=".") yield # this is where the testing happens def test_empty_operation() -> None: From 9f4e5de3ff80bc57eaf25cb2c158456600742d24 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 26 Jul 2024 09:08:03 -0700 Subject: [PATCH 41/44] note about global phase --- samples/testing/operations/README.md | 2 +- samples/testing/operations/src/OperationEquivalence.qs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/testing/operations/README.md b/samples/testing/operations/README.md index 528de87ceb..2f5a26fc6e 100644 --- a/samples/testing/operations/README.md +++ b/samples/testing/operations/README.md @@ -9,7 +9,7 @@ There are two primary ways to test operations in the QDK: - Use the `dump_operation` Python API to retrieve the operation's representation as a matrix and compare it against the expected matrix. 2. **Q# `Fact` Assertions:** - - Use a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical. The `Fact` function asserts that the check returns `true`. + - Use a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical upto a global phase. The `Fact` function asserts that the check returns `true`. ## Project Structure This sample project is a multi-file Q# project that showcases both testing methods. The project structure is as follows: diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index 30f48ef502..04385c4443 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -5,7 +5,7 @@ namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; open CustomOperation; /// # Summary - /// Verifies the equivalence of quantum operations using `Fact` function + /// Verifies the equivalence of quantum operations upto a global phase using `Fact` function /// and the `CheckOperationsAreEqual` operation. You can either run this here, /// by clicking `Run` in VsCode or call `TestEquivalence` operation in Python. @EntryPoint() From ad0d03a982c4d05f58e1f364d55385044d9e3353 Mon Sep 17 00:00:00 2001 From: Manvi Agrawal Date: Fri, 26 Jul 2024 12:17:31 -0700 Subject: [PATCH 42/44] pr feedback --- samples/testing/operations/test_operations.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/samples/testing/operations/test_operations.py b/samples/testing/operations/test_operations.py index 89379bb672..cf2664e833 100644 --- a/samples/testing/operations/test_operations.py +++ b/samples/testing/operations/test_operations.py @@ -57,8 +57,6 @@ def test_custom_operation() -> None: ] def test_operation_no_args_in_qsharp_file() -> None: - qsharp.init(project_root='.') - res = dump_operation("qs => CustomOperation.ApplySWAP(qs[0], qs[1])", 2) assert res == [ [1, 0, 0, 0], @@ -68,8 +66,6 @@ def test_operation_no_args_in_qsharp_file() -> None: ] def test_operation_with_args_in_qsharp_file() -> None: - qsharp.init(project_root='.') - res0 = dump_operation("BellState.AllBellStates(_, 0)", 2) assert res0 == [ @@ -108,8 +104,6 @@ def test_operation_with_args_in_qsharp_file() -> None: def test_operation_equivalence_using_fact() -> None: - qsharp.init(project_root='.') - qsharp.eval( "OperationEquivalence.TestEquivalence()" ) From 49e4a803d63cb4ba7e54608fe25a2935600c7282 Mon Sep 17 00:00:00 2001 From: Manvi-Agrawal <40084144+Manvi-Agrawal@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:18:01 -0700 Subject: [PATCH 43/44] Apply suggestions from code review Co-authored-by: Mariia Mykhailova --- samples/testing/operations/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/testing/operations/README.md b/samples/testing/operations/README.md index 2f5a26fc6e..86a7244b58 100644 --- a/samples/testing/operations/README.md +++ b/samples/testing/operations/README.md @@ -9,14 +9,14 @@ There are two primary ways to test operations in the QDK: - Use the `dump_operation` Python API to retrieve the operation's representation as a matrix and compare it against the expected matrix. 2. **Q# `Fact` Assertions:** - - Use a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical upto a global phase. The `Fact` function asserts that the check returns `true`. + - Use a `Fact` function in your Q# code that uses the `CheckOperationsAreEqual` operation to verify if two operations are identical up to a global phase. The `Fact` function asserts that the check returns `true`. ## Project Structure This sample project is a multi-file Q# project that showcases both testing methods. The project structure is as follows: - src - `BellState.qs`: Q# file containing the `AllBellStates` operation to be tested - - `CustomOperation.qs`: Q# file containing the `ApplySWAP1` and `ApplySWAP2` operations to be tested + - `CustomOperation.qs`: Q# file containing the `ApplySWAP` operation to be tested - `OperationEquivalence.qs`: Q# file containing the `TestEquivalence` operation to be called in Python wrapper - `qsharp.json`: Q# project manifest file, instructing compiler to include all files in `src` directory. - `test_dump_operation.py`: Python wrapper containing tests. From 4fcc56d8bb0cc3406083ea7a1ee91189c07d15df Mon Sep 17 00:00:00 2001 From: Manvi-Agrawal <40084144+Manvi-Agrawal@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:19:01 -0700 Subject: [PATCH 44/44] Apply suggestions from code review Co-authored-by: Mariia Mykhailova --- samples/testing/operations/src/OperationEquivalence.qs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/testing/operations/src/OperationEquivalence.qs b/samples/testing/operations/src/OperationEquivalence.qs index 04385c4443..beec07871c 100644 --- a/samples/testing/operations/src/OperationEquivalence.qs +++ b/samples/testing/operations/src/OperationEquivalence.qs @@ -5,7 +5,7 @@ namespace OperationEquivalence { open Microsoft.Quantum.Diagnostics; open CustomOperation; /// # Summary - /// Verifies the equivalence of quantum operations upto a global phase using `Fact` function + /// Verifies the equivalence of quantum operations up to a global phase using `Fact` function /// and the `CheckOperationsAreEqual` operation. You can either run this here, /// by clicking `Run` in VsCode or call `TestEquivalence` operation in Python. @EntryPoint()