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

Commit b351b1b

Browse files
yusudzyurysudz
andauthored
Extends #257 (fixing #256) to QuantumProcessor sim (#302)
* Extends #257 (fixing #256) to QuantumProcessorDispatcher sim as well * Pulled SampleDistribution method out to shared utils Co-authored-by: Yury Sudzilouski <v-yusudz@microsoft.com>
1 parent edc3ad2 commit b351b1b

File tree

5 files changed

+70
-97
lines changed

5 files changed

+70
-97
lines changed

src/Simulation/Common/Utils.cs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
// Licensed under the MIT License.
33

44
using Microsoft.Quantum.Simulation.Core;
5+
using System;
56
using System.Collections.Generic;
67
using System.Diagnostics;
8+
using System.Linq;
79

810
namespace Microsoft.Quantum.Simulation.Common
911
{
10-
public class CommonUtils
12+
public static class CommonUtils
1113
{
1214
/// <summary>
1315
/// Removes PauliI terms from observable and corresponding qubits from qubits.
@@ -25,7 +27,7 @@ public static void PruneObservable(IQArray<Pauli> observable, IQArray<Qubit> qub
2527
/// <summary>
2628
/// Returns IEnumerable&lt;T&gt; that contains sub-sequence of <paramref name="sequenceToPrune"/>[i], such that <paramref name="sequence"/>[i] is not equal to <paramref name="value"/>.
2729
/// </summary>
28-
public static IEnumerable<T> PrunedSequence<U,T>(IQArray<U> sequence, U value, IQArray<T> sequenceToPrune )
30+
public static IEnumerable<T> PrunedSequence<U,T>(IQArray<U> sequence, U value, IQArray<T> sequenceToPrune)
2931
{
3032
for (uint i = 0; i < sequence.Length; ++i)
3133
{
@@ -63,5 +65,65 @@ public static (long, long) Reduce(long numerator, long denominatorPower)
6365

6466
return (numNew, denomPowerNew);
6567
}
68+
69+
/// <summary>
70+
/// Takes an array of doubles as
71+
/// input, and returns a randomly-selected index into the array
72+
/// as an `Int`. The probability of selecting a specific index
73+
/// is proportional to the value of the array element at that index.
74+
/// Array elements that are equal to zero are ignored and their indices
75+
/// are never returned.If any array element is less than zero, or if
76+
/// no array element is greater than zero, then the operation fails.
77+
/// As a source of randomness uses a number uniformly distributed between 0 and 1.
78+
/// Used for Quantum.Intrinsic.Random
79+
/// </summary>
80+
/// <param name="uniformZeroOneSample"> Number between Zero and one, uniformly distributed</param>
81+
public static long SampleDistribution(IQArray<double> unnormalizedDistribution, double uniformZeroOneSample)
82+
{
83+
if (unnormalizedDistribution.Any(prob => prob < 0.0))
84+
{
85+
throw new ExecutionFailException("Random expects array of non-negative doubles.");
86+
}
87+
88+
var total = unnormalizedDistribution.Sum();
89+
if (total == 0)
90+
{
91+
throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
92+
}
93+
94+
var sample = uniformZeroOneSample * total;
95+
96+
return unnormalizedDistribution
97+
// Get the unnormalized CDF of the distribution.
98+
.SelectAggregates((double acc, double x) => acc + x)
99+
// Look for the first index at which the CDF is bigger
100+
// than the random sample of 𝑈(0, 1) that we were given
101+
// as a parameter.
102+
.Select((cumulativeProb, idx) => (cumulativeProb, idx))
103+
.Where(item => item.cumulativeProb >= sample)
104+
// Cast that index to long, and default to returning
105+
// the last item.
106+
.Select(
107+
item => (long)item.idx
108+
)
109+
.DefaultIfEmpty(
110+
unnormalizedDistribution.Length - 1
111+
)
112+
.First();
113+
}
114+
115+
internal static IEnumerable<TResult> SelectAggregates<TSource, TResult>(
116+
this IEnumerable<TSource> source,
117+
Func<TResult, TSource, TResult> aggregate,
118+
TResult initial = default
119+
)
120+
{
121+
var acc = initial;
122+
foreach (var element in source)
123+
{
124+
acc = aggregate(acc, element);
125+
yield return acc;
126+
}
127+
}
66128
}
67129
}

src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,5 @@ public static partial class Extensions
7474
{
7575
return InterfaceType(t, typeof(IControllable<>));
7676
}
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-
}
9177
}
9278
}

