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

Commit d7e1d9d

Browse files
Chris Granadebettinaheim
andauthored
Fix #256. (#257)
* Fix #256. * Added regression test. * Fixed test target. * Add internal fact. * Fix fact. Co-authored-by: bettinaheim <34236215+bettinaheim@users.noreply.github.com>
1 parent 86d3a81 commit d7e1d9d

File tree

3 files changed

+64
-18
lines changed

3 files changed

+64
-18
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
5+
namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.Tests {
6+
open Microsoft.Quantum.Intrinsic;
7+
open Microsoft.Quantum.Diagnostics;
8+
9+
internal function Fact(condition : Bool, message : String) : Unit {
10+
if (not condition) {
11+
fail message;
12+
}
13+
}
14+
15+
@Test("ResourcesEstimator")
16+
/// # Summary
17+
/// Checks for regression against microsoft/qsharp-runtime#256.
18+
operation CheckRandomInCorrectRange() : Unit {
19+
for (idxTrial in 0..99) {
20+
let sample = Random([1.0, 2.0, 2.0]);
21+
22+
Fact(0 <= sample and sample <= 2, $"sample was {sample}, not in range [0, 2]");
23+
}
24+
}
25+
}

src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Diagnostics;
67

78
using Microsoft.Quantum.Simulation.Core;
@@ -73,5 +74,19 @@ public static partial class Extensions
7374
{
7475
return InterfaceType(t, typeof(IControllable<>));
7576
}
77+
78+
internal static IEnumerable<TResult> SelectAggregates<TSource, TResult>(
79+
this IEnumerable<TSource> source,
80+
Func<TResult, TSource, TResult> aggregate,
81+
TResult initial = default
82+
)
83+
{
84+
var acc = initial;
85+
foreach (var element in source)
86+
{
87+
acc = aggregate(acc, element);
88+
yield return acc;
89+
}
90+
}
7691
}
7792
}

src/Simulation/Simulators/QCTraceSimulator/Utils.cs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System;
45
using System.Collections.Generic;
6+
using System.Linq;
57
using Microsoft.Quantum.Simulation.Core;
68
using Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime;
79

@@ -214,32 +216,36 @@ static class SimulatorsUtils
214216
/// <param name="uniformZeroOneSample"> Number between Zero and one, uniformly distributed</param>
215217
public static long SampleDistribution(IQArray<double> unnormalizedDistribution, double uniformZeroOneSample)
216218
{
217-
double total = 0.0;
218-
foreach (double prob in unnormalizedDistribution)
219+
if (unnormalizedDistribution.Any(prob => prob < 0.0))
219220
{
220-
if (prob < 0)
221-
{
222-
throw new ExecutionFailException("Random expects array of non-negative doubles.");
223-
}
224-
total += prob;
221+
throw new ExecutionFailException("Random expects array of non-negative doubles.");
225222
}
226223

224+
var total = unnormalizedDistribution.Sum();
227225
if (total == 0)
228226
{
229227
throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
230228
}
231229

232-
double sample = uniformZeroOneSample * total;
233-
double sum = unnormalizedDistribution[0];
234-
for (int i = 0; i < unnormalizedDistribution.Length - 1; ++i)
235-
{
236-
if (sum >= sample)
237-
{
238-
return i;
239-
}
240-
sum += unnormalizedDistribution[i];
241-
}
242-
return unnormalizedDistribution.Length;
230+
var sample = uniformZeroOneSample * total;
231+
232+
return unnormalizedDistribution
233+
// Get the unnormalized CDF of the distribution.
234+
.SelectAggregates((double acc, double x) => acc + x)
235+
// Look for the first index at which the CDF is bigger
236+
// than the random sample of 𝑈(0, 1) that we were given
237+
// as a parameter.
238+
.Select((cumulativeProb, idx) => (cumulativeProb, idx))
239+
.Where(item => item.cumulativeProb >= sample)
240+
// Cast that index to long, and default to returning
241+
// the last item.
242+
.Select(
243+
item => (long)item.idx
244+
)
245+
.DefaultIfEmpty(
246+
unnormalizedDistribution.Length - 1
247+
)
248+
.First();
243249
}
244250
}
245251
}

0 commit comments

Comments
 (0)