Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port fixed point library to modern QDK #1838

Merged
merged 30 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4f98e07
wip: start fixed point library
sezna Aug 8, 2024
62e9622
wip
sezna Aug 9, 2024
152ed2f
wip: fixed point library
sezna Aug 9, 2024
86be0c7
Merge branch 'main' of github.com:microsoft/qsharp into alex/fixed-po…
sezna Aug 12, 2024
fec25b6
Wipg
sezna Aug 12, 2024
4c4cb0c
wip
sezna Aug 13, 2024
4c0bf40
wip
sezna Aug 13, 2024
04c67b8
Merge branch 'main' of github.com:microsoft/qsharp into alex/fixed-po…
sezna Aug 13, 2024
caa1d82
it....works
sezna Aug 13, 2024
a64c788
add signed library
sezna Aug 14, 2024
625d11d
wip
sezna Aug 14, 2024
a41292b
wip
sezna Aug 14, 2024
42d3c67
wip
sezna Aug 14, 2024
86512c8
wip: import signed library
sezna Aug 14, 2024
971339f
Merge branch 'main' of github.com:microsoft/qsharp into alex/fixed-po…
sezna Aug 20, 2024
5af07e6
merge from main
sezna Aug 20, 2024
5b03d43
Fmt
sezna Aug 20, 2024
fe230b3
wip: testing
sezna Aug 20, 2024
8552564
finish basic fixed point tests
sezna Aug 20, 2024
8157678
better tests
sezna Aug 20, 2024
07f4667
revert accidental whitespace changes
sezna Aug 20, 2024
31a675a
Add copyright header
sezna Aug 20, 2024
6657049
Merge branch 'main' of github.com:microsoft/qsharp into alex/fixed-po…
sezna Aug 26, 2024
8f2e0b7
Add tests measuring various widths of fixed points
sezna Aug 26, 2024
07f0ace
wip
sezna Aug 26, 2024
f16d1e0
update to latest version of signed library
sezna Aug 26, 2024
3148c25
remove unrelated change in signed lib, that has been pulled into anot…
sezna Aug 26, 2024
3d6bbcd
update commit hashes for deps
sezna Aug 27, 2024
c08919a
Update library/fixed_point/src/Measurement.qs
sezna Aug 29, 2024
047ba17
PR feedback
sezna Aug 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions library/fixed_point/qsharp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"Signed": {
"github": {
"owner": "microsoft",
"repo": "qsharp",
"ref": "adcefe8",
"path": "library/signed"
}
},
"Unstable": {
"github": {
"owner": "Microsoft",
"repo": "qsharp",
"ref": "adcefe8",
"path": "library/unstable"
}
}
},
"files": [
"src/Comparison.qs",
"src/Convert.qs",
"src/Facts.qs",
"src/Init.qs",
"src/Main.qs",
"src/Measurement.qs",
"src/Operations.qs",
"src/Polynomial.qs",
"src/Reciprocal.qs",
"src/Tests.qs",
"src/Types.qs"
]
}
29 changes: 29 additions & 0 deletions library/fixed_point/src/Comparison.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Types.FixedPoint;
import Facts.IdenticalFormatFactFxP;
import Signed.Comparison.CompareGTSI;

/// # Summary
/// Compares two fixed-point numbers stored in quantum registers, and
/// controls a flip on the result.
///
/// # Input
/// ## fp1
/// First fixed-point number to be compared.
/// ## fp2
/// Second fixed-point number to be compared.
/// ## result
/// Result of the comparison. Will be flipped if `fp1 > fp2`.
///
/// # Remarks
/// The current implementation requires the two fixed-point numbers
/// to have the same point position and the same number of qubits.
operation CompareGreaterThanFxP(fp1 : FixedPoint, fp2 : FixedPoint, result : Qubit) : Unit is Adj + Ctl {
IdenticalFormatFactFxP([fp1, fp2]);

CompareGTSI((fp1::Register), (fp2::Register), result);
}

