/// # Summary /// Runs a specified quantum operation with different parameters `ns`, /// saving the resource estimates as a csv file to a specified location. /// This also runs the operation with a second parameter, which varies /// between specified minimum and maximum values. It only runs over the /// second parameter until it minimizes depth and T count. /// The main purpose is to estimate optimal window sizes for windowed operations. /// /// # Inputs /// ## runner /// The quantum operation being tested (must also match the type `Qop`). /// This operation must take a boolean `isControlled` and an integer parameter /// ## ns /// An array of integer parameters. This method will run the quantum operation /// with each parameter /// ## isControlled /// A boolean argument to pass to the quantum operation. The intention is that /// it tells the operator whether to test a controlled or uncontrolled version. /// ## isAmortized /// Decides how to select the optimal second parameter. If it's amortized, it divides /// the resulting cost by the value of the second parameter. This is intended /// for windowed addition: as the window size increases, we need to do fewer additions. /// ## filename /// The filename, including directory, of where to save the results /// ## full_depth /// If true, counts all gates as depth 1; if false, only counts T-gates as depth 1, /// all others as depth 0 /// ## minParameters /// The minimum value for the second parameter, corresponding to values in ns /// ## maxParameters /// The maximum value for the second parameter. private static void TwoArgResourceTest <TypeQop>( RunTwoArgQop runner, int[] ns, int[][] ms, bool isControlled, string filename, bool full_depth ) { if (full_depth) { filename += "-all-gates"; } if (isControlled) { filename += "-controlled"; } filename += ".csv"; // Create table headers if (!System.IO.File.Exists(filename)) { string estimation = DisplayCSV.GetHeader(full_depth) + ", first arg, second arg"; System.IO.File.WriteAllText(filename, estimation); } ReaderWriterLock locker = new ReaderWriterLock(); for (int i = 0; i < ns.Length; i++) { // Local variables to prevent threading issues var thisThreadProblemSize = ns[i]; var thisTheadSecondParams = ms[i]; // Starts a thread for each value in ns. // Each thread will independently search for an optimal size. Thread oneParameterTest = new Thread(() => SingleTwoArgResourceTest <TypeQop>( runner, locker, thisThreadProblemSize, thisTheadSecondParams, isControlled, filename, full_depth)); oneParameterTest.Start(); } }
private static void SingleTwoArgResourceTest <TypeQop>( RunTwoArgQop runner, ReaderWriterLock locker, int n, int[] ms, bool isControlled, string filename, bool full_depth) { // Iterate through values of the second parameter foreach (int m in ms) { QCTraceSimulator estimator = GetTraceSimulator(full_depth); // construct simulator object // we must generate a new simulator in each round, to clear previous estimates var res = runner(estimator, n, m, isControlled).Result; // run test // Get results var roundDepth = estimator.GetMetric <TypeQop>(MetricsNames.DepthCounter.Depth); var roundTGates = estimator.GetMetric <TypeQop>(PrimitiveOperationsGroupsNames.T); // Create string of a row of parameters string thisCircuitCosts = DisplayCSV.CSV(estimator.ToCSV(), typeof(TypeQop).FullName, false, string.Empty, false, string.Empty); // add the row to the string of the csv thisCircuitCosts += $"{n}, {m}"; try { locker.AcquireWriterLock(int.MaxValue); // absurd timeout value System.IO.File.AppendAllText(filename, thisCircuitCosts); } finally { locker.ReleaseWriterLock(); } } }