From feed9bf5305622d6c86e98802fe8b5f5452494a9 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Thu, 12 Sep 2019 10:35:09 -0700 Subject: [PATCH] Parameterize chemistry cmdline samples using CommandLineUtils. (#226) * Allow for command-line parameterization of two chem samples. * Ported GetGateCount to use same library as other two chem samples. * Slight fixes to get-gatecount. --- .../1-AnalyzeHamiltonian.csproj | 1 + Chemistry/AnalyzeHamiltonian/Program.cs | 55 +++++--- Chemistry/GetGateCount/3-GetGateCount.csproj | 2 +- Chemistry/GetGateCount/Program.cs | 114 ++++++--------- .../RunSimulation/2-RunSimulation.csproj | 1 + Chemistry/RunSimulation/Program.cs | 133 +++++++++++------- 6 files changed, 167 insertions(+), 139 deletions(-) diff --git a/Chemistry/AnalyzeHamiltonian/1-AnalyzeHamiltonian.csproj b/Chemistry/AnalyzeHamiltonian/1-AnalyzeHamiltonian.csproj index 01da5b1d517f..1e908a6e70b6 100644 --- a/Chemistry/AnalyzeHamiltonian/1-AnalyzeHamiltonian.csproj +++ b/Chemistry/AnalyzeHamiltonian/1-AnalyzeHamiltonian.csproj @@ -10,6 +10,7 @@ + diff --git a/Chemistry/AnalyzeHamiltonian/Program.cs b/Chemistry/AnalyzeHamiltonian/Program.cs index 95edfa33a78e..4cedd02595e8 100644 --- a/Chemistry/AnalyzeHamiltonian/Program.cs +++ b/Chemistry/AnalyzeHamiltonian/Program.cs @@ -5,6 +5,7 @@ using Microsoft.Quantum.Chemistry; using System.Linq; using Microsoft.Quantum.Chemistry.OrbitalIntegrals; +using McMaster.Extensions.CommandLineUtils; // This loads a Hamiltonian from file and computes some of its features // - L1-Norm of terms @@ -15,7 +16,23 @@ namespace Microsoft.Quantum.Chemistry.Sample class Program { - static void Main(string[] args) + public static int Main(string[] args) => + CommandLineApplication.Execute(args); + + public enum DataFormat + { + LiQuiD, Broombridge + } + + [Option(Description = "Format to use when loading data.")] + public DataFormat Format { get; } = DataFormat.Broombridge; + + [Option(Description = "Path to data to be loaded.")] + public string Path { get; } = System.IO.Path.Combine( + "..", "IntegralData", "YAML", "lih_sto-3g_0.800_int.yaml" + ); + + void OnExecute() { var logger = Logging.LoggerFactory.CreateLogger(); @@ -33,28 +50,31 @@ static void Main(string[] args) "nitrogenase_tzvp_54.dat" // 108 SO */ - string LiquidRoot = @"..\IntegralData\Liquid\"; - string LiquidFilename = "Be_sto6g_10.dat"; - // For loading data in the format consumed by Liquid. - logger.LogInformation($"Processing {LiquidFilename}"); - var generalHamiltonian0 = LiQuiD.Deserialize($@"{LiquidRoot}\{LiquidFilename}").Single() - .OrbitalIntegralHamiltonian - .ToFermionHamiltonian(IndexConvention.UpDown); + logger.LogInformation($"Processing {Path}..."); + var generalHamiltonian = + ( + Format == DataFormat.Broombridge - // For loading data in the YAML format. - string YAMLRoot = @"..\IntegralData\YAML\"; - string YAMLFilename = "lih_sto-3g_0.800_int.yaml"; - var generalHamiltonian1 = Broombridge.Deserializers.DeserializeBroombridge($@"{YAMLRoot}\{YAMLFilename}") - .ProblemDescriptions.Single() - .OrbitalIntegralHamiltonian + ? Broombridge + .Deserializers + .DeserializeBroombridge(Path) + .ProblemDescriptions + .Single() + .OrbitalIntegralHamiltonian + + : LiQuiD + .Deserialize(Path) + .Single() + .OrbitalIntegralHamiltonian + ) .ToFermionHamiltonian(IndexConvention.UpDown); - // Read Hamiltonian terms from file. logger.LogInformation("End read file. Computing one-norms."); - foreach (var termType in generalHamiltonian0.Terms.Keys) + + foreach (var termType in generalHamiltonian.Terms.Keys) { - var line = $"One-norm for term type {termType}: {generalHamiltonian0.Norm(new[] { termType }, 1.0)}"; + var line = $"One-norm for term type {termType}: {generalHamiltonian.Norm(new[] { termType }, 1.0)}"; logger.LogInformation(line); } logger.LogInformation("Computed one-norm."); @@ -66,4 +86,3 @@ static void Main(string[] args) } } } - diff --git a/Chemistry/GetGateCount/3-GetGateCount.csproj b/Chemistry/GetGateCount/3-GetGateCount.csproj index 1bff0d455f60..eee2024981e9 100644 --- a/Chemistry/GetGateCount/3-GetGateCount.csproj +++ b/Chemistry/GetGateCount/3-GetGateCount.csproj @@ -12,6 +12,7 @@ + @@ -19,7 +20,6 @@ - diff --git a/Chemistry/GetGateCount/Program.cs b/Chemistry/GetGateCount/Program.cs index fffa7a16f114..67d51d02e997 100644 --- a/Chemistry/GetGateCount/Program.cs +++ b/Chemistry/GetGateCount/Program.cs @@ -18,9 +18,9 @@ // in a robust way that makes it easy to turn on and off different messages. using Microsoft.Extensions.Logging; -// We use the Mono.Options and System.Management.Automation -// libraries to make it easy to use this sample from the command line. -using Mono.Options; +// We use the McMaster.Extensions.CommandLineUtils +// library to make it easy to use this sample from the command line. +using McMaster.Extensions.CommandLineUtils; // Finally, we include the gate counting logic itself from GetGateCount.cs. using static Microsoft.Quantum.Chemistry.Samples.GetGateCount; @@ -30,83 +30,58 @@ namespace Microsoft.Quantum.Chemistry.Samples { class Program { - static void Main(string[] args) - { + public static int Main(string[] args) => + CommandLineApplication.Execute(args); + - string filename = @"..\IntegralData\Liquid\h2s_sto6g_22.dat"; - var format = IntegralDataFormat.Liquid; - - bool runTrotterStep = true; - bool runMinQubitQubitizationStep = true; - bool runMinTCountQubitizationStep = true; - bool showHelp = false; - string outputFolder = null; - - string logPath = null; - - // These are arguments that can be set from command line. - var options = new OptionSet { - { "h|?|help", "Shows this help message.", h => showHelp = true }, - { "p|path=", "Path to the integral data file to use.", f => filename = f }, - { "f|format=", - "Format to use when loading integral data.", - (string f) => format = (IntegralDataFormat) Enum.Parse(typeof(IntegralDataFormat), f) - }, - { "t|run-trotter=", - "Controls whether the Trotter simulation step will be estimated.", - (bool t) => runTrotterStep = t - }, - { "q|run-qubitization=", - "Controls whether the qubitization simulation step that minimizes qubit count will be estimated.", - (bool q) => runMinQubitQubitizationStep = q - }, - { "o|run-optimized-qubitization=", - "Controls whether the qubitization simulation step that minimizes T count will be estimated.", - (bool o) => runMinTCountQubitizationStep = o - }, - { "l|log=", - "Controls where log messages will be written to.", - (string l) => logPath = l - }, - { "output=", - "Specifies the folder into which gate count estimates should be written as CSVs.", - (string o) => outputFolder = o - } - }; + [Option("-p|--path", Description = "Path to the integral data file to use.")] + public string Path { get; } = System.IO.Path.Combine( + "..", "IntegralData", "Liquid", "h2s_sto6g_22.dat" + ); - // This parses the command line arguments, and catches undefined arguments. - List extra; - try - { - extra = options.Parse(args); - } - catch (OptionException) - { - ShowHelp(options); - System.Environment.Exit(1); - } + [Option("-f|--format", Description="Format to use when loading integral data.")] + public IntegralDataFormat Format { get; } = IntegralDataFormat.Liquid; + + [Option("--skip-trotter-suzuki", Description="If set, skips estimating for the Trotter–Suzuki simulation step.")] + public bool SkipTrotterSuzuki { get; } = false; + public bool RunTrotterSuzuki => !SkipTrotterSuzuki; + + [Option("--skip-qubitization", Description = "If set, skips estimating for the qubitized simulation step.")] + public bool SkipQubitization { get; } = false; + public bool RunQubitization => !SkipQubitization; - if (showHelp) + [Option("--skip-opt-qubitization", Description = "If set, skips estimating for the optimized qubitized simulation step.")] + public bool SkipOptimizedQubitization { get; } = false; + public bool RunOptimizedQubitization => !SkipOptimizedQubitization; + + [Option("-l|--log", Description = "Controls where log messages will be written to.")] + public string LogPath { get; } = null; + + [Option("-o|--output", Description = "Specifies the folder into which gate count estimates should be written as CSVs.")] + public string OutputPath { get; } = null; + + + void OnExecute() + { + if (LogPath != null) { - ShowHelp(options); - System.Environment.Exit(1); + Logging.LogPath = LogPath; } - - Logging.LogPath = logPath; var logger = Logging.LoggerFactory.CreateLogger(); // Here, we specify the Hamiltonian simulation configurations we wish to run. var configurations = Configure( - runTrotterStep: runTrotterStep, - runMinQubitQubitizationStep: runMinQubitQubitizationStep, - runMinTCountQubitizationStep: runMinTCountQubitizationStep); + runTrotterStep: RunTrotterSuzuki, + runMinQubitQubitizationStep: RunQubitization, + runMinTCountQubitizationStep: RunOptimizedQubitization + ); - using (logger.BeginScope($"Using {filename}.")) + using (logger.BeginScope($"Using {Path}.")) { logger.LogInformation($"Loading..."); // Read Hamiltonian terms from file and run gate counts. - var gateCountResults = RunGateCount(filename, format, configurations, outputFolder).Result; + var gateCountResults = RunGateCount(Path, Format, configurations, OutputPath).Result; foreach(var result in gateCountResults) { @@ -120,13 +95,6 @@ static void Main(string[] args) } } - public static void ShowHelp(OptionSet options) - { - System.Console.WriteLine("get-gatecount"); - System.Console.WriteLine("Usage:"); - options.WriteOptionDescriptions(Console.Out); - return; - } } } diff --git a/Chemistry/RunSimulation/2-RunSimulation.csproj b/Chemistry/RunSimulation/2-RunSimulation.csproj index e63d8688b304..2b04f941f277 100644 --- a/Chemistry/RunSimulation/2-RunSimulation.csproj +++ b/Chemistry/RunSimulation/2-RunSimulation.csproj @@ -5,6 +5,7 @@ x64 + diff --git a/Chemistry/RunSimulation/Program.cs b/Chemistry/RunSimulation/Program.cs index cb483242c692..e042d6d30d63 100644 --- a/Chemistry/RunSimulation/Program.cs +++ b/Chemistry/RunSimulation/Program.cs @@ -12,6 +12,7 @@ using Microsoft.Quantum.Chemistry.OrbitalIntegrals; using Microsoft.Quantum.Chemistry.Fermion; using Microsoft.Quantum.Chemistry.QSharpFormat; +using McMaster.Extensions.CommandLineUtils; // This loads a Hamiltonian from file and performs quantum phase estimation on // - Jordan–Wigner Trotter step @@ -23,8 +24,68 @@ namespace Microsoft.Quantum.Chemistry.Samples class Program { + public static int Main(string[] args) => + CommandLineApplication.Execute(args); - static void Main(string[] args) + public enum DataFormat + { + LiQuiD, Broombridge + } + + [Option(Description = "Format to use when loading data.")] + public DataFormat Format { get; } = DataFormat.Broombridge; + + [Option(Description = "Path to data to be loaded.")] + public string Path { get; } = System.IO.Path.Combine( + "..", "IntegralData", "YAML", "lih_sto-3g_0.800_int.yaml" + ); + + [Option("--n-bits", Description = "Number of bits of precision to report from phase estimation.")] + public int NBits { get; } = 10; + + [Option("--n-reps", Description = "Number of repetitions to use to find the minimum energy.")] + public int NRepetitions { get; } = 5; + + [Option("--skip-jw", Description = "Skips simulating phase estimation with a Jordan–Wigner transformed Trotter–Suzuki approximation.")] + public bool SkipJordanWigner { get; } = false; + + public bool RunJordanWigner => !SkipJordanWigner; + + [Option(Description = "Step size to use in the Trotter–Suzuki approximation.")] + public double StepSize { get; } = 0.4; + + [Option("--skip-opt-jw", Description = "Skips simulating phase estimation with an optimized Jordan–Wigner transformed Trotter–Suzuki approximation.")] + public bool SkipOptimizedJordanWigner { get; } = false; + public bool RunOptimizedJordanWigner => !SkipOptimizedJordanWigner; + + [Option("--skip-qubitized-jw", Description = "Skips simulating phase estimation with a Jordan–Wigner transformed qubitization representation.")] + public bool SkipQubitizedJordanWigner { get; } = false; + public bool RunQubitizedJordanWigner => !SkipQubitizedJordanWigner; + + static void ParseLiQuiD(string path, out int nElectrons, out FermionHamiltonian hamiltonian) + { + nElectrons = 2; + hamiltonian = LiQuiD + .Deserialize(path) + .Single() + .OrbitalIntegralHamiltonian + .ToFermionHamiltonian(IndexConvention.UpDown); + } + + static void ParseBroombridge(string path, out int nElectrons, out FermionHamiltonian hamiltonian) + { + var description = Broombridge + .Deserializers + .DeserializeBroombridge(path) + .ProblemDescriptions + .Single(); + nElectrons = description.NElectrons; + hamiltonian = description + .OrbitalIntegralHamiltonian + .ToFermionHamiltonian(IndexConvention.UpDown); + } + + void OnExecute() { var logger = Logging.LoggerFactory.CreateLogger(); @@ -51,29 +112,23 @@ static void Main(string[] args) #region For loading data in the format consumed by Liquid. stopWatch.Start(); - string LiquidRoot = @"..\IntegralData\Liquid\"; - string LiquidFilename = "h2_sto3g_4.dat"; - logger.LogInformation($"Processing {LiquidFilename}"); - var problemDescriptionLiQuiD = LiQuiD.Deserialize($@"{LiquidRoot}\{LiquidFilename}").Single(); - // Number of electrons. This must be specified for the liquid format. - problemDescriptionLiQuiD.NElectrons = 2; + logger.LogInformation($"Processing {Path}..."); + int nElectrons; + FermionHamiltonian fermionHamiltonian; + if (Format == DataFormat.Broombridge) + { + ParseBroombridge(Path, out nElectrons, out fermionHamiltonian); + } + else + { + ParseLiQuiD(Path, out nElectrons, out fermionHamiltonian); + } - logger.LogInformation($"Liquid Load took {stopWatch.ElapsedMilliseconds}ms"); - stopWatch.Restart(); - #endregion - #region For loading data in the Broombridge format. - stopWatch.Start(); - string YAMLRoot = @"..\IntegralData\YAML\"; - string YAMLFilename = "lih_sto-3g_0.800_int.yaml"; - var problemDescriptionBroombridge = Broombridge.Deserializers.DeserializeBroombridge($@"{YAMLRoot}\{YAMLFilename}").ProblemDescriptions.Single(); - logger.LogInformation($"Broombridge Load took {stopWatch.ElapsedMilliseconds}ms"); + logger.LogInformation($"Load took {stopWatch.ElapsedMilliseconds}ms."); stopWatch.Restart(); #endregion - // Select problem description to use - var problemDescription = problemDescriptionBroombridge; - var fermionHamiltonian = problemDescription.OrbitalIntegralHamiltonian.ToFermionHamiltonian(IndexConvention.UpDown); // Logs spin-orbital data in Logger.Message. logger.LogInformation(fermionHamiltonian.ToString()); @@ -82,7 +137,7 @@ static void Main(string[] args) var jordanWignerEncoding = fermionHamiltonian.ToPauliHamiltonian(Paulis.QubitEncoding.JordanWigner); // Create input wavefunction. - var wavefunction = fermionHamiltonian.CreateHartreeFockState(problemDescription.NElectrons); + var wavefunction = fermionHamiltonian.CreateHartreeFockState(nElectrons); // Alternately, use wavefunction contained in problem description, // if available @@ -100,48 +155,32 @@ static void Main(string[] args) // consumed by Q#. var qSharpData = QSharpFormat.Convert.ToQSharpFormat( jordanWignerEncoding.ToQSharpFormat(), - wavefunction.ToQSharpFormat()); + wavefunction.ToQSharpFormat() + ); #region Calling into Q# - // Bits of precision in phase estimation. - var bits = 10; - - // Repetitions to find minimum energy. - var reps = 5; - - // Run phase estimation simulation using Jordan–Wigner Trotterization. - var runJW = true; - - // Trotter step size. - var trotterStep = .4; - - // Run phase estimation simulation using Jordan–Wigner Trotterization with optimzied circuit. - var runJWOptimized = true; - - // Run phase estimation simulation using Jordan–Wigner qubitization. - var runJWQubitization = true; - if (runJW) + if (RunJordanWigner) { - for (int i = 0; i < reps; i++) + for (int i = 0; i < NRepetitions; i++) { - var (phaseEst, energyEst) = TrotterEstimateEnergy.Run(qsim, qSharpData, bits, trotterStep).Result; + var (phaseEst, energyEst) = TrotterEstimateEnergy.Run(qsim, qSharpData, NBits, StepSize).Result; logger.LogInformation($"Trotter simulation. phase: {phaseEst}; energy {energyEst}"); } } - if (runJWOptimized) + if (RunOptimizedJordanWigner) { - for (int i = 0; i < reps; i++) + for (int i = 0; i < NRepetitions; i++) { - var (phaseEst, energyEst) = OptimizedTrotterEstimateEnergy.Run(qsim, qSharpData, bits - 1, trotterStep).Result; + var (phaseEst, energyEst) = OptimizedTrotterEstimateEnergy.Run(qsim, qSharpData, NBits - 1, StepSize).Result; logger.LogInformation($"Optimized Trotter simulation. phase {phaseEst}; energy {energyEst}"); } } - if (runJWQubitization) + if (RunQubitizedJordanWigner) { - for (int i = 0; i < reps; i++) + for (int i = 0; i < NRepetitions; i++) { - var (phaseEst, energyEst) = QubitizationEstimateEnergy.Run(qsim, qSharpData, bits - 2).Result; + var (phaseEst, energyEst) = QubitizationEstimateEnergy.Run(qsim, qSharpData, NBits - 2).Result; logger.LogInformation($"Qubitization simulation. phase: {phaseEst}; energy {energyEst}"); } }