src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.random.cs

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

4+
using Microsoft.Quantum.Simulation.Common;
45
using Microsoft.Quantum.Simulation.Core;
56
using System;
67

@@ -18,7 +19,7 @@ public TracerRandom(QCTraceSimulatorImpl m) : base(m)
1819

1920
public override Func<IQArray<double>, Int64> Body => (p) =>
2021
{
21-
return SimulatorsUtils.SampleDistribution(p, core.random.NextDouble());
22+
return CommonUtils.SampleDistribution(p, core.random.NextDouble());
2223
};
2324
}
2425
}

src/Simulation/Simulators/QCTraceSimulator/Utils.cs

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using Microsoft.Quantum.Simulation.Common;
78
using Microsoft.Quantum.Simulation.Core;
89
using Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime;
910

@@ -199,53 +200,4 @@ public static class MetricsCountersNames
199200
/// </summary>
200201
public const string widthCounter = nameof(WidthCounter);
201202
}
202-
203-
static class SimulatorsUtils
204-
{
205-
/// <summary>
206-
/// Takes an array of doubles as
207-
/// input, and returns a randomly-selected index into the array
208-
/// as an `Int`. The probability of selecting a specific index
209-
/// is proportional to the value of the array element at that index.
210-
/// Array elements that are equal to zero are ignored and their indices
211-
/// are never returned.If any array element is less than zero, or if
212-
/// no array element is greater than zero, then the operation fails.
213-
/// As a source of randomness uses a number uniformly distributed between 0 and 1.
214-
/// Used for Quantum.Intrinsic.Random
215-
/// </summary>
216-
/// <param name="uniformZeroOneSample"> Number between Zero and one, uniformly distributed</param>
217-
public static long SampleDistribution(IQArray<double> unnormalizedDistribution, double uniformZeroOneSample)
218-
{
219-
if (unnormalizedDistribution.Any(prob => prob < 0.0))
220-
{
221-
throw new ExecutionFailException("Random expects array of non-negative doubles.");
222-
}
223-
224-
var total = unnormalizedDistribution.Sum();
225-
if (total == 0)
226-
{
227-
throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
228-
}
229-
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();
249-
}
250-
}
251203
}

src/Simulation/Simulators/QuantumProcessor/random.cs

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,13 @@
33

44
using Microsoft.Quantum.Simulation.Core;
55
using System;
6+
using System.Linq;
7+
using Microsoft.Quantum.Simulation.Common;
68

79
namespace Microsoft.Quantum.Simulation.QuantumProcessor
810
{
911
public partial class QuantumProcessorDispatcher
1012
{
11-
public static long SampleDistribution(IQArray<double> unnormalizedDistribution, double uniformZeroOneSample)
12-
{
13-
double total = 0.0;
14-
foreach (double prob in unnormalizedDistribution)
15-
{
16-
if (prob < 0)
17-
{
18-
throw new ExecutionFailException("Random expects array of non-negative doubles.");
19-
}
20-
total += prob;
21-
}
22-
23-
if (total == 0)
24-
{
25-
throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
26-
}
27-
28-
double sample = uniformZeroOneSample * total;
29-
double sum = unnormalizedDistribution[0];
30-
for (int i = 0; i < unnormalizedDistribution.Length - 1; ++i)
31-
{
32-
if (sum >= sample)
33-
{
34-
return i;
35-
}
36-
sum += unnormalizedDistribution[i];
37-
}
38-
return unnormalizedDistribution.Length;
39-
}
40-
4113
public class QuantumProcessorDispatcherRandom : Quantum.Intrinsic.Random
4214
{
4315
private QuantumProcessorDispatcher Simulator { get; }
@@ -48,7 +20,7 @@ public QuantumProcessorDispatcherRandom(QuantumProcessorDispatcher m) : base(m)
4820

4921
public override Func<IQArray<double>, Int64> Body => (p) =>
5022
{
51-
return SampleDistribution(p, Simulator.random.NextDouble());
23+
return CommonUtils.SampleDistribution(p, Simulator.random.NextDouble());
5224
};
5325
}
5426
}

0 commit comments

Comments
 (0)