diff --git a/samples/algorithms/database-search/host.py b/samples/algorithms/database-search/host.py new file mode 100644 index 000000000000..ede635530170 --- /dev/null +++ b/samples/algorithms/database-search/host.py @@ -0,0 +1,117 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import math +import qsharp +from Microsoft.Quantum.Samples.DatabaseSearch import ApplyQuantumSearch, ApplyGroverSearch + +def random_oracle(): + """Let us investigate the success probability of classical random search. + + This corresponds to the case where we only prepare the start state, and + do not perform any Grover iterates to amplify the marked subspace. + """ + n_iterations = 0 + + # Define the size `N` = 2^n of the database to search in terms of number of qubits + n_qubits = 3 + db_size = 2 ** n_qubits + + # We now execute the classical random search and verify that the success + # probability matches the classical result of 1/N. Let us repeat 100 + # times to collect enough statistics. + classical_success = 1 / db_size + repeats = 1000 + success_count = 0 + + print("Classical random search for marked element in database.") + print(f"Database size: {db_size}.") + print(f"Success probability: {classical_success}.\n") + + for i in range(repeats): + # The simulation returns a tuple like so: (Int, List). + marked_qubit, db_register = ApplyQuantumSearch.simulate(nIterations=n_iterations, nDatabaseQubits=n_qubits) + success_count += 1 if marked_qubit == 1 else 0 + # Print the results of the search every 100 attempts + if (i + 1) % 100 == 0: + print(f"Attempt: {i}. Success: {marked_qubit}, Probability: {round(success_count / (i + 1), 3)} Found database index: {', '.join([str(x) for x in db_register])}") + +def quantum_oracle(): + """Let us investigate the success probability of the quantum search. + + Now perform Grover iterates to amplify the marked subspace. + """ + n_iterations = 3 + # Number of queries to database oracle. + queries = n_iterations * 2 + 1 + # Define the size `N` = 2^n of the database to search in terms of number of qubits + n_qubits = 6 + db_size = 2 ** n_qubits + + # Now execute the quantum search and verify that the success probability matches the theoretical prediction. + classical_success = 1 / db_size + quantum_success = math.pow(math.sin((2 * n_iterations + 1) * math.asin(1 / math.sqrt(db_size))), 2) + repeats = 100 + success_count = 0 + + print("Quantum search for marked element in database.") + print(f" Database Size: {db_size}") + print(f" Classical Success Probability: {classical_success}") + print(f" Queries per search: {queries}") + print(f" Quantum Success Probability: {quantum_success}.\n") + + for i in range(repeats): + # The simulation returns a tuple like so: (Int, List). + marked_qubit, register = ApplyQuantumSearch.simulate(nIterations=n_iterations, nDatabaseQubits=n_qubits) + success_count += 1 if marked_qubit == 1 else 0 + # Print the results of the search every 10 attempts. + if (i + 1) % 10 == 0: + empirical_success = round(success_count / (i + 1), 3) + # This is how much faster the quantum algorithm performs on average over the classical search. + speed_up = round( (empirical_success / classical_success) / queries, 3) + print(f"Attempt: {i} Success: {marked_qubit} Probability: {empirical_success} Speed: {speed_up} Found database index at: {', '.join([str(x) for x in register])}") + +def multiple_quantum_elements(): + """Let us investigate the success probability of the quantum search with multiple marked elements. + + We perform Grover iterates to amplify the marked subspace. + """ + n_iterations = 3 + # Number of queries to database oracle. + queries = n_iterations * 2 + 1 + # Define the size `N` = 2^n of the database to search in terms of number of qubits + n_qubits = 8 + db_size = 2 ** n_qubits + # We define the marked elements. These must be smaller than `databaseSize`. + marked_elements = [0, 39, 101, 234] + # Now execute the quantum search and verify that the success probability matches the theoretical prediction. + classical_success = len(marked_elements) / db_size + quantum_success = math.pow(math.sin((2 * n_iterations + 1) * math.asin(math.sqrt(len(marked_elements)) / math.sqrt(db_size))), 2) + repeats = 10 + success_count = 0 + + print("Quantum search for marked element in database.") + print(f" Database size: {db_size}.") + print(f" Marked Elements: {', '.join([str(x) for x in marked_elements])}") + print(f" Classical Success Probility: {classical_success}") + print(f" Queries per search: {queries}") + print(f" Quantum success probability: {quantum_success}.\n") + + for i in range(repeats): + # The simulation returns a tuple like so: (Int, List). + marked_qubits, register = ApplyGroverSearch.simulate(markedElements=marked_elements, nIterations=n_iterations, nDatabaseQubits=n_qubits) + success_count += 1 if marked_qubits == 1 else 0 + + # Print the results of the search every attempt. + empirical_success = round(success_count / (i + 1), 3) + # This is how much faster the quantum algorithm performs on average over the classical search. + speed_up = round( (empirical_success / classical_success) / queries, 3) + print(f"Attempt: {i}. Success: {marked_qubits}, Probability: {empirical_success} Speed up: {speed_up} Found database index: {register}") + +if __name__ == "__main__": + random_oracle() + print("\n") + quantum_oracle() + print("\n") + multiple_quantum_elements() + print("\n\n") diff --git a/samples/algorithms/integer-factorization/host.py b/samples/algorithms/integer-factorization/host.py new file mode 100644 index 000000000000..f1ebf25c00c2 --- /dev/null +++ b/samples/algorithms/integer-factorization/host.py @@ -0,0 +1,64 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import argparse +import qsharp +from qsharp import IQSharpError +from Microsoft.Quantum.Samples.IntegerFactorization import FactorInteger + + +def factor_integer(number_to_factor, n_trials, use_robust_phase_estimation): + """ Use Shor's algorithm to factor an integer. + + Shor's algorithm is a probabilistic algorithm and can fail with certain probability in several ways. + For more details see Shor.qs. + """ + # Repeat Shor's algorithm multiple times because the algorithm is + # probabilistic. + for i in range(n_trials): + # Report the number to factor on each attempt. + print("==========================================") + print(f'Factoring {number_to_factor}') + # Compute the factors + try: + output = FactorInteger.simulate( + number=number_to_factor, + useRobustPhaseEstimation=use_robust_phase_estimation, + raise_on_stderr=True) + factor_1, factor_2 = output + print(f"Factors are {factor_1} and {factor_2}.") + except IQSharpError as error: + # Report the failed attempt. + print("This run of Shor's algorithm failed:") + print(error) + + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Factor Integers using Shor's algorithm.") + parser.add_argument( + '-n', + '--number', + type=int, + help='number to be factored.(default=15)', + default=15 + ) + parser.add_argument( + '-t', + '--trials', + type=int, + help='number of trial to perform.(default=10)', + default=10 + ) + parser.add_argument( + '-u', + '--use-robust-pe', + action='store_true', + help='if true uses Robust Phase Estimation, otherwise uses Quantum Phase Estimation.(default=False)', + default=False) + args = parser.parse_args() + if args.number >= 1: + factor_integer(args.number, args.trials, args.use_robust_pe) + else: + print("Error: Invalid number. The number '-n' must be greater than or equal to 1.") diff --git a/samples/algorithms/oracle-synthesis/host.py b/samples/algorithms/oracle-synthesis/host.py new file mode 100644 index 000000000000..82b42755189c --- /dev/null +++ b/samples/algorithms/oracle-synthesis/host.py @@ -0,0 +1,30 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +from Microsoft.Quantum.Samples.OracleSynthesis import RunOracleSynthesisOnCleanTarget, RunOracleSynthesis + +if __name__ == "__main__": + """Runs the Oracle Synthesis. + + The input 'func' is suppose to be an integer representation of a truth table. + So if 'func' = 5 then the truth table is [1, 0, 1] which is actually encoded as [-1, 1, -1] => [true, false, true]. + The input 'vars' determines the size of the truth table such that the length of a the table = 2 ** 'vars'. + So if 'vars' = 3 then the table will have 8 values. + """ + print("Running Synthesis on clean target...") + for i in range(256): + # Implements oracle circuit for a given function, assuming that target qubit is initialized 0. + # The adjoint operation assumes that the target qubit will be released to 0. + res = RunOracleSynthesisOnCleanTarget.simulate(func=i, vars=3) + if not res: + print(f"Result = {res}") + print("Complete.\n") + + print("Running Synthesis...") + for i in range(256): + # Implements oracle circuit for function + res = RunOracleSynthesis.simulate(func=i, vars=3) + if not res: + print(f"Result = {res}") + print("Complete.\n") diff --git a/samples/algorithms/order_finding.py b/samples/algorithms/order_finding.py new file mode 100644 index 000000000000..7a8af24886f8 --- /dev/null +++ b/samples/algorithms/order_finding.py @@ -0,0 +1,125 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import argparse +import random +import qsharp +from Microsoft.Quantum.Samples.OrderFinding import FindOrder + + +def get_order(perm, index): + """Returns the exact order (length) of the cycle that contains a given index. + """ + order = 1 + curr = index + while index != perm[curr]: + order += 1 + curr = perm[curr] + return order + + +def guess_quantum(perm, index): + """Estimates the order of a cycle, using a quantum algorithm defined in the Q# file. + + Computes the permutation πⁱ(input) where i is a superposition of all values from 0 to 7. + The algorithm then uses QFT to find a period in the resulting state. + The result needs to be post-processed to find the estimate. + """ + result = FindOrder.simulate(perm=perm, input=index) + if result == 0: + guess = random.random() + # The probability distribution is extracted from the second column (m = 0) in Fig. 2's table + # on the right-hand side, as shown in L.M.K. Vandersypen et al., PRL 85, 5452, 2000 (https://arxiv.org/abs/quant-ph/0007017). + if guess <= 0.5505: + return 1 + elif guess <= 0.5505 + 0.1009: + return 2 + elif guess <= 0.5505 + 0.1009 + 0.1468: + return 3 + return 4 + elif result % 2 == 1: + return 3 + elif (result == 2) or (result == 6): + return 4 + return 2 + + +def guess_classical(perm, index): + """Guesses the order (classically) for cycle that contains a given index + + The algorithm computes π³(index). If the result is index, it + returns 1 or 3 with probability 50% each, otherwise, it + returns 2 or 4 with probability 50% each. + """ + if perm[perm[perm[index]]] == index: + return random.choice([1, 3]) + return random.choice([2, 4]) + + +def guess_order(perm, index, n): + + # This object counts the number of times the quantum algorithm guesses a + # given order.(so { order: count }) + q_guesses = {k + 1: 0 for k in perm} + # This object counts the number of times the classical algorithm guesses a + # given order.(so { order: count }) + c_guesses = {k + 1: 0 for k in perm} + + # Guess the order, 'n' amount of times. + for i in range(n): + # Count the classical guesses. + c_guesses[guess_classical(perm, index)] += 1 + # Count the quantum guesses. + q_guesses[guess_quantum(perm, index)] += 1 + + print("\nClassical Guesses: ") + for order, count in c_guesses.items(): + # Return the percentage of each order guess, which = (num_of_guesses / + # total_guesses) * 100. + print(f"{order}: {count / n : 0.2%}") + + print("\nQuantum Guesses: ") + for order, count in q_guesses.items(): + # Return the percentage of each order guess, which = (num_of_guesses / + # total_guesses) * 100. + print(f"{order}: {count / n : 0.2%}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Guess the order of a given permutation, using both classical and Quantum computing.") + parser.add_argument( + '-p', + '--permutation', + nargs=4, + type=int, + help='provide only four integers to form a permutation.(default=[1,2,3,0])', + metavar='INT', + default=[ + 1, + 2, + 3, + 0]) + parser.add_argument( + '-i', + '--index', + type=int, + help='the permutations cycle index.(default=0)', + default=0 + ) + parser.add_argument( + '-s', + '--shots', + type=int, + help='number of repetitions when guessing.(default=1024)', + default=1024 + ) + + args = parser.parse_args() + print(f"Permutation: {args.permutation}") + print(f"Find cycle length at index: {args.index}") + + exact_order = get_order(args.permutation, args.index) + print(f"Exact order: {exact_order}") + + guess_order(args.permutation, args.index, args.shots) diff --git a/samples/algorithms/reversible-logic-synthesis/host.py b/samples/algorithms/reversible-logic-synthesis/host.py new file mode 100644 index 000000000000..82fb6e29728b --- /dev/null +++ b/samples/algorithms/reversible-logic-synthesis/host.py @@ -0,0 +1,14 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +from Microsoft.Quantum.Samples.ReversibleLogicSynthesis import SimulatePermutation, FindHiddenShift + +if __name__ == "__main__": + perm = [0, 2, 3, 5, 7, 1, 4, 6] + res = SimulatePermutation.simulate(perm=perm) + print(f'Does circuit realize permutation: {res}') + + for shift in range(len(perm)): + measure = FindHiddenShift.simulate(perm=perm, shift=shift) + print(f'Applied shift = {shift} Measured shift: {measure}') diff --git a/samples/chemistry/AnalyzeHamiltonian/host.py b/samples/chemistry/AnalyzeHamiltonian/host.py new file mode 100644 index 000000000000..66251a742235 --- /dev/null +++ b/samples/chemistry/AnalyzeHamiltonian/host.py @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import numpy as np +from numpy import linalg as LA +from qsharp.chemistry import load_broombridge, load_fermion_hamiltonian, IndexConvention + + +LiH = '../IntegralData/YAML/lih_sto-3g_0.800_int.yaml' + +print(f"Processing the following file: {LiH}") +broombridge = load_broombridge(LiH) +general_hamiltonian = broombridge.problem_description[0].load_fermion_hamiltonian( + index_convention=IndexConvention.UpDown) +print("End of file. Computing One-norms:") +for term, matrix in general_hamiltonian.terms: + one_norm = LA.norm(np.asarray([v for k, v in matrix], dtype=np.float32), ord=1) + print(f"One-norm for term type {term}: {one_norm}") diff --git a/samples/error-correction/bit-flip-code/host.py b/samples/error-correction/bit-flip-code/host.py new file mode 100644 index 000000000000..d8da7147a87a --- /dev/null +++ b/samples/error-correction/bit-flip-code/host.py @@ -0,0 +1,44 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +from Microsoft.Quantum.Samples.BitFlipCode import ( + CheckBitFlipCodeCorrectsBitFlipErrors, + CheckBitFlipCodeStateParity, + CheckCanonBitFlipCodeCorrectsBitFlipErrors +) + +"""First, we call the CheckBitFlipCodeStateParity operation defined in BitFlipCode. +This operation encodes into a bit-flip code, such that + + α |0〉 + β |1〉 + +is encoded into + + α |000〉 + β |111〉, + +then ensures that the parity measurements Z₀Z₁ and +Z₁Z₂ both return the result Zero, indicating the eigenvalue +(-1)⁰ is positive. +This check is implemented as a sequence of assertions. +Since we are using a target machine which supports assertions, +this implies that if flow control continues past the operation +invocation, then all of the relevant checks have passed +""" +CheckBitFlipCodeStateParity.simulate() +print("\nParity check passed successfully!\n") + +"""Next, we call the operation CheckBitFlipCodeCorrectsBitFlipErrors to check that the bit-flip code actually protects against bit-flip errors. + +As before, this operation fails if an error is not corrected properly. +In the UnitTesting sample, we will see how to represent this pattern in terms of unit tests. +""" +CheckBitFlipCodeCorrectsBitFlipErrors.simulate() +print("Corrected all three bit-flip errors successfully!\n") + +"""Finally, we repeat the check from above. + +This time using operations and data types from the canon to allow us to represent other codes. +""" +CheckCanonBitFlipCodeCorrectsBitFlipErrors.simulate() +print("Corrected all three bit-flip errors successfully!\n") diff --git a/samples/getting-started/simple-algorithms/host.py b/samples/getting-started/simple-algorithms/host.py new file mode 100644 index 000000000000..aebb51889cdc --- /dev/null +++ b/samples/getting-started/simple-algorithms/host.py @@ -0,0 +1,89 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +from Microsoft.Quantum.Samples.SimpleAlgorithms import BernsteinVaziraniTestCase, DeutschJozsaTestCase, HiddenShiftBentCorrelationTestCase + + +def bernstein_vazirani(n_qubits=4): + """Consider a function 𝑓(𝑥⃗) on bitstrings 𝑥⃗ = (𝑥₀, …, 𝑥ₙ₋₁) of the form: + + 𝑓(𝑥⃗) ≔ Σᵢ 𝑥ᵢ 𝑟ᵢ + + where 𝑟⃗ = (𝑟₀, …, 𝑟ₙ₋₁) is an unknown bitstring that determines the parity of 𝑓. + The Bernstein–Vazirani algorithm allows determining 𝑟 given a quantum operation that implements + + |𝑥〉|𝑦〉 ↦ |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉. + + In SimpleAlgorithms.qs, we implement this algorithm as the operation BernsteinVaziraniTestCase. + This operation takes an integer whose bits describe 𝑟, then uses those bits to construct an appropriate operation, + and finally measures 𝑟. + """ + for parity in range(1 << n_qubits): + measured = BernsteinVaziraniTestCase.simulate( + nQubits=n_qubits, patternInt=parity) + if measured != parity: + raise Exception( + 'Bernstein_Vazirani', + f"Measured parity {measured}, but expected {parity}.") + print("All parities measured successfully!") + + +def deutsch_jozsa(): + """A Boolean function is a function that maps bitstrings to a bit, + 𝑓 : {0, 1}^n → {0, 1}. + + We say that 𝑓 is constant if 𝑓(𝑥⃗) = 𝑓(𝑦⃗) for all bitstrings 𝑥⃗ and 𝑦⃗, and that 𝑓 is balanced if 𝑓 evaluates to true (1) + for exactly half of its inputs. + + If we are given a function 𝑓 as a quantum operation 𝑈 |𝑥〉|𝑦〉 = |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉, and are promised that 𝑓 is either + constant or is balanced, then the Deutsch–Jozsa algorithm decides between these cases with a single application of 𝑈. + + In SimpleAlgorithms.qs, we implement this algorithm as DeutschJozsaTestCase, following the pattern above. + This time, however, we will pass an array to Q# indicating which elements of 𝑓 are marked; that is, should result in true. + We check by ensuring that DeutschJozsaTestCase returns true for constant functions and false for balanced functions. + """ + balanced_test = [1, 2] + if DeutschJozsaTestCase.simulate(nQubits=2, markedElements=balanced_test): + raise Exception( + 'Deutsch_Jozsa', + f"Measured that test case {balanced_test} was constant!") + + constant_test = [0, 1, 2, 3, 4, 5, 6, 7] + if not DeutschJozsaTestCase.simulate( + nQubits=3, markedElements=constant_test): + raise Exception( + 'Deutsch_Jozsa', + f"Measured that test case {constant_test} was constant!") + print("Both constant and balanced functions measured successfully!") + + +def roetteler(n_qubits=4): + """Finally, we consider the case of finding a hidden shift 𝑠 between two Boolean functions 𝑓(𝑥) and 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠). + + This problem can be solved on a quantum computer with one call to each of 𝑓 and 𝑔 in the special case that both functions are + bent; that is, that they are as far from linear as possible. + + Here, we run the test case HiddenShiftBentCorrelationTestCase defined in the matching Q# source code, and ensure that it + correctly finds each hidden shift for a family of bent functions defined by the inner product. + """ + for shift in range(1 << n_qubits): + measured = HiddenShiftBentCorrelationTestCase.simulate( + patternInt=shift, u=n_qubits / 2) + if measured != shift: + raise Exception( + 'Roetteler', + f"Measured parity {measured}, but expected {shift}.") + print("Measured hidden shifts successfully!") + + +if __name__ == "__main__": + try: + bernstein_vazirani() + print() + deutsch_jozsa() + print() + roetteler() + except Exception as e: + func_name, message = e.args + print(f"Error in {func_name}: {message}") diff --git a/samples/numerics/CustomModAdd/host.py b/samples/numerics/CustomModAdd/host.py new file mode 100644 index 000000000000..6c96397a13f4 --- /dev/null +++ b/samples/numerics/CustomModAdd/host.py @@ -0,0 +1,31 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp + +print("Loading the numerics library...") +# Need to load the numerics library. +qsharp.packages.add("Microsoft.Quantum.Numerics") +print("Done. Running program...") +# Refresh to make sure the file is correctly compiled. +qsharp.reload() +from Microsoft.Quantum.Numerics.Samples import CustomModAdd + +if __name__ == "__main__": + """Tests a modular addition similar to the one in Fig. 4 of https://arxiv.org/pdf/quant-ph/9511018v1.pdf.""" + + # List of integers to use for the first number. + input_a = [3, 5, 3, 4, 5] + # List of integers to use for the second number. + input_b = [5, 4, 6, 4, 1] + # Modulus used when adding each pair of numbers. + mod = 7 + # Number of bits to use to represent each number. + n = 4 + # Operation returns a list of results of the same length as the `input_a`. + # ( so len(results) == len(input_a) ) + results = CustomModAdd.toffoli_simulate( + inputs1=input_a, inputs2=input_b, modulus=mod, numBits=n) + + for a, b, result in zip(input_a, input_b, results): + print(f"{a} + {b} mod {mod} = {result}.") diff --git a/samples/numerics/EvaluatingFunctions/host.py b/samples/numerics/EvaluatingFunctions/host.py new file mode 100644 index 000000000000..86f6f2d67738 --- /dev/null +++ b/samples/numerics/EvaluatingFunctions/host.py @@ -0,0 +1,53 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import math +import qsharp +print("Loading the numerics library...") +# Need to load the numerics library. +qsharp.packages.add("Microsoft.Quantum.Numerics") +print("Done. Running program...") +# Refresh to make sure the file is correctly compiled. +qsharp.reload() +from Microsoft.Quantum.Numerics.Samples import EvaluatePolynomial + +if __name__ == "__main__": + """Evaluates the polynomial given by `coefficients` at the evaluation points provided.""" + + # Points at which to evaluate the polynomial + eval_points = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6] + # Polynomial coefficients + coefficients = [0.9992759725166501, -0.16566707016968898, + 0.007958079331694682, -0.0001450780334861007] + # Point position to use for the fixed-point representation + point_position = 3 + # Number of bits to use to represent each fixed-point number + num_bits = 64 + # If True, evaluates an odd polynomial + odd = True + # If True, evaluates an even polynomial + even = False + + # This is just a string that will print out the complete polynomial. + polynomial = f"Evaluating P(x) = {coefficients[0]}" + if odd: + polynomial += "*x" + # Further construct the polynomial string. + for i in range(1, len(coefficients)): + polynomial += f" + {coefficients[i]}* x^{i + (i + 1 if odd else 0) + (i if even else 0)} " + # Show the polynomial. + print(f"{polynomial}.") + # Operation returns a list of results of the same length as the + # `eval_points`. ( so len(results) == len(eval_points) ) + res = EvaluatePolynomial.toffoli_simulate( + coefficients=coefficients, + evaluationPoints=eval_points, + numBits=num_bits, + pointPos=point_position, + odd=odd, + even=even + ) + + for i in range(len(res)): + print( + f"P({eval_points[i]}) = {res[i]}. [sin(x) = {math.sin(eval_points[i])}]") diff --git a/samples/numerics/ResourceCounting/host.py b/samples/numerics/ResourceCounting/host.py new file mode 100644 index 000000000000..7f5f24172a4f --- /dev/null +++ b/samples/numerics/ResourceCounting/host.py @@ -0,0 +1,48 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +print("Loading the numerics library...") +# Need to load the numerics library. +qsharp.packages.add("Microsoft.Quantum.Numerics") +print("Done. Running program...") +# Refresh to make sure the file is correctly compiled. +qsharp.reload() +from Microsoft.Quantum.Numerics.Samples import EvaluatePolynomial + +if __name__ == "__main__": + # Points at which to evaluate the polynomial + eval_points = [0] + # Polynomial coefficients + coefficients = [0.9992759725166501, -0.16566707016968898, + 0.007958079331694682, -0.0001450780334861007] + # Point position to use for the fixed-point representation + point_position = 3 + # Number of bits to use to represent each fixed-point number + num_bits = 32 + # If True, evaluates an odd polynomial + odd = True + # If True, evaluates an even polynomial + even = False + # This is just a string that will print out the complete polynomial. + polynomial = f"Resource counting for P(x) = {coefficients[0]}" + if odd: + polynomial += "*x" + # Further construct the polynomial string. + for i in range(len(coefficients)): + polynomial += f" + {coefficients[i]}* x^{i + (i + 1 if odd else 0) + (i if even else 0)}" + # Show the polynomial. + print(f"{polynomial}.") + + res = EvaluatePolynomial.estimate_resources( + coefficients=coefficients, + evaluationPoints=eval_points, + numBits=num_bits, + pointPos=point_position, + odd=odd, + even=even + ) + + print("Metric\tSum") + for k, v in res.items(): + print(f"{k}\t{v}") diff --git a/samples/simulation/h2/command-line/host.py b/samples/simulation/h2/command-line/host.py new file mode 100644 index 000000000000..6a58288542b4 --- /dev/null +++ b/samples/simulation/h2/command-line/host.py @@ -0,0 +1,20 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import qsharp +import Microsoft.Quantum.Samples.H2Simulation as H2Simulation + +# Call a Q# operation that takes unit `()` as its input, and returns the +# static bond lengths[float]. +bond_lengths = H2Simulation.H2BondLengths.simulate() +print(f"Number of bond lengths: {len(bond_lengths)}.\n") + +# Run the simulation at each bond length +for i in range(len(bond_lengths)): + print(f"Estimating bond length {bond_lengths[i]}:") + # The result of calling H2EstimateEnergyRPE is a float, so we take the min over + # that to deal with the possibility that we accidentally entered into the excited + # state instead of the ground state of interest. + est = min([H2Simulation.H2EstimateEnergyRPE.simulate( + idxBondLength=i, nBitsPrecision=6, trotterStepSize=1.0) for _ in range(3)]) + print(f"\tEst: {est}\n") diff --git a/samples/simulation/hubbard/host.py b/samples/simulation/hubbard/host.py new file mode 100644 index 000000000000..c060f00d29d3 --- /dev/null +++ b/samples/simulation/hubbard/host.py @@ -0,0 +1,98 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import argparse +import qsharp +from Microsoft.Quantum.Samples.Hubbard import EstimateHubbardAntiFerromagneticEnergy + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Guess the order of a given permutation, using both classical and Quantum computing.") + parser.add_argument( + '-n', + '--number-sites', + type=int, + help='Number of sites in the 1D Hubbard Model.(default=6)', + default=6 + ) + parser.add_argument( + '-u', + '--u-coefficient', + type=float, + help='The repulsion coefficient.(default=1.0)', + default=1.0 + ) + parser.add_argument( + '-t', + '--t-coefficient', + type=float, + help='the hpping coefficient.(default=0.2)', + default=0.2 + ) + parser.add_argument( + '-p', + '--precision', + type=int, + help='The number of bits of precision in phase estimation.(default=7)', + default=7 + ) + parser.add_argument( + '-s', + '--step-size', + type=float, + help='The trotter step size.(default=0.5)', + default=0.5 + ) + parser.add_argument( + '-a', + '--attempts', + type=int, + help='The number of estimation attempts to perform.(default=10)', + default=10 + ) + + args = parser.parse_args() + attempts = args.attempts + # For this example, we'll consider a loop of size sites, each one of which + # is simulated using two qubits. + n = args.number_sites + # Choose a repulsion term somewhat larger than the hopping term to favor + # single-site occupancy. + u = args.u_coefficient + t = args.t_coefficient + + # We need to choose the number of bits of precision in phase estimation. + # Bear in mind that this is bits of precision before rescaling by the trotterStepSize. + # A smaller trotterStepSize would require more bits of precision to obtain + # the same absolute accuracy. + precision = args.precision + + # Choose a small trotter step size for improved simulation error. + # This should be at least small enough to avoid aliasing of estimated + # phases. + step_size = args.step_size + # Energy estimation error. + error = 2 ** (-1 * precision) / step_size + + # Print our parameter definitions. + print(f"""Hubbard model ground state energy estimation: + {n} sites + {u} repulsion term coefficient + {t} hopping term coefficient + {precision} bits of precision + {error} energy estimate error from phase estimation alone + {step_size} time step + {attempts} attempts""") + + # Since there's a finite chance of successfully projecting onto the ground state, + # we will call our new operation through the simulator several times, + # reporting the estimated energy after each attempt. + for i in range(attempts): + energy_est = EstimateHubbardAntiFerromagneticEnergy.simulate( + nSites=n, + tCoefficient=t, + uCoefficient=u, + bitsPrecision=precision, + trotterStepSize=step_size + ) + print(f"Energy estimated in attempt {i}: {energy_est}")