From 94a4bfde5d23b0f978f713186a90911542b3b076 Mon Sep 17 00:00:00 2001 From: Alexander Hansen Date: Tue, 4 Feb 2025 14:40:00 -0800 Subject: [PATCH 1/5] Appropriately annotate fixedpoint library --- library/fixed_point/src/Facts.qs | 9 ++++++++- library/fixed_point/src/Main.qs | 8 +++++++- library/fixed_point/src/Measurement.qs | 1 + library/fixed_point/src/Operations.qs | 13 ++++++++++--- library/fixed_point/src/Polynomial.qs | 19 ++++++++++++++----- library/fixed_point/src/Reciprocal.qs | 1 + library/fixed_point/src/Tests.qs | 13 +++++++++++-- 7 files changed, 52 insertions(+), 12 deletions(-) diff --git a/library/fixed_point/src/Facts.qs b/library/fixed_point/src/Facts.qs index 3f01db2868..a55e3b9dc0 100644 --- a/library/fixed_point/src/Facts.qs +++ b/library/fixed_point/src/Facts.qs @@ -1,9 +1,10 @@ +import Std.Arrays.Unzipped; // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. import Types.FixedPoint; +import Std.Diagnostics.Fact; import Std.Arrays.IsEmpty, Std.Arrays.Rest; -import Std.Diagnostics.Fact, Std.Diagnostics.CheckAllZero; /// # Summary /// Asserts that a quantum fixed-point number is @@ -12,7 +13,9 @@ import Std.Diagnostics.Fact, Std.Diagnostics.CheckAllZero; /// # Description /// This assertion succeeds when all qubits are in state $\ket{0}$, /// representing that the register encodes the fixed-point number $0.0$. +@Config(Unrestricted) operation AssertAllZeroFxP(fp : FixedPoint) : Unit { + import Std.Diagnostics.CheckAllZero; Fact(CheckAllZero(fp::Register), "Quantum fixed-point number was not zero."); } @@ -25,6 +28,8 @@ operation AssertAllZeroFxP(fp : FixedPoint) : Unit { /// Array of quantum fixed-point numbers that will be checked for /// compatibility (using assertions). function AssertFormatsAreIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { + import Std.Diagnostics.Fact; + if IsEmpty(fixedPoints) { return (); } @@ -48,6 +53,8 @@ function AssertFormatsAreIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { /// Array of quantum fixed-point numbers that will be checked for /// compatibility (using assertions). function AssertPointPositionsIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { + + if IsEmpty(fixedPoints) { return (); } diff --git a/library/fixed_point/src/Main.qs b/library/fixed_point/src/Main.qs index 845e7c59f2..93521f3be8 100644 --- a/library/fixed_point/src/Main.qs +++ b/library/fixed_point/src/Main.qs @@ -1,4 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -export Init.PrepareFxP as PrepareFxP, Measurement.MeasureFxP as MeasureFxP, Reciprocal.ComputeReciprocalFxP as ComputeReciprocalFxP, Types.FixedPoint as FixedPoint; +export Init.PrepareFxP as PrepareFxP, Types.FixedPoint as FixedPoint; + +@Config(Unrestricted) +export Reciprocal.ComputeReciprocalFxP as ComputeReciprocalFxP; + +@Config(FloatingPointComputations) +export Measurement.MeasureFxP as MeasureFxP; diff --git a/library/fixed_point/src/Measurement.qs b/library/fixed_point/src/Measurement.qs index 1e1c42f436..c8a6fb5d57 100644 --- a/library/fixed_point/src/Measurement.qs +++ b/library/fixed_point/src/Measurement.qs @@ -14,6 +14,7 @@ import Std.Convert.ResultArrayAsBoolArray; /// # Input /// ## fp /// Fixed-point number to measure. +@Config(FloatingPointComputations) operation MeasureFxP(fp : FixedPoint) : Double { let measurements = MResetEachZ(fp::Register); let bits = ResultArrayAsBoolArray(measurements); diff --git a/library/fixed_point/src/Operations.qs b/library/fixed_point/src/Operations.qs index fdce658a96..2c24693d98 100644 --- a/library/fixed_point/src/Operations.qs +++ b/library/fixed_point/src/Operations.qs @@ -3,8 +3,9 @@ import Types.FixedPoint; import Init.PrepareFxP; -import Facts.AssertPointPositionsIdenticalFxP, Facts.AssertFormatsAreIdenticalFxP, Facts.AssertAllZeroFxP; +import Operations.AddFxP; import Signed.Operations.Invert2sSI, Signed.Operations.MultiplySI, Signed.Operations.SquareSI; +import Facts.AssertPointPositionsIdenticalFxP; import Std.Arrays.Zipped; import Std.Arithmetic.RippleCarryTTKIncByLE; @@ -17,6 +18,7 @@ import Std.Arithmetic.RippleCarryTTKIncByLE; /// ## fp /// Fixed-point number to which the constant will /// be added. +@Config(Unrestricted) operation AddConstantFxP(constant : Double, fp : FixedPoint) : Unit is Adj + Ctl { let n = Length(fp::Register); use ys = Qubit[n]; @@ -46,6 +48,7 @@ operation AddConstantFxP(constant : Double, fp : FixedPoint) : Unit is Adj + Ctl /// The current implementation requires the two fixed-point numbers /// to have the same point position counting from the least-significant /// bit, i.e., $n_i$ and $p_i$ must be equal. +@Config(Unrestricted) operation AddFxP(fp1 : FixedPoint, fp2 : FixedPoint) : Unit is Adj + Ctl { AssertPointPositionsIdenticalFxP([fp1, fp2]); @@ -62,6 +65,7 @@ operation AddFxP(fp1 : FixedPoint, fp2 : FixedPoint) : Unit is Adj + Ctl { /// # Remarks /// Numerical inaccuracies may occur depending on the /// bit-precision of the fixed-point number. +@Config(Unrestricted) operation InvertFxP(fp : FixedPoint) : Unit is Adj + Ctl { let (_, reg) = fp!; Invert2sSI(reg); @@ -79,6 +83,7 @@ operation InvertFxP(fp : FixedPoint) : Unit is Adj + Ctl { /// # Remarks /// Computes the difference by inverting `subtrahend` before and after adding /// it to `minuend`. Notice that `minuend`, the first argument is updated. +@Config(Unrestricted) operation SubtractFxP(minuend : FixedPoint, subtrahend : FixedPoint) : Unit is Adj + Ctl { within { InvertFxP(subtrahend); @@ -102,13 +107,14 @@ operation SubtractFxP(minuend : FixedPoint, subtrahend : FixedPoint) : Unit is A /// # Remarks /// The current implementation requires the three fixed-point numbers /// to have the same point position and the same number of qubits. +@Config(Unrestricted) operation MultiplyFxP(fp1 : FixedPoint, fp2 : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled MultiplyFxP([], (fp1, fp2, result)); } controlled (controls, ...) { - AssertFormatsAreIdenticalFxP([fp1, fp2, result]); + Facts.AssertFormatsAreIdenticalFxP([fp1, fp2, result]); let n = Length(fp1::Register); use tmpResult = Qubit[2 * n]; @@ -133,12 +139,13 @@ operation MultiplyFxP(fp1 : FixedPoint, fp2 : FixedPoint, result : FixedPoint) : /// ## result /// Result fixed-point number, /// must be in state $\ket{0}$ initially. +@Config(Unrestricted) operation SquareFxP(fp : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled SquareFxP([], (fp, result)); } controlled (controls, ...) { - AssertFormatsAreIdenticalFxP([fp, result]); + Facts.AssertFormatsAreIdenticalFxP([fp, result]); let n = Length(fp::Register); use tmpResult = Qubit[2 * n]; diff --git a/library/fixed_point/src/Polynomial.qs b/library/fixed_point/src/Polynomial.qs index 083c4848e1..5bc356b690 100644 --- a/library/fixed_point/src/Polynomial.qs +++ b/library/fixed_point/src/Polynomial.qs @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import Facts.AssertFormatsAreIdenticalFxP, Facts.AssertAllZeroFxP; import Types.FixedPoint; import Init.PrepareFxP; -import Operations.MultiplyFxP, Operations.SquareFxP, Operations.AddConstantFxP; +import Facts.AssertFormatsAreIdenticalFxP; + /// # Summary /// Evaluates a polynomial in a fixed-point representation. @@ -19,12 +19,15 @@ import Operations.MultiplyFxP, Operations.SquareFxP, Operations.AddConstantFxP; /// ## result /// Output fixed-point number which will hold $P(x)$. Must be in state /// $\ket{0}$ initially. +@Config(Unrestricted) operation EvaluatePolynomialFxP(coefficients : Double[], fpx : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled EvaluatePolynomialFxP([], (coefficients, fpx, result)); } controlled (controls, ...) { - AssertFormatsAreIdenticalFxP([fpx, result]); + import Operations.AddConstantFxP; + + Facts.AssertFormatsAreIdenticalFxP([fpx, result]); let degree = Length(coefficients) - 1; let p = fpx::IntegerBits; let n = Length(fpx::Register); @@ -40,10 +43,11 @@ operation EvaluatePolynomialFxP(coefficients : Double[], fpx : FixedPoint, resul let currentIterate = FixedPoint(p, qubits[(d - 1) * n..d * n - 1]); let nextIterate = FixedPoint(p, qubits[(d - 2) * n..(d - 1) * n - 1]); // multiply by x and then add current coefficient - MultiplyFxP(currentIterate, fpx, nextIterate); + Operations.MultiplyFxP(currentIterate, fpx, nextIterate); AddConstantFxP(coefficients[d-1], nextIterate); } } apply { + import Operations.MultiplyFxP; let finalIterate = FixedPoint(p, qubits[0..n-1]); // final multiplication into the result register Controlled MultiplyFxP(controls, (finalIterate, fpx, result)); @@ -67,12 +71,15 @@ operation EvaluatePolynomialFxP(coefficients : Double[], fpx : FixedPoint, resul /// ## result /// Output fixed-point number which will hold $P(x)$. Must be in state /// $\ket{0}$ initially. +@Config(Unrestricted) operation EvaluateEvenPolynomialFxP(coefficients : Double[], fpx : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled EvaluateEvenPolynomialFxP([], (coefficients, fpx, result)); } controlled (controls, ...) { - AssertFormatsAreIdenticalFxP([fpx, result]); + import Operations.SquareFxP; + + Facts.AssertFormatsAreIdenticalFxP([fpx, result]); let halfDegree = Length(coefficients) - 1; let n = Length(fpx::Register); @@ -104,11 +111,13 @@ operation EvaluateEvenPolynomialFxP(coefficients : Double[], fpx : FixedPoint, r /// ## result /// Output fixed-point number which will hold P(x). Must be in state /// $\ket{0}$ initially. +@Config(Unrestricted) operation EvaluateOddPolynomialFxP(coefficients : Double[], fpx : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled EvaluateOddPolynomialFxP([], (coefficients, fpx, result)); } controlled (controls, ...) { + import Operations.MultiplyFxP; AssertFormatsAreIdenticalFxP([fpx, result]); let halfDegree = Length(coefficients) - 1; let n = Length(fpx::Register); diff --git a/library/fixed_point/src/Reciprocal.qs b/library/fixed_point/src/Reciprocal.qs index 4c5b4049bf..a80e0c0acc 100644 --- a/library/fixed_point/src/Reciprocal.qs +++ b/library/fixed_point/src/Reciprocal.qs @@ -21,6 +21,7 @@ import Std.Math.Min; /// Fixed-point number to be inverted. /// ## result /// Fixed-point number that will hold the result. Must be initialized to $\ket{0.0}$. +@Config(Unrestricted) operation ComputeReciprocalFxP(x : FixedPoint, result : FixedPoint) : Unit is Adj { body (...) { Controlled ComputeReciprocalFxP([], (x, result)); diff --git a/library/fixed_point/src/Tests.qs b/library/fixed_point/src/Tests.qs index 29568bea78..fa7e1466d2 100644 --- a/library/fixed_point/src/Tests.qs +++ b/library/fixed_point/src/Tests.qs @@ -3,12 +3,12 @@ import Init.PrepareFxP; import Types.FixedPoint; -import Measurement.MeasureFxP; import Std.Diagnostics.Fact; import Std.Convert.IntAsDouble; import Std.Math.AbsD; import Operations.*; +@Config(Unrestricted) @Test() operation FxpMeasurementTest() : Unit { for numQubits in 3..12 { @@ -29,7 +29,9 @@ operation FxpMeasurementTest() : Unit { } } +@Config(Unrestricted) operation TestConstantMeasurement(constant : Double, registerWidth : Int, integerWidth : Int, epsilon : Double) : Unit { + import Measurement.MeasureFxP; use register = Qubit[registerWidth]; let newFxp = new FixedPoint { IntegerBits = integerWidth, Register = register }; PrepareFxP(constant, newFxp); @@ -39,6 +41,7 @@ operation TestConstantMeasurement(constant : Double, registerWidth : Int, intege ResetAll(register); } +@Config(Unrestricted) @Test() operation FxpOperationTests() : Unit { for i in 0..10 { @@ -51,8 +54,9 @@ operation FxpOperationTests() : Unit { TestSquare(constant1); } } - +@Config(Unrestricted) operation TestSquare(a : Double) : Unit { + import Measurement.MeasureFxP; Message($"Testing Square({a})"); use resultRegister = Qubit[30]; let resultFxp = new FixedPoint { IntegerBits = 8, Register = resultRegister }; @@ -69,8 +73,10 @@ operation TestSquare(a : Double) : Unit { ResetAll(aRegister); } +@Config(Unrestricted) // assume the second register that `op` takes is the result register operation TestOperation(a : Double, b : Double, op : (FixedPoint, FixedPoint) => (), reference : (Double, Double) -> Double, name : String) : Unit { + import Measurement.MeasureFxP; Message($"Testing {name}({a}, {b})"); use register1 = Qubit[20]; let aFxp = new FixedPoint { IntegerBits = 8, Register = register1 }; @@ -89,8 +95,11 @@ operation TestOperation(a : Double, b : Double, op : (FixedPoint, FixedPoint) => ResetAll(register1 + register2); } +@Config(Unrestricted) // assume the third register that `op` takes is the result register operation TestOperation3(a : Double, b : Double, op : (FixedPoint, FixedPoint, FixedPoint) => (), reference : (Double, Double) -> Double, name : String) : Unit { + import Measurement.MeasureFxP; + Message($"Testing {name}({a}, {b})"); use register1 = Qubit[24]; let aFxp = new FixedPoint { IntegerBits = 8, Register = register1 }; From 6816191ccbfe33b7555dc743b10f97cb417c74bb Mon Sep 17 00:00:00 2001 From: Alexander Hansen Date: Tue, 4 Feb 2025 14:42:33 -0800 Subject: [PATCH 2/5] Fix formatting --- compiler/qsc_frontend/src/typeck/tests.rs | 19 +++++++++++++++++++ library/fixed_point/src/Facts.qs | 3 +-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/compiler/qsc_frontend/src/typeck/tests.rs b/compiler/qsc_frontend/src/typeck/tests.rs index 1933bdc07b..0b872de0f6 100644 --- a/compiler/qsc_frontend/src/typeck/tests.rs +++ b/compiler/qsc_frontend/src/typeck/tests.rs @@ -4695,3 +4695,22 @@ fn field_access_not_ident() { "##]], ); } + +#[test] +// ref issue #2153 +fn struct_syntax_single_field() { + check( + indoc! {" + namespace A { + struct B { C : Int } + function Foo() : Unit { + let b = B(5); + + } + } + "}, + "", + &expect![[r##" + "##]], + ); +} diff --git a/library/fixed_point/src/Facts.qs b/library/fixed_point/src/Facts.qs index a55e3b9dc0..5e9b3c3b03 100644 --- a/library/fixed_point/src/Facts.qs +++ b/library/fixed_point/src/Facts.qs @@ -1,10 +1,9 @@ -import Std.Arrays.Unzipped; // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. import Types.FixedPoint; import Std.Diagnostics.Fact; -import Std.Arrays.IsEmpty, Std.Arrays.Rest; +import Std.Arrays.IsEmpty, Std.Arrays.Rest, Std.Arrays.Unzipped; /// # Summary /// Asserts that a quantum fixed-point number is From 74e7da7048dccb5966a60c8987d63d4bc7095fc8 Mon Sep 17 00:00:00 2001 From: Alexander Hansen Date: Tue, 4 Feb 2025 14:43:45 -0800 Subject: [PATCH 3/5] remove accidental add --- compiler/qsc_frontend/src/typeck/tests.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/compiler/qsc_frontend/src/typeck/tests.rs b/compiler/qsc_frontend/src/typeck/tests.rs index 0b872de0f6..1933bdc07b 100644 --- a/compiler/qsc_frontend/src/typeck/tests.rs +++ b/compiler/qsc_frontend/src/typeck/tests.rs @@ -4695,22 +4695,3 @@ fn field_access_not_ident() { "##]], ); } - -#[test] -// ref issue #2153 -fn struct_syntax_single_field() { - check( - indoc! {" - namespace A { - struct B { C : Int } - function Foo() : Unit { - let b = B(5); - - } - } - "}, - "", - &expect![[r##" - "##]], - ); -} From b9b0af2a35061a045fa5320ff03dbba65833ec5e Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Thu, 13 Feb 2025 08:38:35 -0800 Subject: [PATCH 4/5] Update library/fixed_point/src/Facts.qs Co-authored-by: Stefan J. Wernli --- library/fixed_point/src/Facts.qs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/fixed_point/src/Facts.qs b/library/fixed_point/src/Facts.qs index 5e9b3c3b03..634d93e8fe 100644 --- a/library/fixed_point/src/Facts.qs +++ b/library/fixed_point/src/Facts.qs @@ -27,7 +27,6 @@ operation AssertAllZeroFxP(fp : FixedPoint) : Unit { /// Array of quantum fixed-point numbers that will be checked for /// compatibility (using assertions). function AssertFormatsAreIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { - import Std.Diagnostics.Fact; if IsEmpty(fixedPoints) { return (); From 3f1c438040ff9b54dcf27d289642dde1df7d70a7 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Thu, 13 Feb 2025 08:38:42 -0800 Subject: [PATCH 5/5] Update library/fixed_point/src/Facts.qs Co-authored-by: Stefan J. Wernli --- library/fixed_point/src/Facts.qs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/fixed_point/src/Facts.qs b/library/fixed_point/src/Facts.qs index 634d93e8fe..1bc83c6d17 100644 --- a/library/fixed_point/src/Facts.qs +++ b/library/fixed_point/src/Facts.qs @@ -51,8 +51,6 @@ function AssertFormatsAreIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { /// Array of quantum fixed-point numbers that will be checked for /// compatibility (using assertions). function AssertPointPositionsIdenticalFxP(fixedPoints : FixedPoint[]) : Unit { - - if IsEmpty(fixedPoints) { return (); }