export CompareGreaterThanFxP;
95 changes: 95 additions & 0 deletions library/fixed_point/src/Convert.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import Std.Convert.IntAsDouble, Std.Convert.BoolArrayAsInt;
import Std.Math.AbsD, Std.Math.Floor;
import Std.Arrays.Most, Std.Arrays.Tail;

/// # Summary
/// Computes fixed-point approximation for a double and returns it as `Bool` array.
///
/// # Input
/// ## integerBits
/// Assumed number of integer bits (including the sign bit).
/// ## fractionalBits
/// Assumed number of fractional bits.
/// ## value
/// Value to be approximated.
///
/// # Example
/// Note that the first element in the Boolean array is the least-significant bit.
/// ```qsharp
/// let bits = FixedPointAsBoolArray(2, 2, 1.25); // bits = [true, false, true, false]
/// let bits = FixedPointAsBoolArray(2, 2, 1.3); // bits = [true, false, true, false], approximated
/// let bits = FixedPointAsBoolArray(2, 2, -1.75); // bits = [true, false, false, true], two's complement
/// ```
function FixedPointAsBoolArray(integerBits : Int, fractionalBits : Int, value : Double) : Bool[] {
let numBits = integerBits + fractionalBits;
let sign = value < 0.0;

mutable result = [false, size = numBits];
mutable rescaledConstant = 2.0^IntAsDouble(fractionalBits) * AbsD(value) + 0.5;
mutable keepAdding = sign;

for idx in 0..numBits - 1 {
let intConstant = Floor(rescaledConstant);
set rescaledConstant = rescaledConstant / 2.0;
mutable currentBit = (intConstant &&& 1) == (sign ? 0 | 1);
if keepAdding {
set keepAdding = currentBit;
set currentBit = not currentBit;
}
if currentBit {
set result w/= idx <- true;
}
}

return result;
}

/// # Summary
/// Returns the double value of a fixed-point approximation from of a `Bool` array.
///
/// # Input
/// ## integerBits
/// Assumed number of integer bits (including the sign bit).
/// ## bits
/// Bit-string representation of approximated number.
///
/// # Example
/// Note that the first element in the Boolean array is the least-significant bit.
/// ```qsharp
/// let value = BoolArrayAsFixedPoint(2, [true, false, true, false]); // value = 1.25
/// let value = BoolArrayAsFixedPoint(2, [true, false, false, true]); // value = -1.75
/// ```

function BoolArrayAsFixedPoint(integerBits : Int, bits : Bool[]) : Double {
let numBits = Length(bits);
let intPart = (Tail(bits) ? -(1 <<< (numBits - 1)) | 0) + BoolArrayAsInt(Most(bits));
return IntAsDouble(intPart) / (2.0^IntAsDouble(numBits - integerBits));
}

/// # Summary
/// Discretizes a double value as a fixed-point approximation and returns its value as a double.
///
/// # Input
/// ## integerBits
/// Assumed number of integer bits (including the sign bit).
/// ## fractionalBits
/// Assumed number of fractional bits.
/// ## value
/// Value to be approximated.
///
/// # Example
/// ```qsharp
/// let value = DoubleAsFixedPoint(2, 2, 1.3); // value = 1.25
/// let value = DoubleAsFixedPoint(2, 2, 0.8); // value = 0.75
/// ```
function DoubleAsFixedPoint(integerBits : Int, fractionalBits : Int, value : Double) : Double {
return BoolArrayAsFixedPoint(integerBits, FixedPointAsBoolArray(integerBits, fractionalBits, value));
}

export
FixedPointAsBoolArray,
BoolArrayAsFixedPoint,
DoubleAsFixedPoint;
62 changes: 62 additions & 0 deletions library/fixed_point/src/Facts.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Types.FixedPoint;
import Std.Arrays.IsEmpty, Std.Arrays.Rest;
import Std.Diagnostics.Fact, Std.Diagnostics.CheckAllZero;

