microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
katas/content/random_numbers/weighted_random_bit/Verification.qs
58lines · modecode
| 1 | namespace Kata.Verification { |
| 2 | open Microsoft.Quantum.Math; |
| 3 | open Microsoft.Quantum.Convert; |
| 4 | |
| 5 | @EntryPoint() |
| 6 | operation CheckSolution() : Bool { |
| 7 | for x in [0.0, 0.25, 0.5, 0.75, 1.0] { |
| 8 | Message($"Testing generating zero with {x*100.0}% probability..."); |
| 9 | let randomnessVerifier = () => CheckXPercentZero(() => Kata.WeightedRandomBit(x), x); |
| 10 | let isCorrect = IsSufficientlyRandom(randomnessVerifier); |
| 11 | if not isCorrect { |
| 12 | return false; |
| 13 | } |
| 14 | } |
| 15 | Message("Correct!"); |
| 16 | true |
| 17 | } |
| 18 | |
| 19 | /// # Summary |
| 20 | /// Helper operation that checks that the given RNG operation generates zero with x percent probability |
| 21 | /// # Input |
| 22 | /// ## op |
| 23 | /// Random number generation operation to be tested. |
| 24 | /// ## x |
| 25 | /// Probability of generating zero |
| 26 | operation CheckXPercentZero (op : (Unit => Int), x : Double) : Int { |
| 27 | mutable oneCount = 0; |
| 28 | let nRuns = 1000; |
| 29 | for N in 1..nRuns { |
| 30 | let val = op(); |
| 31 | if (val < 0 or val > 1) { |
| 32 | Message($"Unexpected number generated. Expected 0 or 1, instead generated {val}"); |
| 33 | return 0x1; |
| 34 | } |
| 35 | set oneCount += val; |
| 36 | } |
| 37 | |
| 38 | let zeroCount = nRuns - oneCount; |
| 39 | let goalZeroCount = (x == 0.0) ? 0 | (x == 1.0) ? nRuns | Floor(x * IntAsDouble(nRuns)); |
| 40 | // We don't have tests with probabilities near 0.0 or 1.0, so for those the matching has to be exact |
| 41 | if (goalZeroCount == 0 or goalZeroCount == nRuns) { |
| 42 | if zeroCount != goalZeroCount { |
| 43 | Message($"Expected {x * 100.0}% 0's, instead got {zeroCount} 0's out of {nRuns}"); |
| 44 | return 0x2; |
| 45 | } |
| 46 | } else { |
| 47 | if zeroCount < goalZeroCount - 4 * nRuns / 100 { |
| 48 | Message($"Unexpectedly low number of 0's generated: expected around {x * IntAsDouble(nRuns)} 0's, got {zeroCount} out of {nRuns}"); |
| 49 | return 0x3; |
| 50 | } elif zeroCount > goalZeroCount + 4 * nRuns / 100 { |
| 51 | Message($"Unexpectedly high number of 0's generated: expected around {x * IntAsDouble(nRuns)} 0's, got {zeroCount} out of {nRuns}"); |
| 52 | return 0x4; |
| 53 | } |
| 54 | } |
| 55 | return 0x0; |
| 56 | } |
| 57 | |
| 58 | } |
| 59 | |