private static void SingleResourceTestNoCost <TypeQop>( RunParameterizedQop runner, ReaderWriterLock locker, int n, int m, bool isControlled, string filename, bool full_depth) { 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, isControlled, m).Result; // run test // Get results // 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(); } }
/// # 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(); } }
/// # Summary /// Runs a specified quantum operation with different parameters `ns`, /// saving the resource estimates as a csv file to a specified location. /// /// # 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. /// ## 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 private static void BasicResourceTest <TypeQop>(RunQop runner, int[] ns, bool isControlled, string filename, bool full_depth, bool isThreaded) { if (full_depth) { filename += "-all-gates"; } if (isControlled) { filename += "-controlled"; } filename += ".csv"; string estimation = string.Empty; // Headers for the table if (!System.IO.File.Exists(filename)) { estimation += DisplayCSV.GetHeader(full_depth) + ", size"; System.IO.File.WriteAllText(filename, estimation); } // Run the test for every size ReaderWriterLock locker = new ReaderWriterLock(); for (int i = 0; i < ns.Length; i++) { if (isThreaded) { var thisThreadParameter = ns[i]; Thread oneParameterTest = new Thread(() => SingleResourceTest <TypeQop>( runner, locker, thisThreadParameter, isControlled, filename, full_depth)); oneParameterTest.Start(); } else { // Single thread SingleResourceTest <TypeQop>(runner, locker, ns[i], isControlled, filename, full_depth); } } }
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(); } } }
private static void ParameterizedResourceTestSingleThreaded <TypeQop>( RunParameterizedQop runner, int[] ns, bool isControlled, bool isAmortized, string filename, bool full_depth, int[] minParameters, int[] maxParameters) { if (full_depth) { filename += "-all-gates"; } if (isControlled) { filename += "-controlled"; } filename += ".csv"; // Create table headers if file does not already exist if (!System.IO.File.Exists(filename)) { string estimation = string.Empty; estimation += " operation, CNOT count, 1-qubit Clifford count, T count, R count, M count, "; if (full_depth) { estimation += "Full depth, "; } else { estimation += "T depth, "; } estimation += "initial width, extra width, comment, size, parameter"; System.IO.File.WriteAllText(filename, estimation); } var bestParameter = minParameters[0]; for (int i = 0; i < ns.Length; i++) { // Starts a thread for each value in ns. // Each thread will independently search for an optimal size. var bestCost = 9223372036854775807.0; // Iterate through values of the second parameter for (int j = bestParameter; j < maxParameters[i]; j++) { 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, ns[i], isControlled, j).Result; // run test // Get results var roundCost = 0.0; if (DriverParameters.MinimizeDepthCostMetric) { // depth roundCost = estimator.GetMetric <TypeQop>(MetricsNames.DepthCounter.Depth); } else { roundCost = estimator.GetMetric <TypeQop>(PrimitiveOperationsGroupsNames.T); } // If amortized, we divide out the cost of this round if (isAmortized) { roundCost = roundCost / j; } // 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 += $"{ns[i]}, {j}"; System.IO.File.AppendAllText(filename, thisCircuitCosts); // Breaks if it's reached the minimum in both metrics // Assumes the metrics are convex and increasing in n if (roundCost > bestCost) { break; } else if (roundCost < bestCost) { bestCost = roundCost; bestParameter = j; } } } }
private static void SingleParameterizedResourceTest <TypeQop>( RunParameterizedQop runner, ReaderWriterLock locker, int n, int minParameter, int maxParameter, bool isControlled, string filename, bool full_depth, bool isAmortized) { // Track best cost var bestDepth = 9223372036854775807.0; var bestTGates = 9223372036854775807.0; // Iterate through values of the second parameter for (int j = minParameter; j < maxParameter; j++) { 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, isControlled, j).Result; // run test // Get results var roundDepth = estimator.GetMetric <TypeQop>(MetricsNames.DepthCounter.Depth); var roundTGates = estimator.GetMetric <TypeQop>(PrimitiveOperationsGroupsNames.T); // If amortized, we divide out the cost of this round if (isAmortized) { roundDepth = roundDepth / j; roundTGates = roundTGates / j; } // 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}, {j}"; try { locker.AcquireWriterLock(int.MaxValue); // absurd timeout value System.IO.File.AppendAllText(filename, thisCircuitCosts); } finally { locker.ReleaseWriterLock(); } // Breaks if it's reached the minimum in both metrics // Assumes the metrics are convex if (roundDepth >= bestDepth && roundTGates >= bestTGates) { break; } else { if (roundDepth < bestDepth) { bestDepth = roundDepth; } if (roundTGates < bestTGates) { bestTGates = roundTGates; } } } }