Skip to content

Commit

Permalink
Appropriately annotate fixedpoint library
Browse files Browse the repository at this point in the history
  • Loading branch information
sezna committed Feb 4, 2025
1 parent acd1890 commit 94a4bfd
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 12 deletions.
9 changes: 8 additions & 1 deletion library/fixed_point/src/Facts.qs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.");
}

Expand All @@ -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 ();
}
Expand All @@ -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 ();
}
Expand Down
8 changes: 7 additions & 1 deletion library/fixed_point/src/Main.qs
Original file line number Diff line number Diff line change
@@ -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;
1 change: 1 addition & 0 deletions library/fixed_point/src/Measurement.qs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 10 additions & 3 deletions library/fixed_point/src/Operations.qs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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];
Expand Down Expand Up @@ -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]);

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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];
Expand All @@ -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];
Expand Down
19 changes: 14 additions & 5 deletions library/fixed_point/src/Polynomial.qs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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);
Expand All @@ -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));
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions library/fixed_point/src/Reciprocal.qs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
13 changes: 11 additions & 2 deletions library/fixed_point/src/Tests.qs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -39,6 +41,7 @@ operation TestConstantMeasurement(constant : Double, registerWidth : Int, intege
ResetAll(register);
}

@Config(Unrestricted)
@Test()
operation FxpOperationTests() : Unit {
for i in 0..10 {
Expand All @@ -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 };
Expand All @@ -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 };
Expand All @@ -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 };
Expand Down

0 comments on commit 94a4bfd

Please sign in to comment.