Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Feature branch cleanup (#582)
Browse files Browse the repository at this point in the history
* Fixes #570. (#572)

* Fixes #571. (#573)

* Add DevSkim scanning (#576)

* Examples in fixed-point conversion functions.

* API review April 2022 (#561)

* API review April 2022

* Apply suggestions from code review

Co-authored-by: Mariia Mykhailova <mamykhai@microsoft.com>

* Update api-design-2022-04.md

* Update api-design-2022-04.md

Co-authored-by: Mariia Mykhailova <mamykhai@microsoft.com>

* Fixes #580. (#581)

* Address reviewer's feedback.

Co-authored-by: Angela Burton <anjbur@users.noreply.github.com>
Co-authored-by: Mariia Mykhailova <mamykhai@microsoft.com>
  • Loading branch information
3 people authored May 8, 2022
1 parent a084a1f commit c86b521
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 50 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/devskim.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: DevSkim

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
schedule:
# set schedule to run at 2AM PT on Saturdays
- cron: '0 9 * * Sat'

jobs:
lint:
name: DevSkim
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Run DevSkim scanner
uses: microsoft/DevSkim-Action@v1

- name: Upload DevSkim scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: devskim-results.sarif
59 changes: 59 additions & 0 deletions Design/meetings/2022/api-design-2022-04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Q# API Design Discussions / April 2022

Reviewers (in order by username): tcNickolas, msoeken

## Agenda

- https://github.com/microsoft/QuantumLibraries/issues/423
- https://github.com/microsoft/QuantumLibraries/issues/549
- https://github.com/microsoft/QuantumLibraries/issues/555
- https://github.com/microsoft/QuantumLibraries/issues/559

## Discussion

### Simple and consistent arithmetic API

**Proposal**: https://github.com/microsoft/QuantumLibraries/issues/423

**Reviews**:

> Please add a bullet point including your alias, your review result (*approve*, *reject*, *comment*), and a comment (optional when result is *approve*). Alternatively, add a line to the PR discussion incl. a reference to this issue.
**Consensus**: Postponed (no additional review was provided)

---

### Add names to tuple fields of FixedPoint UDT

**Proposal**: https://github.com/microsoft/QuantumLibraries/issues/549

**Reviews**:
* @tcNickolas, *approve*
> Please add a bullet point including your alias, your review result (*approve*, *reject*, *comment*), and a comment (optional when result is *approve*). Alternatively, add a line to the PR discussion incl. a reference to this issue.
**Consensus**: Approved (incl. implicit approval from proposal author)

---

### Add SubtractFxP and InvertFxP to the Numerics package

**Proposal**: https://github.com/microsoft/QuantumLibraries/issues/555

**Reviews**:
* @tcNickoas, *approve* - I had a comment about the order of arguments for `SubtractFxP`, but I see you've already incorporated it in the proposal
> Please add a bullet point including your alias, your review result (*approve*, *reject*, *comment*), and a comment (optional when result is *approve*). Alternatively, add a line to the PR discussion incl. a reference to this issue.
**Consensus**: Approved (incl. implicit approval from proposal author)

---

### FixedPoint conversion functions

**Proposal**: https://github.com/microsoft/QuantumLibraries/issues/559

**Reviews**:
* @tcNickolas, *approve*, left a comment
> Please add a bullet point including your alias, your review result (*approve*, *reject*, *comment*), and a comment (optional when result is *approve*). Alternatively, add a line to the PR discussion incl. a reference to this issue.
**Consensus**: Approved (incl. implicit approval from proposal author)

21 changes: 21 additions & 0 deletions Numerics/src/FixedPoint/Convert.qs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ namespace Microsoft.Quantum.Convert {
/// 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;
Expand Down Expand Up @@ -47,6 +55,13 @@ namespace Microsoft.Quantum.Convert {
/// 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));
Expand All @@ -63,6 +78,12 @@ namespace Microsoft.Quantum.Convert {
/// 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));
}
Expand Down
13 changes: 13 additions & 0 deletions Numerics/tests/FixedPointTests.qs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ namespace Microsoft.Quantum.Tests {
NearEqualityFactD(PrepareAsSignedAndMeasure(0b1111, qsFxP), -0.25);
}

@Test("QuantumSimulator")
operation FixedPointConversionTest() : Unit {
AllEqualityFactB(FixedPointAsBoolArray(2, 2, 1.25), [true, false, true, false], "FixedPointAsBoolArray failed");
AllEqualityFactB(FixedPointAsBoolArray(2, 2, 1.3), [true, false, true, false], "FixedPointAsBoolArray failed");
AllEqualityFactB(FixedPointAsBoolArray(2, 2, -1.75), [true, false, false, true], "FixedPointAsBoolArray failed");

NearEqualityFactD(BoolArrayAsFixedPoint(2, [true, false, true, false]), 1.25);
NearEqualityFactD(BoolArrayAsFixedPoint(2, [true, false, false, true]), -1.75);

NearEqualityFactD(DoubleAsFixedPoint(2, 2, 1.3), 1.25);
NearEqualityFactD(DoubleAsFixedPoint(2, 2, 0.8), 0.75);
}

@Test("ToffoliSimulator")
operation CompareGreaterThanFxPTest() : Unit {
for a in [1.2, 3.9, 3.14159, -0.6, -4.5, -3.1931, 0.0] {
Expand Down
18 changes: 9 additions & 9 deletions Standard/src/AmplitudeAmplification/AmplitudeAmplification.qs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.Quantum.AmplitudeAmplification {
Expand Down Expand Up @@ -129,16 +129,16 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
/// It is assumed that the target state is marked by $\ket{1}\_f$.
/// It is assumed that
/// \begin{align}
/// O\ket{\text{start}}\_{fa}\ket{\psi}\_s= \lambda\ket{1}\_f\ket{\text{anything}}\_a\ket{\text{target}}\_s U \ket{\psi}\_s + \sqrt{1-|\lambda|^2}\ket{0}\_f\cdots,
/// O\ket{\text{start}}\_{fa}\ket{\psi}\_s= \lambda\ket{1}\_f\ket{\text{anything}}\_a\ket{\text{target}}\_s + \sqrt{1-|\lambda|^2}\ket{0}\_f\cdots,
/// \end{align}
/// for some unitary $U$.
/// where $\ket{\text{target}}\_s = U \ket{\psi}\_s$ for some unitary $U$.
function ObliviousAmplitudeAmplificationFromStatePreparation(
phases : ReflectionPhases,
startStateOracle : DeterministicStateOracle,
signalOracle : ObliviousOracle,
idxFlagQubit : Int
)
: ((Qubit[], Qubit[]) => Unit is Adj + Ctl) {
: (Qubit[], Qubit[]) => Unit is Adj + Ctl {
let startStateReflection = ReflectionStart();
let targetStateReflection = TargetStateReflectionOracle(idxFlagQubit);
let obliviousSignalOracle = ObliviousOracleFromDeterministicStateOracle(
Expand Down Expand Up @@ -205,7 +205,7 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
startStateReflection : ReflectionOracle,
targetStateReflection : ReflectionOracle
)
: (Qubit[] => Unit is Adj + Ctl) {
: Qubit[] => Unit is Adj + Ctl {
// Pass empty qubit array using fact that NoOp does nothing.
let qubitEmpty = [];
let signalOracle = ObliviousOracle(NoOp);
Expand Down Expand Up @@ -247,7 +247,7 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
stateOracle : StateOracle,
idxFlagQubit : Int
)
: (Qubit[] => Unit is Adj + Ctl) {
: Qubit[] => Unit is Adj + Ctl {
let systemRegister = [];
let signalOracle = ObliviousOracle(NoOp);
let startStateOracle = DeterministicStateOracleFromStateOracle(idxFlagQubit, stateOracle);
Expand Down Expand Up @@ -290,7 +290,7 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
stateOracle : StateOracle,
idxFlagQubit : Int
)
: (Qubit[] => Unit is Adj + Ctl) {
: Qubit[] => Unit is Adj + Ctl {
let phases = StandardReflectionPhases(nIterations);
return AmplitudeAmplificationFromStatePreparation(phases, stateOracle, idxFlagQubit);
}
Expand All @@ -317,15 +317,15 @@ namespace Microsoft.Quantum.AmplitudeAmplification {
mutable exponentMax = 0;
mutable exponentCurrent = 0;

//Complexity: Let \theta = \mathcal{O}(\sqrt{lambda})
// Complexity: Let \theta = \mathcal{O}(\sqrt{lambda})
// Number of Measurements = O( Log^2(1/\theta) )
// Number of Queries = O(1/\theta)
use flagQubit = Qubit();
let qubits = [flagQubit] + startQubits;
let idxFlagQubit = 0;

repeat {
if 2 ^ exponentMax > queriesMax {
if 2^exponentMax > queriesMax {
fail $"Target state not found. Maximum number of queries exceeded.";
}

Expand Down
4 changes: 2 additions & 2 deletions Standard/src/Math/Functions.qs
Original file line number Diff line number Diff line change
Expand Up @@ -751,15 +751,15 @@ namespace Microsoft.Quantum.Math {
///
/// # Description
/// Returns the factorial as `Double`, given an input of $n$ as a `Double`.
/// The domain of inputs for this function is `AbsD(n) < 170.0`.
/// The domain of inputs for this function is `n < 170`.
///
/// # Remarks
/// For $n \ge 10$, this function uses the Ramanujan approximation with a
/// relative error to the order of $1 / n^5$.
///
/// # Input
/// ## n
/// The number to take the approximate factorial of.
/// The number to take the approximate factorial of. Must not be negative.
///
/// # Output
/// The approximate factorial of `n`.
Expand Down
60 changes: 21 additions & 39 deletions Standard/src/Preparation/QuantumROM.qs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// Licensed under the MIT License.

namespace Microsoft.Quantum.Preparation {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Arithmetic;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Arrays;

/// # Summary
/// Returns an operation that prepares a a purification of a given mixed state.
Expand Down Expand Up @@ -107,10 +108,6 @@ namespace Microsoft.Quantum.Preparation {
return MixedStatePreparation(qubitCounts, oneNorm, op);
}

internal function SplitSign(coefficient : Double) : (Double, Int) {
return (AbsD(coefficient), coefficient < 0.0 ? 1 | 0);
}

/// # Summary
/// Returns an operation that prepares a a purification of a given mixed
/// state, entangled with a register representing a given collection of data.
Expand Down Expand Up @@ -221,6 +218,9 @@ namespace Microsoft.Quantum.Preparation {
/// - Microsoft.Quantum.Preparation.PurifiedMixedState
function PurifiedMixedStateRequirements(targetError : Double, nCoefficients : Int)
: MixedStatePreparationRequirements {
Fact(targetError > 0.0, "targetError must be positive");
Fact(nCoefficients > 0, "nCoefficients must be positive");

let nBitsPrecision = -Ceiling(Lg(0.5*targetError)) + 1;
let nIndexQubits = Ceiling(Lg(IntAsDouble(nCoefficients)));
let nGarbageQubits = nIndexQubits + 2 * nBitsPrecision + 1;
Expand All @@ -235,21 +235,15 @@ namespace Microsoft.Quantum.Preparation {
: (Double, Int[], Int[]) {
let oneNorm = PNorm(1.0, coefficients);
let nCoefficients = Length(coefficients);
if (bitsPrecision > 31) {
fail $"Bits of precision {bitsPrecision} unsupported. Max is 31.";
}
if (nCoefficients <= 1) {
fail $"Cannot prepare state with less than 2 coefficients.";
}
if (oneNorm == 0.0) {
fail $"State must have at least one coefficient > 0";
}
Fact(bitsPrecision <= 31, $"Bits of precision {bitsPrecision} unsupported. Max is 31.");
Fact(nCoefficients > 1, "Cannot prepare state with less than 2 coefficients.");
Fact(oneNorm != 0.0, "State must have at least one coefficient > 0");

let barHeight = 2 ^ bitsPrecision - 1;

mutable altIndex = RangeAsIntArray(0..nCoefficients - 1);
mutable keepCoeff = Mapped(
RoundedDiscretizationCoefficients(_, oneNorm, nCoefficients, barHeight),
coefficient -> Round((AbsD(coefficient) / oneNorm) * IntAsDouble(nCoefficients) * IntAsDouble(barHeight)),
coefficients
);

Expand All @@ -268,15 +262,15 @@ namespace Microsoft.Quantum.Preparation {
mutable barSource = [];

for idxCoeff in IndexRange(keepCoeff) {
if (keepCoeff[idxCoeff] > barHeight) {
if keepCoeff[idxCoeff] > barHeight {
set barSource += [idxCoeff];
} elif (keepCoeff[idxCoeff] < barHeight) {
} elif keepCoeff[idxCoeff] < barHeight {
set barSink += [idxCoeff];
}
}

for rep in 0..nCoefficients * 10 {
if (Length(barSink) > 0 and Length(barSource) > 0) {
if Length(barSink) > 0 and Length(barSource) > 0 {
let idxSink = Tail(barSink);
let idxSource = Tail(barSource);
set barSink = Most(barSink);
Expand All @@ -285,12 +279,12 @@ namespace Microsoft.Quantum.Preparation {
set keepCoeff w/= idxSource <- keepCoeff[idxSource] - barHeight + keepCoeff[idxSink];
set altIndex w/= idxSink <- idxSource;

if (keepCoeff[idxSource] < barHeight) {
if keepCoeff[idxSource] < barHeight {
set barSink += [idxSource];
} elif (keepCoeff[idxSource] > barHeight) {
} elif keepCoeff[idxSource] > barHeight {
set barSource += [idxSource];
}
} elif (Length(barSource) > 0) {
} elif Length(barSource) > 0 {
let idxSource = Tail(barSource);
set barSource = Most(barSource);
set keepCoeff w/= idxSource <- barHeight;
Expand All @@ -302,12 +296,6 @@ namespace Microsoft.Quantum.Preparation {
return (oneNorm, keepCoeff, altIndex);
}

// Used in QuantumROM implementation.
internal function RoundedDiscretizationCoefficients(coefficient: Double, oneNorm: Double, nCoefficients: Int, barHeight: Int)
: Int {
return Round((AbsD(coefficient) / oneNorm) * IntAsDouble(nCoefficients) * IntAsDouble(barHeight));
}

// Used in QuantumROM implementation.
internal operation PrepareQuantumROMState(
nBitsPrecision: Int, nCoeffs: Int, nBitsIndices: Int,
Expand All @@ -332,7 +320,7 @@ namespace Microsoft.Quantum.Preparation {
ApplyToEachCA(H, uniformKeepCoeffRegister!);

// Write bitstrings to altIndex and keepCoeff register.
let unitaryGenerator = (nCoeffs, QuantumROMBitStringWriterByIndex(_, keepCoeff, altIndex, data));
let unitaryGenerator = (nCoeffs, idx -> WriteQuantumROMBitString(idx, keepCoeff, altIndex, data, _, _, _, _));
MultiplexOperationsFromGenerator(unitaryGenerator, indexRegister, (keepCoeffRegister, altIndexRegister, dataRegister, altDataRegister));

// Perform comparison
Expand All @@ -341,23 +329,17 @@ namespace Microsoft.Quantum.Preparation {
let indexRegisterSize = Length(indexRegister!);

// Swap in register based on comparison
ApplyToEachCA((Controlled SWAP)([flagQubit], _), Zipped(indexRegister! + dataRegister, altIndexRegister! + altDataRegister));
}

// Used in QuantumROM implementation.
internal function QuantumROMBitStringWriterByIndex(idx : Int, keepCoeff : Int[], altIndex : Int[], data : Bool[][])
: ((LittleEndian, LittleEndian, Qubit[], Qubit[]) => Unit is Adj + Ctl) {
return WriteQuantumROMBitString(idx, keepCoeff, altIndex, data, _, _, _, _);
ApplyToEachCA(Controlled SWAP([flagQubit], _), Zipped(indexRegister! + dataRegister, altIndexRegister! + altDataRegister));
}

// Used in QuantumROM implementation.
internal operation WriteQuantumROMBitString(idx: Int, keepCoeff: Int[], altIndex: Int[], data : Bool[][], keepCoeffRegister: LittleEndian, altIndexRegister: LittleEndian, dataRegister : Qubit[], altDataRegister : Qubit[])
: Unit is Adj + Ctl {
if (keepCoeff[idx] >= 0) {
if keepCoeff[idx] >= 0 {
ApplyXorInPlace(keepCoeff[idx], keepCoeffRegister);
}
ApplyXorInPlace(altIndex[idx], altIndexRegister);
if (Length(dataRegister) > 0) {
if Length(dataRegister) > 0 {
ApplyToEachCA(CControlledCA(X), Zipped(data[idx], dataRegister));
ApplyToEachCA(CControlledCA(X), Zipped(data[altIndex[idx]], altDataRegister));
}
Expand Down

0 comments on commit c86b521

Please sign in to comment.