diff --git a/src/Simulation/Common/Utils.cs b/src/Simulation/Common/Utils.cs
index 752c4048dcd..4be748429c7 100644
--- a/src/Simulation/Common/Utils.cs
+++ b/src/Simulation/Common/Utils.cs
@@ -2,12 +2,14 @@
// Licensed under the MIT License.
using Microsoft.Quantum.Simulation.Core;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
namespace Microsoft.Quantum.Simulation.Common
{
- public class CommonUtils
+ public static class CommonUtils
{
///
/// Removes PauliI terms from observable and corresponding qubits from qubits.
@@ -25,7 +27,7 @@ public static void PruneObservable(IQArray observable, IQArray qub
///
/// Returns IEnumerable<T> that contains sub-sequence of [i], such that [i] is not equal to .
///
- public static IEnumerable PrunedSequence(IQArray sequence, U value, IQArray sequenceToPrune )
+ public static IEnumerable PrunedSequence(IQArray sequence, U value, IQArray sequenceToPrune)
{
for (uint i = 0; i < sequence.Length; ++i)
{
@@ -63,5 +65,65 @@ public static (long, long) Reduce(long numerator, long denominatorPower)
return (numNew, denomPowerNew);
}
+
+ ///
+ /// Takes an array of doubles as
+ /// input, and returns a randomly-selected index into the array
+ /// as an `Int`. The probability of selecting a specific index
+ /// is proportional to the value of the array element at that index.
+ /// Array elements that are equal to zero are ignored and their indices
+ /// are never returned.If any array element is less than zero, or if
+ /// no array element is greater than zero, then the operation fails.
+ /// As a source of randomness uses a number uniformly distributed between 0 and 1.
+ /// Used for Quantum.Intrinsic.Random
+ ///
+ /// Number between Zero and one, uniformly distributed
+ public static long SampleDistribution(IQArray unnormalizedDistribution, double uniformZeroOneSample)
+ {
+ if (unnormalizedDistribution.Any(prob => prob < 0.0))
+ {
+ throw new ExecutionFailException("Random expects array of non-negative doubles.");
+ }
+
+ var total = unnormalizedDistribution.Sum();
+ if (total == 0)
+ {
+ throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
+ }
+
+ var sample = uniformZeroOneSample * total;
+
+ return unnormalizedDistribution
+ // Get the unnormalized CDF of the distribution.
+ .SelectAggregates((double acc, double x) => acc + x)
+ // Look for the first index at which the CDF is bigger
+ // than the random sample of 𝑈(0, 1) that we were given
+ // as a parameter.
+ .Select((cumulativeProb, idx) => (cumulativeProb, idx))
+ .Where(item => item.cumulativeProb >= sample)
+ // Cast that index to long, and default to returning
+ // the last item.
+ .Select(
+ item => (long)item.idx
+ )
+ .DefaultIfEmpty(
+ unnormalizedDistribution.Length - 1
+ )
+ .First();
+ }
+
+ internal static IEnumerable SelectAggregates(
+ this IEnumerable source,
+ Func aggregate,
+ TResult initial = default
+ )
+ {
+ var acc = initial;
+ foreach (var element in source)
+ {
+ acc = aggregate(acc, element);
+ yield return acc;
+ }
+ }
}
}
diff --git a/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs b/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs
index f3beba01330..b8a4c79c1d8 100644
--- a/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs
+++ b/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs
@@ -74,19 +74,5 @@ public static partial class Extensions
{
return InterfaceType(t, typeof(IControllable<>));
}
-
- internal static IEnumerable SelectAggregates(
- this IEnumerable source,
- Func aggregate,
- TResult initial = default
- )
- {
- var acc = initial;
- foreach (var element in source)
- {
- acc = aggregate(acc, element);
- yield return acc;
- }
- }
}
}
\ No newline at end of file
diff --git a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.random.cs b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.random.cs
index 1fea9dbfeea..2a5578ed962 100644
--- a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.random.cs
+++ b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.random.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using System;
@@ -18,7 +19,7 @@ public TracerRandom(QCTraceSimulatorImpl m) : base(m)
public override Func, Int64> Body => (p) =>
{
- return SimulatorsUtils.SampleDistribution(p, core.random.NextDouble());
+ return CommonUtils.SampleDistribution(p, core.random.NextDouble());
};
}
}
diff --git a/src/Simulation/Simulators/QCTraceSimulator/Utils.cs b/src/Simulation/Simulators/QCTraceSimulator/Utils.cs
index 9f991e7ed0c..ddeac1ab574 100644
--- a/src/Simulation/Simulators/QCTraceSimulator/Utils.cs
+++ b/src/Simulation/Simulators/QCTraceSimulator/Utils.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.Quantum.Simulation.Common;
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime;
@@ -199,53 +200,4 @@ public static class MetricsCountersNames
///
public const string widthCounter = nameof(WidthCounter);
}
-
- static class SimulatorsUtils
- {
- ///
- /// Takes an array of doubles as
- /// input, and returns a randomly-selected index into the array
- /// as an `Int`. The probability of selecting a specific index
- /// is proportional to the value of the array element at that index.
- /// Array elements that are equal to zero are ignored and their indices
- /// are never returned.If any array element is less than zero, or if
- /// no array element is greater than zero, then the operation fails.
- /// As a source of randomness uses a number uniformly distributed between 0 and 1.
- /// Used for Quantum.Intrinsic.Random
- ///
- /// Number between Zero and one, uniformly distributed
- public static long SampleDistribution(IQArray unnormalizedDistribution, double uniformZeroOneSample)
- {
- if (unnormalizedDistribution.Any(prob => prob < 0.0))
- {
- throw new ExecutionFailException("Random expects array of non-negative doubles.");
- }
-
- var total = unnormalizedDistribution.Sum();
- if (total == 0)
- {
- throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
- }
-
- var sample = uniformZeroOneSample * total;
-
- return unnormalizedDistribution
- // Get the unnormalized CDF of the distribution.
- .SelectAggregates((double acc, double x) => acc + x)
- // Look for the first index at which the CDF is bigger
- // than the random sample of 𝑈(0, 1) that we were given
- // as a parameter.
- .Select((cumulativeProb, idx) => (cumulativeProb, idx))
- .Where(item => item.cumulativeProb >= sample)
- // Cast that index to long, and default to returning
- // the last item.
- .Select(
- item => (long)item.idx
- )
- .DefaultIfEmpty(
- unnormalizedDistribution.Length - 1
- )
- .First();
- }
- }
}
diff --git a/src/Simulation/Simulators/QuantumProcessor/random.cs b/src/Simulation/Simulators/QuantumProcessor/random.cs
index d9c51cfa202..0b0452c23c8 100644
--- a/src/Simulation/Simulators/QuantumProcessor/random.cs
+++ b/src/Simulation/Simulators/QuantumProcessor/random.cs
@@ -3,41 +3,13 @@
using Microsoft.Quantum.Simulation.Core;
using System;
+using System.Linq;
+using Microsoft.Quantum.Simulation.Common;
namespace Microsoft.Quantum.Simulation.QuantumProcessor
{
public partial class QuantumProcessorDispatcher
{
- public static long SampleDistribution(IQArray unnormalizedDistribution, double uniformZeroOneSample)
- {
- double total = 0.0;
- foreach (double prob in unnormalizedDistribution)
- {
- if (prob < 0)
- {
- throw new ExecutionFailException("Random expects array of non-negative doubles.");
- }
- total += prob;
- }
-
- if (total == 0)
- {
- throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
- }
-
- double sample = uniformZeroOneSample * total;
- double sum = unnormalizedDistribution[0];
- for (int i = 0; i < unnormalizedDistribution.Length - 1; ++i)
- {
- if (sum >= sample)
- {
- return i;
- }
- sum += unnormalizedDistribution[i];
- }
- return unnormalizedDistribution.Length;
- }
-
public class QuantumProcessorDispatcherRandom : Quantum.Intrinsic.Random
{
private QuantumProcessorDispatcher Simulator { get; }
@@ -48,7 +20,7 @@ public QuantumProcessorDispatcherRandom(QuantumProcessorDispatcher m) : base(m)
public override Func, Int64> Body => (p) =>
{
- return SampleDistribution(p, Simulator.random.NextDouble());
+ return CommonUtils.SampleDistribution(p, Simulator.random.NextDouble());
};
}
}