/// # Summary
/// Asserts that a quantum fixed-point number is
/// initialized to zero.
///
/// # Description
/// This assertion succeeds when all qubits are in state $\ket{0}$,
/// representing that the register encodes the fixed-point number $0.0$.
operation AssertAllZeroFxP(fp : FixedPoint) : Unit {
Fact(CheckAllZero(fp::Register), "Quantum fixed-point number was not zero.");
}

/// # Summary
/// Assert that all fixed-point numbers in the provided array
/// have identical point positions and qubit numbers.
///
/// # Input
/// ## fixedPoints
/// Array of quantum fixed-point numbers that will be checked for
/// compatibility (using assertions).
function IdenticalFormatFactFxP(fixedPoints : FixedPoint[]) : Unit {
sezna marked this conversation as resolved.
Show resolved Hide resolved
if IsEmpty(fixedPoints) {
return ();
}
let (position, register) = fixedPoints[0]!;
sezna marked this conversation as resolved.
Show resolved Hide resolved
Fact(position > 0, "Point position must be greater than zero.");
let n = Length(register);
for fp in Rest(fixedPoints) {
Fact(fp::IntegerBits == position, "FixedPoint numbers must have identical binary point position.");
Fact(Length(fp::Register) == n, "FixedPoint numbers must have identical number of qubits.");
}
}

/// # Summary
/// Assert that all fixed-point numbers in the provided array
/// have identical point positions when counting from the least-
/// significant bit. I.e., number of bits minus point position must
/// be constant for all fixed-point numbers in the array.
///
/// # Input
/// ## fixedPoints
/// Array of quantum fixed-point numbers that will be checked for
/// compatibility (using assertions).
function IdenticalPointPosFactFxP(fixedPoints : FixedPoint[]) : Unit {
sezna marked this conversation as resolved.
Show resolved Hide resolved
if IsEmpty(fixedPoints) {
return ();
}
let (position, register) = fixedPoints[0]!;
sezna marked this conversation as resolved.
Show resolved Hide resolved
Fact(position > 0, "Point position must be greater than zero.");
let n = Length(register);
for fp in Rest(fixedPoints) {
Fact((Length(fp::Register) - fp::IntegerBits) == (n - position), "FixedPoint numbers must have identical point alignment.");
}
}

export AssertAllZeroFxP, IdenticalFormatFactFxP, IdenticalPointPosFactFxP;
18 changes: 18 additions & 0 deletions library/fixed_point/src/Init.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Types.FixedPoint;
import Convert.FixedPointAsBoolArray;

/// # Summary
/// Initialize a quantum fixed-point number to a classical constant.
///
/// # Input
/// ## constant
/// Constant to which to initialize the quantum fixed-point number.
/// ## fp
/// Fixed-point number (of type FixedPoint) to initialize.
operation PrepareFxP(constant : Double, fp : FixedPoint) : Unit is Adj + Ctl {
let bits = FixedPointAsBoolArray(fp::IntegerBits, Length(fp::Register) - fp::IntegerBits, constant);
ApplyPauliFromBitString(PauliX, true, bits, fp::Register);
}
4 changes: 4 additions & 0 deletions library/fixed_point/src/Main.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

export Init.PrepareFxP, Measurement.MeasureFxP, Reciprocal.ComputeReciprocalFxP, Types.FixedPoint;
18 changes: 18 additions & 0 deletions library/fixed_point/src/Measurement.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import Types.FixedPoint;
import Convert.BoolArrayAsFixedPoint;
import Std.Arrays.ForEach;

/// # Summary
/// Measure a fixed-point number, returns its value as Double, and resets
/// all the register to zero.
///
/// # Input
/// ## fp
/// Fixed-point number to measure.
operation MeasureFxP(fp : FixedPoint) : Double {
let bits = ForEach(q => MResetZ(q) == One, fp::Register);
sezna marked this conversation as resolved.
Show resolved Hide resolved
return BoolArrayAsFixedPoint(fp::IntegerBits, bits);
}
Loading
Loading