qsharp-lang 1.0.24-dev → 1.0.25-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { TargetProfile } from "../lib/web/qsc_wasm.js";
1
2
  import { ICompiler, ICompilerWorker } from "./compiler/compiler.js";
2
3
  import { IDebugService, IDebugServiceWorker } from "./debug-service/debug-service.js";
3
4
  import { ILanguageService, ILanguageServiceWorker, qsharpLibraryUriScheme } from "./language-service/language-service.js";
@@ -17,7 +18,7 @@ export { QscEventTarget } from "./compiler/events.js";
17
18
  export { getAllKatas, getExerciseSources, getKata, type ContentItem, type Example, type Exercise, type ExplainedSolution, type ExplainedSolutionItem, type Kata, type KataSection, type Lesson, type LessonItem, type Question, } from "./katas.js";
18
19
  export { default as samples } from "./samples.generated.js";
19
20
  export { type VSDiagnostic } from "./vsdiagnostic.js";
20
- export { log, type LogLevel };
21
+ export { log, type LogLevel, type TargetProfile };
21
22
  export type { ICompilerWorker, ICompiler };
22
23
  export type { ILanguageServiceWorker, ILanguageService };
23
24
  export type { IDebugServiceWorker, IDebugService };
@@ -1,9 +1,10 @@
1
1
  import type { IBreakpointSpan, IStackFrame, IStructStepResult, IVariable, IQuantumState } from "../../lib/node/qsc_wasm.cjs";
2
+ import { TargetProfile } from "../browser.js";
2
3
  import { IQscEventTarget } from "../compiler/events.js";
3
4
  import { IServiceProxy } from "../worker-proxy.js";
4
5
  type QscWasm = typeof import("../../lib/node/qsc_wasm.cjs");
5
6
  export interface IDebugService {
6
- loadSource(path: string, source: string, target: "base" | "full", entry: string | undefined): Promise<string>;
7
+ loadSource(path: string, source: string, target: TargetProfile, entry: string | undefined): Promise<string>;
7
8
  getBreakpoints(path: string): Promise<IBreakpointSpan[]>;
8
9
  getLocalVariables(): Promise<Array<IVariable>>;
9
10
  captureQuantumState(): Promise<Array<IQuantumState>>;
@@ -20,7 +21,7 @@ export declare class QSharpDebugService implements IDebugService {
20
21
  private debugService;
21
22
  private code;
22
23
  constructor(wasm: QscWasm);
23
- loadSource(path: string, source: string, target: "base" | "full", entry: string | undefined): Promise<string>;
24
+ loadSource(path: string, source: string, target: TargetProfile, entry: string | undefined): Promise<string>;
24
25
  getStackFrames(): Promise<IStackFrame[]>;
25
26
  evalNext(bps: number[], eventHandler: IQscEventTarget): Promise<IStructStepResult>;
26
27
  evalStepIn(bps: number[], eventHandler: IQscEventTarget): Promise<IStructStepResult>;
@@ -1385,7 +1385,7 @@ export default {
1385
1385
  {
1386
1386
  "type": "example",
1387
1387
  "id": "multi_qubit_measurements__measuring_one_at_a_time",
1388
- "code": "namespace Kata {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Arithmetic;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Math;\n\n @EntryPoint()\n operation DemoBasisMeasurement() : Unit {\n let numRuns = 1000;\n\n // Define coefficients and obtain measurement probabilities for the\n // state |psi❭ = 0.33 |00❭ + 0.67 |01❭ + 0.67 |11❭\n // Use little endian format to encode basis states as integer indices.\n let coefficients = [0.333, 0.0, 0.667, 0.667];\n let expected_probabilities = [0.111, 0.0, 0.445, 0.445];\n\n // Set up counter array for measurements.\n mutable countArray = [0, 0, 0, 0];\n\n use qs = Qubit[2];\n for i in 1 .. numRuns {\n // Prepare the state from Exercise 1:\n PrepareEx1State(qs);\n if i == 1 {\n Message(\"The state |psi❭ of the system before measurement is:\");\n DumpMachine();\n }\n\n // Measure the first qubit, followed by the second qubit, and\n // convert the result to little endian integer\n let result = MeasureInteger(qs);\n\n // Update countArray\n set countArray w/= result <- countArray[result] + 1;\n }\n\n // Obtain simulated probability of measurement for each outcome\n mutable simulated_probabilities = [];\n for i in 0 .. 3 {\n set simulated_probabilities +=\n [IntAsDouble(countArray[i]) / IntAsDouble(numRuns)];\n }\n\n Message($\"Theoretical measurement probabilities are {expected_probabilities}\");\n Message($\"Simulated measurement probabilities are {simulated_probabilities}\");\n }\n\n operation PrepareEx1State(q : Qubit[]) : Unit {\n Ry(-ArcCos(1.0/9.0), q[0]);\n within {\n S(q[1]);\n H(q[1]);\n } apply {\n Rz(ArcTan(0.5), q[1]);\n CNOT(q[0], q[1]);\n Rz(ArcTan(0.5)-PI(), q[1]);\n CNOT(q[0], q[1]);\n }\n }\n}\n"
1388
+ "code": "namespace Kata {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Measurement;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Math;\n\n @EntryPoint()\n operation DemoBasisMeasurement() : Unit {\n let numRuns = 1000;\n\n // Define coefficients and obtain measurement probabilities for the\n // state |psi❭ = 0.33 |00❭ + 0.67 |01❭ + 0.67 |11❭\n // Use little endian format to encode basis states as integer indices.\n let coefficients = [0.333, 0.0, 0.667, 0.667];\n let expected_probabilities = [0.111, 0.0, 0.445, 0.445];\n\n // Set up counter array for measurements.\n mutable countArray = [0, 0, 0, 0];\n\n use qs = Qubit[2];\n for i in 1 .. numRuns {\n // Prepare the state from Exercise 1:\n PrepareEx1State(qs);\n if i == 1 {\n Message(\"The state |psi❭ of the system before measurement is:\");\n DumpMachine();\n }\n\n // Measure the first qubit, followed by the second qubit, and\n // convert the result to little endian integer\n let result = MeasureInteger(qs);\n\n // Update countArray\n set countArray w/= result <- countArray[result] + 1;\n }\n\n // Obtain simulated probability of measurement for each outcome\n mutable simulated_probabilities = [];\n for i in 0 .. 3 {\n set simulated_probabilities +=\n [IntAsDouble(countArray[i]) / IntAsDouble(numRuns)];\n }\n\n Message($\"Theoretical measurement probabilities are {expected_probabilities}\");\n Message($\"Simulated measurement probabilities are {simulated_probabilities}\");\n }\n\n operation PrepareEx1State(q : Qubit[]) : Unit {\n Ry(-ArcCos(1.0/9.0), q[0]);\n within {\n S(q[1]);\n H(q[1]);\n } apply {\n Rz(ArcTan(0.5), q[1]);\n CNOT(q[0], q[1]);\n Rz(ArcTan(0.5)-PI(), q[1]);\n CNOT(q[0], q[1]);\n }\n }\n}\n"
1389
1389
  },
1390
1390
  {
1391
1391
  "type": "text-content",
@@ -1460,7 +1460,7 @@ export default {
1460
1460
  {
1461
1461
  "type": "example",
1462
1462
  "id": "multi_qubit_measurements__partial_measurements_demo",
1463
- "code": "namespace Kata {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Arithmetic;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Math;\n\n @EntryPoint()\n operation DemoPartialMeasurement() : Unit {\n let numRuns = 1000;\n let divider = \"--------------------------------------------------------------------------------------------------\";\n //\n // We can use coefficients without normalization in PrepareArbitraryStateD,\n // the operation will normalize them automatically.\n let coefficients = [3., 1., 1., 1.];\n let expected_probabilities = [0.833, 0.167];\n\n // Set up the counter array for measurements.\n mutable countArray = [0, 0];\n\n use qs = Qubit[2];\n for i in 1 .. numRuns {\n // Prepare the state from Exercise 4:\n // |𝜓❭ = (1/√12)(3|00⟩+|01⟩+|10⟩+|11⟩)\n PrepareHardyState(qs);\n\n // Display the state of the qubits.\n if i == 1 {\n Message(\"The state |𝜓❭ of the system before measurement is:\");\n DumpMachine();\n Message(divider);\n }\n\n // Measure the first qubit.\n let outcome = M(qs[0]) == Zero ? 0 | 1;\n set countArray w/= outcome <- countArray[outcome] + 1;\n\n if countArray[outcome] == 1 {\n // The first time the outcome is 0/1, print the system state afterwards.\n Message(\"For outcome {outcome}, the post-measurement state of the system is:\");\n DumpMachine();\n }\n ResetAll(qs);\n }\n\n // Obtain simulated probability of measurement for each outcome\n mutable simulated_probabilities = [];\n for i in 0 .. 1 {\n set simulated_probabilities += [IntAsDouble(countArray[i]) / IntAsDouble(numRuns)];\n }\n\n Message($\"Theoretical measurement probabilities are {expected_probabilities}\");\n Message($\"Simulated measurement probabilities are {simulated_probabilities}\");\n }\n\n operation PrepareHardyState(q : Qubit[]) : Unit {\n Ry(ArcCos(2.0/3.0), q[1]);\n within {\n S(q[0]);\n H(q[0]);\n } apply {\n CNOT(q[1], q[0]);\n Rz(ArcTan(1.0/2.0), q[0]);\n CNOT(q[1], q[0]);\n Rz(-ArcTan(2.0), q[0]);\n }\n }\n\n}\n"
1463
+ "code": "namespace Kata {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Math;\n\n @EntryPoint()\n operation DemoPartialMeasurement() : Unit {\n let numRuns = 1000;\n let divider = \"--------------------------------------------------------------------------------------------------\";\n //\n // We can use coefficients without normalization in PrepareArbitraryStateD,\n // the operation will normalize them automatically.\n let coefficients = [3., 1., 1., 1.];\n let expected_probabilities = [0.833, 0.167];\n\n // Set up the counter array for measurements.\n mutable countArray = [0, 0];\n\n use qs = Qubit[2];\n for i in 1 .. numRuns {\n // Prepare the state from Exercise 4:\n // |𝜓❭ = (1/√12)(3|00⟩+|01⟩+|10⟩+|11⟩)\n PrepareHardyState(qs);\n\n // Display the state of the qubits.\n if i == 1 {\n Message(\"The state |𝜓❭ of the system before measurement is:\");\n DumpMachine();\n Message(divider);\n }\n\n // Measure the first qubit.\n let outcome = M(qs[0]) == Zero ? 0 | 1;\n set countArray w/= outcome <- countArray[outcome] + 1;\n\n if countArray[outcome] == 1 {\n // The first time the outcome is 0/1, print the system state afterwards.\n Message(\"For outcome {outcome}, the post-measurement state of the system is:\");\n DumpMachine();\n }\n ResetAll(qs);\n }\n\n // Obtain simulated probability of measurement for each outcome\n mutable simulated_probabilities = [];\n for i in 0 .. 1 {\n set simulated_probabilities += [IntAsDouble(countArray[i]) / IntAsDouble(numRuns)];\n }\n\n Message($\"Theoretical measurement probabilities are {expected_probabilities}\");\n Message($\"Simulated measurement probabilities are {simulated_probabilities}\");\n }\n\n operation PrepareHardyState(q : Qubit[]) : Unit {\n Ry(ArcCos(2.0/3.0), q[1]);\n within {\n S(q[0]);\n H(q[0]);\n } apply {\n CNOT(q[1], q[0]);\n Rz(ArcTan(1.0/2.0), q[0]);\n CNOT(q[1], q[0]);\n Rz(-ArcTan(2.0), q[0]);\n }\n }\n\n}\n"
1464
1464
  },
1465
1465
  {
1466
1466
  "type": "text-content",
@@ -1,4 +1,4 @@
1
- import type { ICompletionList, IHover, ILocation, ISignatureHelp, IWorkspaceConfiguration, IWorkspaceEdit, ITextEdit } from "../../lib/node/qsc_wasm.cjs";
1
+ import type { ICompletionList, IHover, ILocation, ISignatureHelp, INotebookMetadata, IWorkspaceConfiguration, IWorkspaceEdit, ITextEdit } from "../../lib/node/qsc_wasm.cjs";
2
2
  import { VSDiagnostic } from "../vsdiagnostic.js";
3
3
  import { IServiceProxy } from "../worker-proxy.js";
4
4
  type QscWasm = typeof import("../../lib/node/qsc_wasm.cjs");
@@ -13,7 +13,7 @@ export type LanguageServiceEvent = {
13
13
  export interface ILanguageService {
14
14
  updateConfiguration(config: IWorkspaceConfiguration): Promise<void>;
15
15
  updateDocument(uri: string, version: number, code: string): Promise<void>;
16
- updateNotebookDocument(notebookUri: string, version: number, cells: {
16
+ updateNotebookDocument(notebookUri: string, version: number, metadata: INotebookMetadata, cells: {
17
17
  uri: string;
18
18
  version: number;
19
19
  code: string;
@@ -44,7 +44,7 @@ export declare class QSharpLanguageService implements ILanguageService {
44
44
  constructor(wasm: QscWasm);
45
45
  updateConfiguration(config: IWorkspaceConfiguration): Promise<void>;
46
46
  updateDocument(documentUri: string, version: number, code: string): Promise<void>;
47
- updateNotebookDocument(notebookUri: string, version: number, cells: {
47
+ updateNotebookDocument(notebookUri: string, version: number, metadata: INotebookMetadata, cells: {
48
48
  uri: string;
49
49
  version: number;
50
50
  code: string;
@@ -19,14 +19,14 @@ export class QSharpLanguageService {
19
19
  this.code[documentUri] = code;
20
20
  this.languageService.update_document(documentUri, version, code);
21
21
  }
22
- async updateNotebookDocument(notebookUri, version, cells) {
22
+ async updateNotebookDocument(notebookUri, version, metadata, cells) {
23
23
  // Note: If a cell was deleted, its uri & contents will remain in the map.
24
24
  // This is harmless and it keeps the code simpler to just leave it this way
25
25
  // instead of trying to maintain a perfect map.
26
26
  for (const cell of cells) {
27
27
  this.code[cell.uri] = cell.code;
28
28
  }
29
- this.languageService.update_notebook_document(notebookUri, cells);
29
+ this.languageService.update_notebook_document(notebookUri, metadata, cells);
30
30
  }
31
31
  async closeDocument(documentUri) {
32
32
  delete this.code[documentUri];
@@ -47,7 +47,7 @@ export default [
47
47
  {
48
48
  "title": "Deutsch-Jozsa (Advanced)",
49
49
  "shots": 1,
50
- "code": "/// # Sample\n/// Deutsch–Jozsa algorithm\n///\n/// # Description\n/// Deutsch–Jozsa is a quantum algorithm that determines whether a given Boolean\n/// function 𝑓 is constant (0 on all inputs or 1 on all inputs) or balanced\n/// (1 for exactly half of the input domain and 0 for the other half).\n///\n/// This Q# program implements the Deutsch–Jozsa algorithm.\nnamespace Sample {\n open Microsoft.Quantum.Canon;\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Math;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : (String, Bool)[] {\n // A Boolean function is a function that maps bitstrings to a bit:\n // 𝑓 : {0, 1}^n → {0, 1}.\n\n // We say that 𝑓 is constant if 𝑓(𝑥⃗) = 𝑓(𝑦⃗) for all bitstrings 𝑥⃗ and\n // 𝑦⃗, and that 𝑓 is balanced if 𝑓 evaluates to true for exactly half of\n // its inputs.\n\n // If we are given a function 𝑓 as a quantum operation 𝑈 |𝑥〉|𝑦〉 =\n // |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉, and are promised that 𝑓 is either constant or is\n // balanced, then the Deutsch–Jozsa algorithm decides between these\n // cases with a single application of 𝑈.\n\n // Here, we demonstrate the use of the Deutsch-Jozsa algorithm by\n // determining the type (constant or balanced) of various functions.\n let nameFunctionTypeTuples = [\n (\"SimpleConstantBoolF\", SimpleConstantBoolF, true),\n (\"SimpleBalancedBoolF\", SimpleBalancedBoolF, false),\n (\"ConstantBoolF\", ConstantBoolF, true),\n (\"BalancedBoolF\", BalancedBoolF, false)\n ];\n\n mutable results = [];\n for (name, fn, shouldBeConstant) in nameFunctionTypeTuples {\n let isConstant = DeutschJozsa(fn, 5);\n if (isConstant != shouldBeConstant) {\n let shouldBeConstantStr = shouldBeConstant ?\n \"constant\" | \n \"balanced\";\n fail $\"{name} should be detected as {shouldBeConstantStr}\";\n }\n\n let isConstantStr = isConstant ? \"constant\" | \"balanced\";\n Message($\"{name} is {isConstantStr}\");\n set results += [(name, isConstant)];\n }\n\n return results;\n }\n\n /// # Summary\n /// This operation implements the DeutschJozsa algorithm.\n /// It returns the Boolean value `true` if the function is constant and\n /// `false` if it is not.\n /// It is assumed that the function is either constant or balanced.\n ///\n /// # Input\n /// ## Uf\n /// A quantum operation that implements |𝑥〉|𝑦〉 ↦ |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉, where 𝑓 is a\n /// Boolean function, 𝑥 is an 𝑛 bit register and 𝑦 is a single qubit.\n /// ## n\n /// The number of bits in the input register |𝑥〉.\n ///\n /// # Output\n /// A boolean value `true` that indicates that the function is constant and\n /// `false` that indicates that the function is balanced.\n ///\n /// # See Also\n /// - For details see Section 1.4.3 of Nielsen & Chuang.\n ///\n /// # References\n /// - [ *Michael A. Nielsen , Isaac L. Chuang*,\n /// Quantum Computation and Quantum Information ]\n /// (http://doi.org/10.1017/CBO9780511976667)\n operation DeutschJozsa(Uf : ((Qubit[], Qubit) => Unit), n : Int) : Bool {\n // We allocate n + 1 clean qubits. Note that the function `Uf` is defined\n // on inputs of the form (x, y), where x has n bits and y has 1 bit.\n use queryRegister = Qubit[n];\n use target = Qubit();\n\n // The last qubit needs to be flipped so that the function will actually\n // be computed into the phase when Uf is applied.\n X(target);\n\n // Now, a Hadamard transform is applied to each of the qubits.\n H(target);\n // We use a within-apply block to ensure that the Hadamard transform is\n // correctly inverted on the |𝑥〉 register.\n within {\n for q in queryRegister {\n H(q);\n }\n } apply {\n // We apply Uf to the n+1 qubits, computing |𝑥, 𝑦〉 ↦ |𝑥, 𝑦 ⊕ 𝑓(𝑥)〉.\n Uf(queryRegister, target);\n }\n\n // The following for-loop measures all qubits and resets them to the |0〉\n // state so that they can be safely deallocated at the end of the block.\n // The loop also sets `result` to `true` if all measurement results are\n // `Zero`, i.e. if the function is a constant function, and sets\n // `result` to `false` if not, which according to the assumption on 𝑓 \n // means that it must be balanced.\n mutable result = true;\n for q in queryRegister {\n if MResetZ(q) == One {\n set result = false;\n }\n }\n\n // Finally, the last qubit, which held the 𝑦-register, is reset.\n Reset(target);\n return result;\n }\n\n // Simple constant Boolean function\n operation SimpleConstantBoolF(args : Qubit[], target : Qubit) : Unit {\n X(target);\n }\n\n // Simple balanced Boolean function\n operation SimpleBalancedBoolF(args : Qubit[], target : Qubit) : Unit {\n CX(args[0], target);\n }\n\n // A more complex constant Boolean function.\n // It applies X to every input basis vector.\n operation ConstantBoolF(args : Qubit[], target : Qubit) : Unit {\n for i in 0..(2^Length(args))-1 {\n ApplyControlledOnInt(i, X, args, target);\n }\n }\n\n // A more complex balanced Boolean function.\n // It applies X to half of the input basis vectors.\n operation BalancedBoolF(args : Qubit[], target : Qubit) : Unit {\n for i in 0..2..(2^Length(args))-1 {\n ApplyControlledOnInt(i, X, args, target);\n }\n }\n}\n"
50
+ "code": "/// # Sample\n/// Deutsch–Jozsa algorithm\n///\n/// # Description\n/// Deutsch–Jozsa is a quantum algorithm that determines whether a given Boolean\n/// function 𝑓 is constant (0 on all inputs or 1 on all inputs) or balanced\n/// (1 for exactly half of the input domain and 0 for the other half).\n///\n/// This Q# program implements the Deutsch–Jozsa algorithm.\nnamespace Sample {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Math;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : (String, Bool)[] {\n // A Boolean function is a function that maps bitstrings to a bit:\n // 𝑓 : {0, 1}^n → {0, 1}.\n\n // We say that 𝑓 is constant if 𝑓(𝑥⃗) = 𝑓(𝑦⃗) for all bitstrings 𝑥⃗ and\n // 𝑦⃗, and that 𝑓 is balanced if 𝑓 evaluates to true for exactly half of\n // its inputs.\n\n // If we are given a function 𝑓 as a quantum operation 𝑈 |𝑥〉|𝑦〉 =\n // |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉, and are promised that 𝑓 is either constant or is\n // balanced, then the Deutsch–Jozsa algorithm decides between these\n // cases with a single application of 𝑈.\n\n // Here, we demonstrate the use of the Deutsch-Jozsa algorithm by\n // determining the type (constant or balanced) of various functions.\n let nameFunctionTypeTuples = [\n (\"SimpleConstantBoolF\", SimpleConstantBoolF, true),\n (\"SimpleBalancedBoolF\", SimpleBalancedBoolF, false),\n (\"ConstantBoolF\", ConstantBoolF, true),\n (\"BalancedBoolF\", BalancedBoolF, false)\n ];\n\n mutable results = [];\n for (name, fn, shouldBeConstant) in nameFunctionTypeTuples {\n let isConstant = DeutschJozsa(fn, 5);\n if (isConstant != shouldBeConstant) {\n let shouldBeConstantStr = shouldBeConstant ?\n \"constant\" | \n \"balanced\";\n fail $\"{name} should be detected as {shouldBeConstantStr}\";\n }\n\n let isConstantStr = isConstant ? \"constant\" | \"balanced\";\n Message($\"{name} is {isConstantStr}\");\n set results += [(name, isConstant)];\n }\n\n return results;\n }\n\n /// # Summary\n /// This operation implements the DeutschJozsa algorithm.\n /// It returns the Boolean value `true` if the function is constant and\n /// `false` if it is not.\n /// It is assumed that the function is either constant or balanced.\n ///\n /// # Input\n /// ## Uf\n /// A quantum operation that implements |𝑥〉|𝑦〉 ↦ |𝑥〉|𝑦 ⊕ 𝑓(𝑥)〉, where 𝑓 is a\n /// Boolean function, 𝑥 is an 𝑛 bit register and 𝑦 is a single qubit.\n /// ## n\n /// The number of bits in the input register |𝑥〉.\n ///\n /// # Output\n /// A boolean value `true` that indicates that the function is constant and\n /// `false` that indicates that the function is balanced.\n ///\n /// # See Also\n /// - For details see Section 1.4.3 of Nielsen & Chuang.\n ///\n /// # References\n /// - [ *Michael A. Nielsen , Isaac L. Chuang*,\n /// Quantum Computation and Quantum Information ]\n /// (http://doi.org/10.1017/CBO9780511976667)\n operation DeutschJozsa(Uf : ((Qubit[], Qubit) => Unit), n : Int) : Bool {\n // We allocate n + 1 clean qubits. Note that the function `Uf` is defined\n // on inputs of the form (x, y), where x has n bits and y has 1 bit.\n use queryRegister = Qubit[n];\n use target = Qubit();\n\n // The last qubit needs to be flipped so that the function will actually\n // be computed into the phase when Uf is applied.\n X(target);\n\n // Now, a Hadamard transform is applied to each of the qubits.\n H(target);\n // We use a within-apply block to ensure that the Hadamard transform is\n // correctly inverted on the |𝑥〉 register.\n within {\n for q in queryRegister {\n H(q);\n }\n } apply {\n // We apply Uf to the n+1 qubits, computing |𝑥, 𝑦〉 ↦ |𝑥, 𝑦 ⊕ 𝑓(𝑥)〉.\n Uf(queryRegister, target);\n }\n\n // The following for-loop measures all qubits and resets them to the |0〉\n // state so that they can be safely deallocated at the end of the block.\n // The loop also sets `result` to `true` if all measurement results are\n // `Zero`, i.e. if the function is a constant function, and sets\n // `result` to `false` if not, which according to the assumption on 𝑓 \n // means that it must be balanced.\n mutable result = true;\n for q in queryRegister {\n if MResetZ(q) == One {\n set result = false;\n }\n }\n\n // Finally, the last qubit, which held the 𝑦-register, is reset.\n Reset(target);\n return result;\n }\n\n // Simple constant Boolean function\n operation SimpleConstantBoolF(args : Qubit[], target : Qubit) : Unit {\n X(target);\n }\n\n // Simple balanced Boolean function\n operation SimpleBalancedBoolF(args : Qubit[], target : Qubit) : Unit {\n CX(args[0], target);\n }\n\n // A more complex constant Boolean function.\n // It applies X to every input basis vector.\n operation ConstantBoolF(args : Qubit[], target : Qubit) : Unit {\n for i in 0..(2^Length(args))-1 {\n ApplyControlledOnInt(i, X, args, target);\n }\n }\n\n // A more complex balanced Boolean function.\n // It applies X to half of the input basis vectors.\n operation BalancedBoolF(args : Qubit[], target : Qubit) : Unit {\n for i in 0..2..(2^Length(args))-1 {\n ApplyControlledOnInt(i, X, args, target);\n }\n }\n}\n"
51
51
  },
52
52
  {
53
53
  "title": "Bernstein–Vazirani",
@@ -67,16 +67,16 @@ export default [
67
67
  {
68
68
  "title": "Hidden Shift",
69
69
  "shots": 1,
70
- "code": "/// # Sample\n/// Hidden shift\n///\n/// # Description\n/// There is a family of problems known as hidden shift problems, in which it\n/// is given that two Boolean functions 𝑓 and 𝑔 satisfy the relation\n/// 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥\n/// where 𝑠 is a hidden bit string that we would like to find.\n///\n/// This Q# program implements an algorithm to solve the hidden shift problem.\nnamespace Sample {\n open Microsoft.Quantum.Arithmetic;\n open Microsoft.Quantum.Arrays;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : Result[] {\n // Consider the case of finding a hidden shift 𝑠 between two Boolean\n // functions 𝑓(𝑥) and 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n // This problem can be solved on a quantum computer with one call to\n // each of 𝑓 and 𝑔 in the special case that both functions are bent;\n // that is, that they are as far from linear as possible.\n\n // Here, we find the hidden shift encoded in the following array of\n // Booleans.\n let shiftAsBoolArray = [true, false, false, false, false, true];\n let shiftAsInt = BoolArrayAsInt(shiftAsBoolArray);\n let hiddenShiftBitString = FindHiddenShift(\n BentFunction,\n register => ShiftedBentFunction(shiftAsInt, register),\n Length(shiftAsBoolArray));\n\n return hiddenShiftBitString;\n }\n\n /// # Summary\n /// Implements a correlation-based algorithm to solve the hidden shift\n /// problem for bent functions.\n ///\n /// # Description\n /// Implements a solution for the hidden shift problem, which is to identify\n /// an unknown shift 𝑠 of the arguments of two Boolean functions 𝑓 and 𝑔\n /// that are promised to satisfy the relation 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥.\n ///\n /// 𝑓 and 𝑔 are assumed to be bent functions. A Boolean function is bent if\n /// it is as far from linear as possible. In particular, bent functions have\n /// flat Fourier (Walsh–Hadamard) spectra.\n ///\n /// In this case, the Roetteler algorithm (see References, below) uses\n /// black-box oracles for 𝑓^* and 𝑔, where 𝑓^* is the dual bent function to\n /// 𝑓, and computes the hidden shift 𝑠 between 𝑓 and 𝑔.\n ///\n /// # Input\n /// ## Ufstar\n /// A quantum operation that implements\n /// $U_f^*: |𝑥〉 ↦ (-1)^{f^*(x)} |𝑥〉$,\n /// where $f^*$ is a Boolean function, 𝑥 is an $n$ bit register\n /// ## Ug\n /// A quantum operation that implements\n /// $U_g:|𝑥〉 ↦ (-1)^{g(x)} |𝑥〉$,\n /// where 𝑔 is a Boolean function that is shifted by unknown\n /// 𝑠 from 𝑓, and 𝑥 is an $n$ bit register.\n /// ## n\n /// The number of bits of the input register |𝑥〉.\n ///\n /// # Output\n /// An array of type `Result[]` which encodes the bit representation\n /// of the hidden shift.\n ///\n /// # References\n /// - [*Martin Roetteler*,\n /// Proc. SODA 2010, ACM, pp. 448-457, 2010]\n /// (https://doi.org/10.1137/1.9781611973075.37)\n operation FindHiddenShift (\n Ufstar : (Qubit[] => Unit),\n Ug : (Qubit[] => Unit),\n n : Int)\n : Result[] {\n // We allocate n clean qubits. Note that the function Ufstar and Ug are\n // unitary operations on n qubits defined via phase encoding.\n use qubits = Qubit[n];\n\n // First, a Hadamard transform is applied to each of the qubits.\n ApplyToEach(H, qubits);\n\n // We now apply the shifted function Ug to the n qubits, computing\n // |x〉 -> (-1)^{g(x)} |x〉.\n Ug(qubits);\n\n within {\n // A Hadamard transform is applied to each of the n qubits.\n ApplyToEachA(H, qubits);\n } apply {\n // we now apply the dual function of the unshifted function, i.e.,\n // Ufstar, to the n qubits, computing |x〉 -> (-1)^{fstar(x)} |x〉.\n Ufstar(qubits);\n }\n\n // Measure the n qubits and reset them to zero so that they can be\n // safely deallocated at the end of the block.\n return ForEach(MResetZ, qubits);\n }\n\n /// # Summary\n /// Implements an oracle for a bent function constructed from the inner\n /// product of Boolean functions.\n ///\n /// # Description\n /// This operation defines the Boolean function IP(x_0, ..., x_{n-1}) which\n /// is computed into the phase, i.e., a diagonal operator that maps\n /// |x〉 -> (-1)^{IP(x)} |x〉, where x stands for x=(x_0, ..., x_{n-1}) and all\n /// the x_i are binary. The IP function is defined as\n /// IP(y, z) = y_0 z_0 + y_1 z_1 + ... y_{u-1} z_{u-1} where\n /// y = (y_0, ..., y_{u-1}) and z = (z_0, ..., z_{u-1}) are two bit vectors\n /// of length u. Notice that the function IP is a Boolean function on n = 2u\n /// bits. IP is a special case of bent function. These are functions for\n /// which the Walsh-Hadamard transform is perfectly flat (in absolute\n /// value).\n /// Because of this flatness, the Walsh-Hadamard spectrum of any bent\n /// function defines a +1/-1 function, i.e., gives rise to another Boolean\n /// function, called the dual bent function. Moreover, for the case of the\n /// IP function it can be shown that IP is equal to its own dual bent\n /// function.\n ///\n /// # Remarks\n /// Notice that a diagonal operator implementing IP between 2 variables y_0\n /// and z_0 is nothing but the AND function between those variables, i.e.,\n /// in phase encoding it is computed by a Controlled-Z gate.\n /// Extending this to an XOR of the AND of more variables, as required in\n /// the definition of the IP function can then be accomplished by applying\n /// several Controlled-Z gates between the respective inputs.\n operation BentFunction(register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n let xs = register[0 .. u - 1];\n let ys = register[u...];\n for index in 0..u-1 {\n CZ(xs[index], ys[index]);\n }\n }\n\n /// # Summary\n /// Implements a shifted bend function 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n ///\n /// # Description\n /// For the hidden shift problem we need another function g which is related\n /// to IP via g(x) = IP(x + s), i.e., we have to shift the argument of the\n /// IP function by a given shift. Notice that the '+' operation here is the\n /// Boolean addition, i.e., a bit-wise operation. Notice further, that in\n /// general a diagonal operation |x〉 -> (-1)^{f(x)} can be turned into a\n /// shifted version by applying a bit flip to the |x〉 register first, then\n /// applying the diagonal operation, and then undoing the bit flips to the\n /// |x〉 register. We use this principle to define shifted versions of the IP\n /// operation.\n operation ShiftedBentFunction(shift : Int, register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n within {\n // Flips the bits in shift.\n ApplyXorInPlace(shift, register);\n } apply {\n // Compute the IP function into the phase.\n BentFunction(register);\n }\n }\n}\n"
70
+ "code": "/// # Sample\n/// Hidden shift\n///\n/// # Description\n/// There is a family of problems known as hidden shift problems, in which it\n/// is given that two Boolean functions 𝑓 and 𝑔 satisfy the relation\n/// 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥\n/// where 𝑠 is a hidden bit string that we would like to find.\n///\n/// This Q# program implements an algorithm to solve the hidden shift problem.\nnamespace Sample {\n open Microsoft.Quantum.Arrays;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : Result[] {\n // Consider the case of finding a hidden shift 𝑠 between two Boolean\n // functions 𝑓(𝑥) and 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n // This problem can be solved on a quantum computer with one call to\n // each of 𝑓 and 𝑔 in the special case that both functions are bent;\n // that is, that they are as far from linear as possible.\n\n // Here, we find the hidden shift encoded in the following array of\n // Booleans.\n let shiftAsBoolArray = [true, false, false, false, false, true];\n let shiftAsInt = BoolArrayAsInt(shiftAsBoolArray);\n let hiddenShiftBitString = FindHiddenShift(\n BentFunction,\n register => ShiftedBentFunction(shiftAsInt, register),\n Length(shiftAsBoolArray));\n\n return hiddenShiftBitString;\n }\n\n /// # Summary\n /// Implements a correlation-based algorithm to solve the hidden shift\n /// problem for bent functions.\n ///\n /// # Description\n /// Implements a solution for the hidden shift problem, which is to identify\n /// an unknown shift 𝑠 of the arguments of two Boolean functions 𝑓 and 𝑔\n /// that are promised to satisfy the relation 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥.\n ///\n /// 𝑓 and 𝑔 are assumed to be bent functions. A Boolean function is bent if\n /// it is as far from linear as possible. In particular, bent functions have\n /// flat Fourier (Walsh–Hadamard) spectra.\n ///\n /// In this case, the Roetteler algorithm (see References, below) uses\n /// black-box oracles for 𝑓^* and 𝑔, where 𝑓^* is the dual bent function to\n /// 𝑓, and computes the hidden shift 𝑠 between 𝑓 and 𝑔.\n ///\n /// # Input\n /// ## Ufstar\n /// A quantum operation that implements\n /// $U_f^*: |𝑥〉 ↦ (-1)^{f^*(x)} |𝑥〉$,\n /// where $f^*$ is a Boolean function, 𝑥 is an $n$ bit register\n /// ## Ug\n /// A quantum operation that implements\n /// $U_g:|𝑥〉 ↦ (-1)^{g(x)} |𝑥〉$,\n /// where 𝑔 is a Boolean function that is shifted by unknown\n /// 𝑠 from 𝑓, and 𝑥 is an $n$ bit register.\n /// ## n\n /// The number of bits of the input register |𝑥〉.\n ///\n /// # Output\n /// An array of type `Result[]` which encodes the bit representation\n /// of the hidden shift.\n ///\n /// # References\n /// - [*Martin Roetteler*,\n /// Proc. SODA 2010, ACM, pp. 448-457, 2010]\n /// (https://doi.org/10.1137/1.9781611973075.37)\n operation FindHiddenShift (\n Ufstar : (Qubit[] => Unit),\n Ug : (Qubit[] => Unit),\n n : Int)\n : Result[] {\n // We allocate n clean qubits. Note that the function Ufstar and Ug are\n // unitary operations on n qubits defined via phase encoding.\n use qubits = Qubit[n];\n\n // First, a Hadamard transform is applied to each of the qubits.\n ApplyToEach(H, qubits);\n\n // We now apply the shifted function Ug to the n qubits, computing\n // |x〉 -> (-1)^{g(x)} |x〉.\n Ug(qubits);\n\n within {\n // A Hadamard transform is applied to each of the n qubits.\n ApplyToEachA(H, qubits);\n } apply {\n // we now apply the dual function of the unshifted function, i.e.,\n // Ufstar, to the n qubits, computing |x〉 -> (-1)^{fstar(x)} |x〉.\n Ufstar(qubits);\n }\n\n // Measure the n qubits and reset them to zero so that they can be\n // safely deallocated at the end of the block.\n return ForEach(MResetZ, qubits);\n }\n\n /// # Summary\n /// Implements an oracle for a bent function constructed from the inner\n /// product of Boolean functions.\n ///\n /// # Description\n /// This operation defines the Boolean function IP(x_0, ..., x_{n-1}) which\n /// is computed into the phase, i.e., a diagonal operator that maps\n /// |x〉 -> (-1)^{IP(x)} |x〉, where x stands for x=(x_0, ..., x_{n-1}) and all\n /// the x_i are binary. The IP function is defined as\n /// IP(y, z) = y_0 z_0 + y_1 z_1 + ... y_{u-1} z_{u-1} where\n /// y = (y_0, ..., y_{u-1}) and z = (z_0, ..., z_{u-1}) are two bit vectors\n /// of length u. Notice that the function IP is a Boolean function on n = 2u\n /// bits. IP is a special case of bent function. These are functions for\n /// which the Walsh-Hadamard transform is perfectly flat (in absolute\n /// value).\n /// Because of this flatness, the Walsh-Hadamard spectrum of any bent\n /// function defines a +1/-1 function, i.e., gives rise to another Boolean\n /// function, called the dual bent function. Moreover, for the case of the\n /// IP function it can be shown that IP is equal to its own dual bent\n /// function.\n ///\n /// # Remarks\n /// Notice that a diagonal operator implementing IP between 2 variables y_0\n /// and z_0 is nothing but the AND function between those variables, i.e.,\n /// in phase encoding it is computed by a Controlled-Z gate.\n /// Extending this to an XOR of the AND of more variables, as required in\n /// the definition of the IP function can then be accomplished by applying\n /// several Controlled-Z gates between the respective inputs.\n operation BentFunction(register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n let xs = register[0 .. u - 1];\n let ys = register[u...];\n for index in 0..u-1 {\n CZ(xs[index], ys[index]);\n }\n }\n\n /// # Summary\n /// Implements a shifted bend function 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n ///\n /// # Description\n /// For the hidden shift problem we need another function g which is related\n /// to IP via g(x) = IP(x + s), i.e., we have to shift the argument of the\n /// IP function by a given shift. Notice that the '+' operation here is the\n /// Boolean addition, i.e., a bit-wise operation. Notice further, that in\n /// general a diagonal operation |x〉 -> (-1)^{f(x)} can be turned into a\n /// shifted version by applying a bit flip to the |x〉 register first, then\n /// applying the diagonal operation, and then undoing the bit flips to the\n /// |x〉 register. We use this principle to define shifted versions of the IP\n /// operation.\n operation ShiftedBentFunction(shift : Int, register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n within {\n // Flips the bits in shift.\n ApplyXorInPlace(shift, register);\n } apply {\n // Compute the IP function into the phase.\n BentFunction(register);\n }\n }\n}\n"
71
71
  },
72
72
  {
73
73
  "title": "Hidden Shift (Advanced)",
74
74
  "shots": 1,
75
- "code": "/// # Sample\n/// Hidden shift\n///\n/// # Description\n/// There is a family of problems known as hidden shift problems, in which it\n/// is given that two Boolean functions 𝑓 and 𝑔 satisfy the relation\n/// 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥\n/// where 𝑠 is a hidden bit string that we would like to find.\n///\n/// This Q# program implements an algorithm to solve the hidden shift problem.\nnamespace Sample {\n open Microsoft.Quantum.Arithmetic;\n open Microsoft.Quantum.Arrays;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : Int[] {\n let nQubits = 10;\n\n // Consider the case of finding a hidden shift 𝑠 between two Boolean\n // functions 𝑓(𝑥) and 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n // This problem can be solved on a quantum computer with one call to\n // each of 𝑓 and 𝑔 in the special case that both functions are bent;\n // that is, that they are as far from linear as possible.\n\n // Here, we find the hidden shift for various pairs of bent functions.\n let shifts = [170, 512, 999];\n mutable hiddenShifts = [];\n for shift in shifts {\n let hiddenShiftBitString = FindHiddenShift(\n BentFunction,\n register => ShiftedBentFunction(shift, register),\n nQubits);\n let hiddenShift = ResultArrayAsInt(hiddenShiftBitString);\n Fact(\n hiddenShift == shift,\n $\"Found shift {hiddenShift}, but expected {shift}.\");\n Message($\"Found {shift} successfully!\");\n set hiddenShifts += [hiddenShift];\n }\n\n return hiddenShifts;\n }\n\n /// # Summary\n /// Implements a correlation-based algorithm to solve the hidden shift\n /// problem for bent functions.\n ///\n /// # Description\n /// Implements a solution for the hidden shift problem, which is to identify\n /// an unknown shift 𝑠 of the arguments of two Boolean functions 𝑓 and 𝑔\n /// that are promised to satisfy the relation 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥.\n ///\n /// 𝑓 and 𝑔 are assumed to be bent functions. A Boolean function is bent if\n /// it is as far from linear as possible. In particular, bent functions have\n /// flat Fourier (Walsh–Hadamard) spectra.\n ///\n /// In this case, the Roetteler algorithm (see References, below) uses\n /// black-box oracles for 𝑓^* and 𝑔, where 𝑓^* is the dual bent function to\n /// 𝑓, and computes the hidden shift 𝑠 between 𝑓 and 𝑔.\n ///\n /// # Input\n /// ## Ufstar\n /// A quantum operation that implements\n /// $U_f^*: |𝑥〉 ↦ (-1)^{f^*(x)} |𝑥〉$,\n /// where $f^*$ is a Boolean function, 𝑥 is an $n$ bit register\n /// ## Ug\n /// A quantum operation that implements\n /// $U_g:|𝑥〉 ↦ (-1)^{g(x)} |𝑥〉$,\n /// where 𝑔 is a Boolean function that is shifted by unknown\n /// 𝑠 from 𝑓, and 𝑥 is an $n$ bit register.\n /// ## n\n /// The number of bits of the input register |𝑥〉.\n ///\n /// # Output\n /// An array of type `Result[]` which encodes the bit representation\n /// of the hidden shift.\n ///\n /// # References\n /// - [*Martin Roetteler*,\n /// Proc. SODA 2010, ACM, pp. 448-457, 2010]\n /// (https://doi.org/10.1137/1.9781611973075.37)\n operation FindHiddenShift (\n Ufstar : (Qubit[] => Unit),\n Ug : (Qubit[] => Unit),\n n : Int)\n : Result[] {\n // We allocate n clean qubits. Note that the function Ufstar and Ug are\n // unitary operations on n qubits defined via phase encoding.\n use qubits = Qubit[n];\n\n // First, a Hadamard transform is applied to each of the qubits.\n ApplyToEach(H, qubits);\n\n // We now apply the shifted function Ug to the n qubits, computing\n // |x〉 -> (-1)^{g(x)} |x〉.\n Ug(qubits);\n\n within {\n // A Hadamard transform is applied to each of the n qubits.\n ApplyToEachA(H, qubits);\n } apply {\n // we now apply the dual function of the unshifted function, i.e.,\n // Ufstar, to the n qubits, computing |x〉 -> (-1)^{fstar(x)} |x〉.\n Ufstar(qubits);\n }\n\n // Measure the n qubits and reset them to zero so that they can be\n // safely deallocated at the end of the block.\n return ForEach(MResetZ, qubits);\n }\n\n /// # Summary\n /// Implements an oracle for a bent function constructed from the inner\n /// product of Boolean functions.\n ///\n /// # Description\n /// This operation defines the Boolean function IP(x_0, ..., x_{n-1}) which\n /// is computed into the phase, i.e., a diagonal operator that maps\n /// |x〉 -> (-1)^{IP(x)} |x〉, where x stands for x=(x_0, ..., x_{n-1}) and all\n /// the x_i are binary. The IP function is defined as\n /// IP(y, z) = y_0 z_0 + y_1 z_1 + ... y_{u-1} z_{u-1} where\n /// y = (y_0, ..., y_{u-1}) and z = (z_0, ..., z_{u-1}) are two bit vectors\n /// of length u. Notice that the function IP is a Boolean function on n = 2u\n /// bits. IP is a special case of bent function. These are functions for\n /// which the Walsh-Hadamard transform is perfectly flat (in absolute\n /// value).\n /// Because of this flatness, the Walsh-Hadamard spectrum of any bent\n /// function defines a +1/-1 function, i.e., gives rise to another Boolean\n /// function, called the dual bent function. Moreover, for the case of the\n /// IP function it can be shown that IP is equal to its own dual bent\n /// function.\n ///\n /// # Remarks\n /// Notice that a diagonal operator implementing IP between 2 variables y_0\n /// and z_0 is nothing but the AND function between those variables, i.e.,\n /// in phase encoding it is computed by a Controlled-Z gate.\n /// Extending this to an XOR of the AND of more variables, as required in\n /// the definition of the IP function can then be accomplished by applying\n /// several Controlled-Z gates between the respective inputs.\n operation BentFunction(register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n let xs = register[0 .. u - 1];\n let ys = register[u...];\n for index in 0..u-1 {\n CZ(xs[index], ys[index]);\n }\n }\n\n /// # Summary\n /// Implements a shifted bend function 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n ///\n /// # Description\n /// For the hidden shift problem we need another function g which is related\n /// to IP via g(x) = IP(x + s), i.e., we have to shift the argument of the\n /// IP function by a given shift. Notice that the '+' operation here is the\n /// Boolean addition, i.e., a bit-wise operation. Notice further, that in\n /// general a diagonal operation |x〉 -> (-1)^{f(x)} can be turned into a\n /// shifted version by applying a bit flip to the |x〉 register first, then\n /// applying the diagonal operation, and then undoing the bit flips to the\n /// |x〉 register. We use this principle to define shifted versions of the IP\n /// operation.\n operation ShiftedBentFunction(shift : Int, register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n within {\n // Flips the bits in shift.\n ApplyXorInPlace(shift, register);\n } apply {\n // Compute the IP function into the phase.\n BentFunction(register);\n }\n }\n}\n"
75
+ "code": "/// # Sample\n/// Hidden shift\n///\n/// # Description\n/// There is a family of problems known as hidden shift problems, in which it\n/// is given that two Boolean functions 𝑓 and 𝑔 satisfy the relation\n/// 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥\n/// where 𝑠 is a hidden bit string that we would like to find.\n///\n/// This Q# program implements an algorithm to solve the hidden shift problem.\nnamespace Sample {\n open Microsoft.Quantum.Arrays;\n open Microsoft.Quantum.Convert;\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Measurement;\n\n @EntryPoint()\n operation Main() : Int[] {\n let nQubits = 10;\n\n // Consider the case of finding a hidden shift 𝑠 between two Boolean\n // functions 𝑓(𝑥) and 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n // This problem can be solved on a quantum computer with one call to\n // each of 𝑓 and 𝑔 in the special case that both functions are bent;\n // that is, that they are as far from linear as possible.\n\n // Here, we find the hidden shift for various pairs of bent functions.\n let shifts = [170, 512, 999];\n mutable hiddenShifts = [];\n for shift in shifts {\n let hiddenShiftBitString = FindHiddenShift(\n BentFunction,\n register => ShiftedBentFunction(shift, register),\n nQubits);\n let hiddenShift = ResultArrayAsInt(hiddenShiftBitString);\n Fact(\n hiddenShift == shift,\n $\"Found shift {hiddenShift}, but expected {shift}.\");\n Message($\"Found {shift} successfully!\");\n set hiddenShifts += [hiddenShift];\n }\n\n return hiddenShifts;\n }\n\n /// # Summary\n /// Implements a correlation-based algorithm to solve the hidden shift\n /// problem for bent functions.\n ///\n /// # Description\n /// Implements a solution for the hidden shift problem, which is to identify\n /// an unknown shift 𝑠 of the arguments of two Boolean functions 𝑓 and 𝑔\n /// that are promised to satisfy the relation 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠) for all 𝑥.\n ///\n /// 𝑓 and 𝑔 are assumed to be bent functions. A Boolean function is bent if\n /// it is as far from linear as possible. In particular, bent functions have\n /// flat Fourier (Walsh–Hadamard) spectra.\n ///\n /// In this case, the Roetteler algorithm (see References, below) uses\n /// black-box oracles for 𝑓^* and 𝑔, where 𝑓^* is the dual bent function to\n /// 𝑓, and computes the hidden shift 𝑠 between 𝑓 and 𝑔.\n ///\n /// # Input\n /// ## Ufstar\n /// A quantum operation that implements\n /// $U_f^*: |𝑥〉 ↦ (-1)^{f^*(x)} |𝑥〉$,\n /// where $f^*$ is a Boolean function, 𝑥 is an $n$ bit register\n /// ## Ug\n /// A quantum operation that implements\n /// $U_g:|𝑥〉 ↦ (-1)^{g(x)} |𝑥〉$,\n /// where 𝑔 is a Boolean function that is shifted by unknown\n /// 𝑠 from 𝑓, and 𝑥 is an $n$ bit register.\n /// ## n\n /// The number of bits of the input register |𝑥〉.\n ///\n /// # Output\n /// An array of type `Result[]` which encodes the bit representation\n /// of the hidden shift.\n ///\n /// # References\n /// - [*Martin Roetteler*,\n /// Proc. SODA 2010, ACM, pp. 448-457, 2010]\n /// (https://doi.org/10.1137/1.9781611973075.37)\n operation FindHiddenShift (\n Ufstar : (Qubit[] => Unit),\n Ug : (Qubit[] => Unit),\n n : Int)\n : Result[] {\n // We allocate n clean qubits. Note that the function Ufstar and Ug are\n // unitary operations on n qubits defined via phase encoding.\n use qubits = Qubit[n];\n\n // First, a Hadamard transform is applied to each of the qubits.\n ApplyToEach(H, qubits);\n\n // We now apply the shifted function Ug to the n qubits, computing\n // |x〉 -> (-1)^{g(x)} |x〉.\n Ug(qubits);\n\n within {\n // A Hadamard transform is applied to each of the n qubits.\n ApplyToEachA(H, qubits);\n } apply {\n // we now apply the dual function of the unshifted function, i.e.,\n // Ufstar, to the n qubits, computing |x〉 -> (-1)^{fstar(x)} |x〉.\n Ufstar(qubits);\n }\n\n // Measure the n qubits and reset them to zero so that they can be\n // safely deallocated at the end of the block.\n return ForEach(MResetZ, qubits);\n }\n\n /// # Summary\n /// Implements an oracle for a bent function constructed from the inner\n /// product of Boolean functions.\n ///\n /// # Description\n /// This operation defines the Boolean function IP(x_0, ..., x_{n-1}) which\n /// is computed into the phase, i.e., a diagonal operator that maps\n /// |x〉 -> (-1)^{IP(x)} |x〉, where x stands for x=(x_0, ..., x_{n-1}) and all\n /// the x_i are binary. The IP function is defined as\n /// IP(y, z) = y_0 z_0 + y_1 z_1 + ... y_{u-1} z_{u-1} where\n /// y = (y_0, ..., y_{u-1}) and z = (z_0, ..., z_{u-1}) are two bit vectors\n /// of length u. Notice that the function IP is a Boolean function on n = 2u\n /// bits. IP is a special case of bent function. These are functions for\n /// which the Walsh-Hadamard transform is perfectly flat (in absolute\n /// value).\n /// Because of this flatness, the Walsh-Hadamard spectrum of any bent\n /// function defines a +1/-1 function, i.e., gives rise to another Boolean\n /// function, called the dual bent function. Moreover, for the case of the\n /// IP function it can be shown that IP is equal to its own dual bent\n /// function.\n ///\n /// # Remarks\n /// Notice that a diagonal operator implementing IP between 2 variables y_0\n /// and z_0 is nothing but the AND function between those variables, i.e.,\n /// in phase encoding it is computed by a Controlled-Z gate.\n /// Extending this to an XOR of the AND of more variables, as required in\n /// the definition of the IP function can then be accomplished by applying\n /// several Controlled-Z gates between the respective inputs.\n operation BentFunction(register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n let xs = register[0 .. u - 1];\n let ys = register[u...];\n for index in 0..u-1 {\n CZ(xs[index], ys[index]);\n }\n }\n\n /// # Summary\n /// Implements a shifted bend function 𝑔(𝑥) = 𝑓(𝑥 ⊕ 𝑠).\n ///\n /// # Description\n /// For the hidden shift problem we need another function g which is related\n /// to IP via g(x) = IP(x + s), i.e., we have to shift the argument of the\n /// IP function by a given shift. Notice that the '+' operation here is the\n /// Boolean addition, i.e., a bit-wise operation. Notice further, that in\n /// general a diagonal operation |x〉 -> (-1)^{f(x)} can be turned into a\n /// shifted version by applying a bit flip to the |x〉 register first, then\n /// applying the diagonal operation, and then undoing the bit flips to the\n /// |x〉 register. We use this principle to define shifted versions of the IP\n /// operation.\n operation ShiftedBentFunction(shift : Int, register : Qubit[]) : Unit {\n Fact(Length(register) % 2 == 0, \"Length of register must be even.\");\n let u = Length(register) / 2;\n within {\n // Flips the bits in shift.\n ApplyXorInPlace(shift, register);\n } apply {\n // Compute the IP function into the phase.\n BentFunction(register);\n }\n }\n}\n"
76
76
  },
77
77
  {
78
78
  "title": "Shor",
79
79
  "shots": 1,
80
- "code": "/// # Sample\n/// Shor's algorithm\n///\n/// # Description\n/// Shor's algorithm is a quantum algorithm for finding the prime factors of an\n/// integer.\n///\n/// This Q# program implements Shor's algorithm.\nnamespace Sample {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Random;\n open Microsoft.Quantum.Math;\n open Microsoft.Quantum.Arithmetic;\n open Microsoft.Quantum.Unstable.Arithmetic;\n open Microsoft.Quantum.Arrays;\n\n @EntryPoint()\n operation Main() : (Int, Int) {\n let n = 143; // 11*13;\n // You can try these other examples for a lengthier computation.\n // let n = 16837; // = 113*149\n // let n = 22499; // = 149*151\n\n // Use Shor's algorithm to factor a semiprime integer.\n let (a, b) = FactorSemiprimeInteger(n);\n Message($\"Found factorization {n} = {a} * {b} \");\n return (a, b);\n }\n\n /// # Summary\n /// Uses Shor's algorithm to factor an input number.\n ///\n /// # Input\n /// ## number\n /// A semiprime integer to be factored.\n ///\n /// # Output\n /// Pair of numbers p > 1 and q > 1 such that p⋅q = `number`\n operation FactorSemiprimeInteger(number : Int) : (Int, Int) {\n // First check the most trivial case (the provided number is even).\n if number % 2 == 0 {\n Message(\"An even number has been given; 2 is a factor.\");\n return (number / 2, 2);\n }\n // These mutables will keep track of whether we found the factors, and\n // if so, what they are. The default value for the factors is (1,1).\n mutable foundFactors = false;\n mutable factors = (1, 1);\n mutable attempt = 1;\n repeat {\n Message($\"*** Factorizing {number}, attempt {attempt}.\");\n // Try to guess a number co-prime to `number` by getting a random\n // integer in the interval [1, number-1]\n let generator = DrawRandomInt(1, number - 1);\n\n // Check if the random integer is indeed co-prime.\n // If true use Quantum algorithm for Period finding.\n if GreatestCommonDivisorI(generator, number) == 1 {\n Message($\"Estimating period of {generator}.\");\n\n // Call Quantum Period finding algorithm for\n // `generator` mod `number`.\n let period = EstimatePeriod(generator, number);\n\n // Set the flag and factors values if the continued\n // fractions classical algorithm succeeds.\n set (foundFactors, factors) =\n MaybeFactorsFromPeriod(number, generator, period);\n }\n // In this case, we guessed a divisor by accident.\n else {\n // Find divisor.\n let gcd = GreatestCommonDivisorI(number, generator);\n Message($\"We have guessed a divisor {gcd} by accident. \" +\n \"No quantum computation was done.\");\n\n // Set the flag `foundFactors` to true, indicating that we\n // succeeded in finding factors.\n set foundFactors = true;\n set factors = (gcd, number / gcd);\n }\n set attempt = attempt+1;\n if (attempt > 100) {\n fail \"Failed to find factors: too many attempts!\";\n }\n }\n until foundFactors\n fixup {\n Message(\"The estimated period did not yield a valid factor. \" +\n \"Trying again.\");\n }\n\n // Return the factorization\n return factors;\n }\n\n /// # Summary\n /// Tries to find the factors of `modulus` given a `period` and `generator`.\n ///\n /// # Input\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## period\n /// The estimated period (multiplicative order) of the generator mod\n /// `modulus`.\n ///\n /// # Output\n /// A tuple of a flag indicating whether factors were found successfully,\n /// and a pair of integers representing the factors that were found.\n /// Note that the second output is only meaningful when the first output is\n /// `true`.\n function MaybeFactorsFromPeriod(\n modulus : Int,\n generator : Int,\n period : Int)\n : (Bool, (Int, Int)) {\n\n // Period finding reduces to factoring only if period is even\n if period % 2 == 0 {\n // Compute `generator` ^ `period/2` mod `number`.\n let halfPower = ExpModI(generator, period / 2, modulus);\n\n // If we are unlucky, halfPower is just -1 mod N, which is a trivial\n // case and not useful for factoring.\n if halfPower != modulus - 1 {\n // When the halfPower is not -1 mod N, halfPower-1 or\n // halfPower+1 share non-trivial divisor with `number`. Find it.\n let factor = MaxI(\n GreatestCommonDivisorI(halfPower - 1, modulus),\n GreatestCommonDivisorI(halfPower + 1, modulus)\n );\n\n // Add a flag that we found the factors, and return only if computed\n // non-trivial factors (not like 1:n or n:1)\n if (factor != 1) and (factor != modulus) {\n Message($\"Found factor={factor}\");\n return (true, (factor, modulus / factor));\n }\n } \n // Return a flag indicating we hit a trivial case and didn't get\n // any factors.\n Message($\"Found trivial factors.\");\n return (false, (1, 1));\n } else {\n // When period is odd we have to pick another generator to estimate\n // period of and start over.\n Message($\"Estimated period {period} was odd, trying again.\");\n return (false, (1, 1));\n }\n }\n\n /// # Summary\n /// Find the period of a number from an input frequency.\n ///\n /// # Input\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## frequencyEstimate\n /// The frequency that we want to convert to a period.\n /// ## bitsPrecision\n /// Number of bits of precision with which we need to estimate s/r to\n /// recover period r using continued fractions algorithm.\n /// ## currentDivisor\n /// The divisor of the generator period found so far.\n ///\n /// # Output\n /// The period as calculated from the estimated frequency via the continued\n /// fractions algorithm.\n function PeriodFromFrequency(\n modulus : Int,\n frequencyEstimate : Int,\n bitsPrecision : Int,\n currentDivisor : Int)\n : Int {\n // Now we use the ContinuedFractionConvergentI function to recover s/r\n // from dyadic fraction k/2^bitsPrecision.\n let (numerator, period) = ContinuedFractionConvergentI(\n (frequencyEstimate, 2 ^ bitsPrecision),\n modulus);\n\n // ContinuedFractionConvergentI does not guarantee the signs of the\n // numerator and denominator. Here we make sure that both are positive\n // using AbsI.\n let (numeratorAbs, periodAbs) = (AbsI(numerator), AbsI(period));\n\n // Compute and return the newly found divisor.\n let period =\n (periodAbs * currentDivisor) /\n GreatestCommonDivisorI(currentDivisor, periodAbs);\n Message($\"Found period={period}\");\n return period;\n }\n\n /// # Summary\n /// Finds a multiplicative order of the generator in the residue ring Z mod\n /// `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n ///\n /// # Output\n /// The period (multiplicative order) of the generator mod `modulus`\n operation EstimatePeriod(generator : Int, modulus : Int) : Int {\n // Here we check that the inputs to the EstimatePeriod operation are\n // valid.\n Fact(\n GreatestCommonDivisorI(generator, modulus) == 1,\n \"`generator` and `modulus` must be co-prime\");\n\n // Number of bits in the modulus with respect to which we are estimating\n // the period.\n let bitsize = BitSizeI(modulus);\n\n // The EstimatePeriod operation estimates the period r by finding an\n // approximation k/2^(bits precision) to a fraction s/r, where s is some\n // integer. Note that if s and r have common divisors we will end up\n // recovering a divisor of r and not r itself.\n\n // Number of bits of precision with which we need to estimate s/r to\n // recover period r, using continued fractions algorithm.\n let bitsPrecision = 2 * bitsize + 1;\n\n // Current estimate for the frequency of the form s/r.\n let frequencyEstimate = EstimateFrequency(generator, modulus, bitsize);\n if frequencyEstimate != 0 {\n return PeriodFromFrequency(\n modulus, frequencyEstimate, bitsPrecision, 1);\n }\n else {\n Message(\"The estimated frequency was 0, trying again.\");\n return 1;\n }\n }\n\n /// # Summary\n /// Estimates the frequency of a generator in the residue ring Z mod\n /// `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## bitsize\n /// Number of bits needed to represent the modulus.\n ///\n /// # Output\n /// The numerator k of dyadic fraction k/2^bitsPrecision approximating s/r.\n operation EstimateFrequency(generator : Int,modulus : Int, bitsize : Int)\n : Int {\n mutable frequencyEstimate = 0;\n let bitsPrecision = 2 * bitsize + 1;\n Message($\"Estimating frequency with bitsPrecision={bitsPrecision}.\");\n\n // Allocate qubits for the superposition of eigenstates of the oracle\n // that is used in period finding.\n use eigenstateRegister = Qubit[bitsize];\n\n // Initialize eigenstateRegister to 1, which is a superposition of the\n // eigenstates we are estimating the phases of.\n // We are interpreting the register as encoding an unsigned integer in\n // little-endian format.\n ApplyXorInPlace(1, eigenstateRegister);\n\n // Use phase estimation with a semiclassical Fourier transform to\n // estimate the frequency.\n use c = Qubit();\n for idx in bitsPrecision-1..-1..0 {\n H(c);\n Controlled ApplyOrderFindingOracle(\n [c],\n (generator, modulus, 1 <<< idx, eigenstateRegister));\n R1Frac(frequencyEstimate, bitsPrecision-1-idx, c);\n H(c);\n if M(c) == One {\n X(c); // Reset\n set frequencyEstimate += 1 <<< (bitsPrecision-1-idx);\n }\n }\n\n // Return all the qubits used for oracle's eigenstate back to 0 state\n // using ResetAll.\n ResetAll(eigenstateRegister);\n Message($\"Estimated frequency={frequencyEstimate}\");\n return frequencyEstimate;\n }\n\n /// # Summary\n /// Interprets `target` as encoding unsigned little-endian integer k and\n /// performs transformation |k⟩ ↦ |gᵖ⋅k mod N ⟩ where p is `power`, g is\n /// `generator` and N is `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## power\n /// Power of `generator` by which `target` is multiplied.\n /// ## target\n /// Register interpreted as little-endian which is multiplied by given power\n /// of the generator. The multiplication is performed modulo `modulus`.\n operation ApplyOrderFindingOracle(\n generator : Int,\n modulus : Int,\n power : Int,\n target : Qubit[])\n : Unit is Adj + Ctl {\n // Check that the parameters satisfy the requirements.\n Fact(\n GreatestCommonDivisorI(generator, modulus) == 1,\n \"`generator` and `modulus` must be co-prime\");\n\n // The oracle we use for order finding implements |x⟩ ↦ |x⋅a mod N⟩.\n // We also use `ExpModI` to compute a by which x must be multiplied.\n // Also note that we interpret target as unsigned integer in\n // little-endian fromat.\n ModularMultiplyByConstant(\n modulus,\n ExpModI(generator, power, modulus),\n target);\n }\n\n //\n // Arithmetic helper functions to implement order-finding oracle.\n //\n\n /// # Summary\n /// Returns the number of trailing zeroes of a number.\n ///\n /// ## Example\n /// let zeroes = NTrailingZeroes(21); // NTrailingZeroes(0b1101) = 0\n /// let zeroes = NTrailingZeroes(20); // NTrailingZeroes(0b1100) = 2\n function NTrailingZeroes(number : Int) : Int {\n Fact(number != 0, \"NTrailingZeroes: number cannot be 0.\");\n mutable nZeroes = 0;\n mutable copy = number;\n while (copy % 2 == 0) {\n set nZeroes += 1;\n set copy /= 2;\n }\n return nZeroes;\n }\n\n /// # Summary\n /// Performs modular in-place multiplication by a classical constant.\n ///\n /// # Description\n /// Given the classical constants `c` and `modulus`, and an input quantum\n /// register |𝑦⟩ in little-endian format, this operation computes\n /// `(c*x) % modulus` into |𝑦⟩.\n ///\n /// # Input\n /// ## modulus\n /// Modulus to use for modular multiplication\n /// ## c\n /// Constant by which to multiply |𝑦⟩\n /// ## y\n /// Quantum register of target\n operation ModularMultiplyByConstant(modulus : Int, c : Int, y : Qubit[])\n : Unit is Adj + Ctl {\n use qs = Qubit[Length(y)];\n for idx in IndexRange(y) {\n let shiftedC = (c <<< idx) % modulus;\n Controlled ModularAddConstant(\n [y[idx]],\n (modulus, shiftedC, qs));\n }\n for idx in IndexRange(y) {\n SWAP(y[idx], qs[idx]);\n }\n let invC = InverseModI(c, modulus);\n for idx in IndexRange(y) {\n let shiftedC = (invC <<< idx) % modulus;\n Controlled ModularAddConstant(\n [y[idx]],\n (modulus, modulus - shiftedC, qs));\n }\n }\n\n /// # Summary\n /// Performs modular in-place addition of a classical constant into a\n /// quantum register.\n ///\n /// # Description\n /// Given the classical constants `c` and `modulus`, and an input quantum\n /// register |𝑦⟩ in little-endian format, this operation computes\n /// `(x+c) % modulus` into |𝑦⟩.\n ///\n /// # Input\n /// ## modulus\n /// Modulus to use for modular addition\n /// ## c\n /// Constant to add to |𝑦⟩\n /// ## y\n /// Quantum register of target\n operation ModularAddConstant(modulus : Int, c : Int, y : Qubit[])\n : Unit is Adj + Ctl {\n body (...) {\n Controlled ModularAddConstant([], (modulus, c, y));\n }\n controlled (ctrls, ...) {\n // We apply a custom strategy to control this operation instead of\n // letting the compiler create the controlled variant for us in\n // which the `Controlled` functor would be distributed over each\n // operation in the body.\n //\n // Here we can use some scratch memory to save ensure that at most\n // one control qubit is used for costly operations such as\n // `AddConstant` and `CompareGreaterThenOrEqualConstant`.\n if Length(ctrls) >= 2 {\n use control = Qubit();\n within {\n Controlled X(ctrls, control);\n } apply {\n Controlled ModularAddConstant(\n [control],\n (modulus, c, y));\n }\n } else {\n use carry = Qubit();\n Controlled AddConstant(\n ctrls, (c, y + [carry]));\n Controlled Adjoint AddConstant(\n ctrls, (modulus, y + [carry]));\n Controlled AddConstant(\n [carry], (modulus, y));\n Controlled CompareGreaterThanOrEqualConstant(\n ctrls, (c, y, carry));\n }\n }\n }\n\n /// # Summary\n /// Performs in-place addition of a constant into a quantum register.\n ///\n /// # Description\n /// Given a non-empty quantum register |𝑦⟩ of length 𝑛+1 and a positive\n // constant 𝑐 < 2ⁿ, computes |𝑦 + c⟩ into |𝑦⟩.\n ///\n /// # Input\n /// ## c\n /// Constant number to add to |𝑦⟩.\n /// ## y\n /// Quantum register of second summand and target; must not be empty.\n operation AddConstant(c : Int, y : Qubit[]) : Unit is Adj + Ctl {\n // We are using this version instead of the library version that is\n // based on Fourier angles to show an advantage of sparse simulation\n // in this sample.\n let n = Length(y);\n Fact(n > 0, \"Bit width must be at least 1\");\n Fact(c >= 0, \"constant must not be negative\");\n Fact(c < 2^n, \"constant must be smaller than {2^n)}\");\n if c != 0 {\n // If c has j trailing zeroes than the j least significant bits of y\n // won't be affected by the addition and can therefore be ignored by\n // applying the addition only to the other qubits and shifting c\n // accordingly.\n let j = NTrailingZeroes(c);\n use x = Qubit[n - j];\n within {\n ApplyXorInPlace(c >>> j, x);\n } apply {\n IncByLE(x, y[j...]);\n }\n }\n }\n\n /// # Summary\n /// Performs greater-than-or-equals comparison to a constant.\n ///\n /// # Description\n /// Toggles output qubit `target` if and only if input register `x` is\n /// greater than or equal to `c`.\n ///\n /// # Input\n /// ## c\n /// Constant value for comparison.\n /// ## x\n /// Quantum register to compare against.\n /// ## target\n /// Target qubit for comparison result.\n ///\n /// # Reference\n /// This construction is described in [Lemma 3, arXiv:2201.10200]\n operation CompareGreaterThanOrEqualConstant(\n c : Int,\n x : Qubit[],\n target : Qubit)\n : Unit is Adj+Ctl {\n let bitWidth = Length(x);\n if c == 0 {\n X(target);\n } elif c >= (2^bitWidth) {\n // do nothing\n } elif c == (2^(bitWidth - 1)) {\n CNOT(Tail(x), target);\n } else {\n // normalize constant\n let l = NTrailingZeroes(c);\n let cNormalized = c >>> l;\n let xNormalized = x[l...];\n let bitWidthNormalized = Length(xNormalized);\n use qs = Qubit[bitWidthNormalized - 1];\n let cs1 = [Head(xNormalized)] + Most(qs);\n Fact(Length(cs1) == Length(qs),\n \"Arrays should be of the same length.\");\n within {\n for i in 0..Length(cs1)-1 {\n let op =\n cNormalized &&& (1 <<< (i+1)) != 0 ?\n ApplyAnd | ApplyOr;\n op(cs1[i], xNormalized[i+1], qs[i]);\n }\n } apply {\n CNOT(Tail(qs), target);\n }\n }\n }\n\n /// # Summary\n /// Inverts a given target qubit if and only if both control qubits are in\n /// the 1 state, using measurement to perform the adjoint operation.\n ///\n /// # Description\n /// Inverts `target` if and only if both controls are 1, but assumes that\n /// `target` is in state 0. The operation has T-count 4, T-depth 2 and\n /// requires no helper qubit, and may therefore be preferable to a CCNOT\n /// operation, if `target` is known to be 0.\n /// The adjoint of this operation is measurement based and requires no T\n /// gates.\n /// Although the Toffoli gate (CCNOT) will perform faster in in simulations,\n /// this version has lower T gate requirements.\n ///\n /// # Input\n /// ## control1\n /// First control qubit\n /// ## control2\n /// Second control qubit\n /// ## target\n /// Target auxiliary qubit; must be in state 0\n ///\n /// # References\n /// - Cody Jones: \"Novel constructions for the fault-tolerant\n /// Toffoli gate\",\n /// Phys. Rev. A 87, 022328, 2013\n /// [arXiv:1212.5069](https://arxiv.org/abs/1212.5069)\n /// doi:10.1103/PhysRevA.87.022328\n /// - Craig Gidney: \"Halving the cost of quantum addition\",\n /// Quantum 2, page 74, 2018\n /// [arXiv:1709.06648](https://arxiv.org/abs/1709.06648)\n /// doi:10.1103/PhysRevA.85.044302\n /// - Mathias Soeken: \"Quantum Oracle Circuits and the Christmas\n /// Tree Pattern\",\n /// [Blog article from December 19, 2019](https://msoeken.github.io/blog_qac.html)\n /// (note: explains the multiple controlled construction)\n operation ApplyAnd(control1 : Qubit, control2 : Qubit, target : Qubit)\n : Unit is Adj {\n body (...) {\n H(target);\n T(target);\n CNOT(control1, target);\n CNOT(control2, target);\n within {\n CNOT(target, control1);\n CNOT(target, control2);\n }\n apply {\n Adjoint T(control1);\n Adjoint T(control2);\n T(target);\n }\n H(target);\n S(target);\n }\n adjoint (...) {\n H(target);\n if (M(target) == One) {\n X(target);\n CZ(control1, control2);\n }\n }\n }\n\n /// # Summary\n /// Applies X to the target if any of the controls are 1.\n operation ApplyOr(control1 : Qubit, control2 : Qubit, target : Qubit)\n : Unit is Adj {\n within {\n ApplyToEachA(X, [control1, control2]);\n } apply {\n ApplyAnd(control1, control2, target);\n X(target);\n }\n }\n}\n"
80
+ "code": "/// # Sample\n/// Shor's algorithm\n///\n/// # Description\n/// Shor's algorithm is a quantum algorithm for finding the prime factors of an\n/// integer.\n///\n/// This Q# program implements Shor's algorithm.\nnamespace Sample {\n open Microsoft.Quantum.Diagnostics;\n open Microsoft.Quantum.Random;\n open Microsoft.Quantum.Math;\n open Microsoft.Quantum.Unstable.Arithmetic;\n open Microsoft.Quantum.Arrays;\n\n @EntryPoint()\n operation Main() : (Int, Int) {\n let n = 143; // 11*13;\n // You can try these other examples for a lengthier computation.\n // let n = 16837; // = 113*149\n // let n = 22499; // = 149*151\n\n // Use Shor's algorithm to factor a semiprime integer.\n let (a, b) = FactorSemiprimeInteger(n);\n Message($\"Found factorization {n} = {a} * {b} \");\n return (a, b);\n }\n\n /// # Summary\n /// Uses Shor's algorithm to factor an input number.\n ///\n /// # Input\n /// ## number\n /// A semiprime integer to be factored.\n ///\n /// # Output\n /// Pair of numbers p > 1 and q > 1 such that p⋅q = `number`\n operation FactorSemiprimeInteger(number : Int) : (Int, Int) {\n // First check the most trivial case (the provided number is even).\n if number % 2 == 0 {\n Message(\"An even number has been given; 2 is a factor.\");\n return (number / 2, 2);\n }\n // These mutables will keep track of whether we found the factors, and\n // if so, what they are. The default value for the factors is (1,1).\n mutable foundFactors = false;\n mutable factors = (1, 1);\n mutable attempt = 1;\n repeat {\n Message($\"*** Factorizing {number}, attempt {attempt}.\");\n // Try to guess a number co-prime to `number` by getting a random\n // integer in the interval [1, number-1]\n let generator = DrawRandomInt(1, number - 1);\n\n // Check if the random integer is indeed co-prime.\n // If true use Quantum algorithm for Period finding.\n if GreatestCommonDivisorI(generator, number) == 1 {\n Message($\"Estimating period of {generator}.\");\n\n // Call Quantum Period finding algorithm for\n // `generator` mod `number`.\n let period = EstimatePeriod(generator, number);\n\n // Set the flag and factors values if the continued\n // fractions classical algorithm succeeds.\n set (foundFactors, factors) =\n MaybeFactorsFromPeriod(number, generator, period);\n }\n // In this case, we guessed a divisor by accident.\n else {\n // Find divisor.\n let gcd = GreatestCommonDivisorI(number, generator);\n Message($\"We have guessed a divisor {gcd} by accident. \" +\n \"No quantum computation was done.\");\n\n // Set the flag `foundFactors` to true, indicating that we\n // succeeded in finding factors.\n set foundFactors = true;\n set factors = (gcd, number / gcd);\n }\n set attempt = attempt+1;\n if (attempt > 100) {\n fail \"Failed to find factors: too many attempts!\";\n }\n }\n until foundFactors\n fixup {\n Message(\"The estimated period did not yield a valid factor. \" +\n \"Trying again.\");\n }\n\n // Return the factorization\n return factors;\n }\n\n /// # Summary\n /// Tries to find the factors of `modulus` given a `period` and `generator`.\n ///\n /// # Input\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## period\n /// The estimated period (multiplicative order) of the generator mod\n /// `modulus`.\n ///\n /// # Output\n /// A tuple of a flag indicating whether factors were found successfully,\n /// and a pair of integers representing the factors that were found.\n /// Note that the second output is only meaningful when the first output is\n /// `true`.\n function MaybeFactorsFromPeriod(\n modulus : Int,\n generator : Int,\n period : Int)\n : (Bool, (Int, Int)) {\n\n // Period finding reduces to factoring only if period is even\n if period % 2 == 0 {\n // Compute `generator` ^ `period/2` mod `number`.\n let halfPower = ExpModI(generator, period / 2, modulus);\n\n // If we are unlucky, halfPower is just -1 mod N, which is a trivial\n // case and not useful for factoring.\n if halfPower != modulus - 1 {\n // When the halfPower is not -1 mod N, halfPower-1 or\n // halfPower+1 share non-trivial divisor with `number`. Find it.\n let factor = MaxI(\n GreatestCommonDivisorI(halfPower - 1, modulus),\n GreatestCommonDivisorI(halfPower + 1, modulus)\n );\n\n // Add a flag that we found the factors, and return only if computed\n // non-trivial factors (not like 1:n or n:1)\n if (factor != 1) and (factor != modulus) {\n Message($\"Found factor={factor}\");\n return (true, (factor, modulus / factor));\n }\n } \n // Return a flag indicating we hit a trivial case and didn't get\n // any factors.\n Message($\"Found trivial factors.\");\n return (false, (1, 1));\n } else {\n // When period is odd we have to pick another generator to estimate\n // period of and start over.\n Message($\"Estimated period {period} was odd, trying again.\");\n return (false, (1, 1));\n }\n }\n\n /// # Summary\n /// Find the period of a number from an input frequency.\n ///\n /// # Input\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## frequencyEstimate\n /// The frequency that we want to convert to a period.\n /// ## bitsPrecision\n /// Number of bits of precision with which we need to estimate s/r to\n /// recover period r using continued fractions algorithm.\n /// ## currentDivisor\n /// The divisor of the generator period found so far.\n ///\n /// # Output\n /// The period as calculated from the estimated frequency via the continued\n /// fractions algorithm.\n function PeriodFromFrequency(\n modulus : Int,\n frequencyEstimate : Int,\n bitsPrecision : Int,\n currentDivisor : Int)\n : Int {\n // Now we use the ContinuedFractionConvergentI function to recover s/r\n // from dyadic fraction k/2^bitsPrecision.\n let (numerator, period) = ContinuedFractionConvergentI(\n (frequencyEstimate, 2 ^ bitsPrecision),\n modulus);\n\n // ContinuedFractionConvergentI does not guarantee the signs of the\n // numerator and denominator. Here we make sure that both are positive\n // using AbsI.\n let (numeratorAbs, periodAbs) = (AbsI(numerator), AbsI(period));\n\n // Compute and return the newly found divisor.\n let period =\n (periodAbs * currentDivisor) /\n GreatestCommonDivisorI(currentDivisor, periodAbs);\n Message($\"Found period={period}\");\n return period;\n }\n\n /// # Summary\n /// Finds a multiplicative order of the generator in the residue ring Z mod\n /// `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n ///\n /// # Output\n /// The period (multiplicative order) of the generator mod `modulus`\n operation EstimatePeriod(generator : Int, modulus : Int) : Int {\n // Here we check that the inputs to the EstimatePeriod operation are\n // valid.\n Fact(\n GreatestCommonDivisorI(generator, modulus) == 1,\n \"`generator` and `modulus` must be co-prime\");\n\n // Number of bits in the modulus with respect to which we are estimating\n // the period.\n let bitsize = BitSizeI(modulus);\n\n // The EstimatePeriod operation estimates the period r by finding an\n // approximation k/2^(bits precision) to a fraction s/r, where s is some\n // integer. Note that if s and r have common divisors we will end up\n // recovering a divisor of r and not r itself.\n\n // Number of bits of precision with which we need to estimate s/r to\n // recover period r, using continued fractions algorithm.\n let bitsPrecision = 2 * bitsize + 1;\n\n // Current estimate for the frequency of the form s/r.\n let frequencyEstimate = EstimateFrequency(generator, modulus, bitsize);\n if frequencyEstimate != 0 {\n return PeriodFromFrequency(\n modulus, frequencyEstimate, bitsPrecision, 1);\n }\n else {\n Message(\"The estimated frequency was 0, trying again.\");\n return 1;\n }\n }\n\n /// # Summary\n /// Estimates the frequency of a generator in the residue ring Z mod\n /// `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## bitsize\n /// Number of bits needed to represent the modulus.\n ///\n /// # Output\n /// The numerator k of dyadic fraction k/2^bitsPrecision approximating s/r.\n operation EstimateFrequency(generator : Int,modulus : Int, bitsize : Int)\n : Int {\n mutable frequencyEstimate = 0;\n let bitsPrecision = 2 * bitsize + 1;\n Message($\"Estimating frequency with bitsPrecision={bitsPrecision}.\");\n\n // Allocate qubits for the superposition of eigenstates of the oracle\n // that is used in period finding.\n use eigenstateRegister = Qubit[bitsize];\n\n // Initialize eigenstateRegister to 1, which is a superposition of the\n // eigenstates we are estimating the phases of.\n // We are interpreting the register as encoding an unsigned integer in\n // little-endian format.\n ApplyXorInPlace(1, eigenstateRegister);\n\n // Use phase estimation with a semiclassical Fourier transform to\n // estimate the frequency.\n use c = Qubit();\n for idx in bitsPrecision-1..-1..0 {\n H(c);\n Controlled ApplyOrderFindingOracle(\n [c],\n (generator, modulus, 1 <<< idx, eigenstateRegister));\n R1Frac(frequencyEstimate, bitsPrecision-1-idx, c);\n H(c);\n if M(c) == One {\n X(c); // Reset\n set frequencyEstimate += 1 <<< (bitsPrecision-1-idx);\n }\n }\n\n // Return all the qubits used for oracle's eigenstate back to 0 state\n // using ResetAll.\n ResetAll(eigenstateRegister);\n Message($\"Estimated frequency={frequencyEstimate}\");\n return frequencyEstimate;\n }\n\n /// # Summary\n /// Interprets `target` as encoding unsigned little-endian integer k and\n /// performs transformation |k⟩ ↦ |gᵖ⋅k mod N ⟩ where p is `power`, g is\n /// `generator` and N is `modulus`.\n ///\n /// # Input\n /// ## generator\n /// The unsigned integer multiplicative order (period) of which is being\n /// estimated. Must be co-prime to `modulus`.\n /// ## modulus\n /// The modulus which defines the residue ring Z mod `modulus` in which the\n /// multiplicative order of `generator` is being estimated.\n /// ## power\n /// Power of `generator` by which `target` is multiplied.\n /// ## target\n /// Register interpreted as little-endian which is multiplied by given power\n /// of the generator. The multiplication is performed modulo `modulus`.\n operation ApplyOrderFindingOracle(\n generator : Int,\n modulus : Int,\n power : Int,\n target : Qubit[])\n : Unit is Adj + Ctl {\n // Check that the parameters satisfy the requirements.\n Fact(\n GreatestCommonDivisorI(generator, modulus) == 1,\n \"`generator` and `modulus` must be co-prime\");\n\n // The oracle we use for order finding implements |x⟩ ↦ |x⋅a mod N⟩.\n // We also use `ExpModI` to compute a by which x must be multiplied.\n // Also note that we interpret target as unsigned integer in\n // little-endian fromat.\n ModularMultiplyByConstant(\n modulus,\n ExpModI(generator, power, modulus),\n target);\n }\n\n //\n // Arithmetic helper functions to implement order-finding oracle.\n //\n\n /// # Summary\n /// Returns the number of trailing zeroes of a number.\n ///\n /// ## Example\n /// let zeroes = NTrailingZeroes(21); // NTrailingZeroes(0b1101) = 0\n /// let zeroes = NTrailingZeroes(20); // NTrailingZeroes(0b1100) = 2\n function NTrailingZeroes(number : Int) : Int {\n Fact(number != 0, \"NTrailingZeroes: number cannot be 0.\");\n mutable nZeroes = 0;\n mutable copy = number;\n while (copy % 2 == 0) {\n set nZeroes += 1;\n set copy /= 2;\n }\n return nZeroes;\n }\n\n /// # Summary\n /// Performs modular in-place multiplication by a classical constant.\n ///\n /// # Description\n /// Given the classical constants `c` and `modulus`, and an input quantum\n /// register |𝑦⟩ in little-endian format, this operation computes\n /// `(c*x) % modulus` into |𝑦⟩.\n ///\n /// # Input\n /// ## modulus\n /// Modulus to use for modular multiplication\n /// ## c\n /// Constant by which to multiply |𝑦⟩\n /// ## y\n /// Quantum register of target\n operation ModularMultiplyByConstant(modulus : Int, c : Int, y : Qubit[])\n : Unit is Adj + Ctl {\n use qs = Qubit[Length(y)];\n for idx in IndexRange(y) {\n let shiftedC = (c <<< idx) % modulus;\n Controlled ModularAddConstant(\n [y[idx]],\n (modulus, shiftedC, qs));\n }\n for idx in IndexRange(y) {\n SWAP(y[idx], qs[idx]);\n }\n let invC = InverseModI(c, modulus);\n for idx in IndexRange(y) {\n let shiftedC = (invC <<< idx) % modulus;\n Controlled ModularAddConstant(\n [y[idx]],\n (modulus, modulus - shiftedC, qs));\n }\n }\n\n /// # Summary\n /// Performs modular in-place addition of a classical constant into a\n /// quantum register.\n ///\n /// # Description\n /// Given the classical constants `c` and `modulus`, and an input quantum\n /// register |𝑦⟩ in little-endian format, this operation computes\n /// `(x+c) % modulus` into |𝑦⟩.\n ///\n /// # Input\n /// ## modulus\n /// Modulus to use for modular addition\n /// ## c\n /// Constant to add to |𝑦⟩\n /// ## y\n /// Quantum register of target\n operation ModularAddConstant(modulus : Int, c : Int, y : Qubit[])\n : Unit is Adj + Ctl {\n body (...) {\n Controlled ModularAddConstant([], (modulus, c, y));\n }\n controlled (ctrls, ...) {\n // We apply a custom strategy to control this operation instead of\n // letting the compiler create the controlled variant for us in\n // which the `Controlled` functor would be distributed over each\n // operation in the body.\n //\n // Here we can use some scratch memory to save ensure that at most\n // one control qubit is used for costly operations such as\n // `AddConstant` and `CompareGreaterThenOrEqualConstant`.\n if Length(ctrls) >= 2 {\n use control = Qubit();\n within {\n Controlled X(ctrls, control);\n } apply {\n Controlled ModularAddConstant(\n [control],\n (modulus, c, y));\n }\n } else {\n use carry = Qubit();\n Controlled AddConstant(\n ctrls, (c, y + [carry]));\n Controlled Adjoint AddConstant(\n ctrls, (modulus, y + [carry]));\n Controlled AddConstant(\n [carry], (modulus, y));\n Controlled CompareGreaterThanOrEqualConstant(\n ctrls, (c, y, carry));\n }\n }\n }\n\n /// # Summary\n /// Performs in-place addition of a constant into a quantum register.\n ///\n /// # Description\n /// Given a non-empty quantum register |𝑦⟩ of length 𝑛+1 and a positive\n // constant 𝑐 < 2ⁿ, computes |𝑦 + c⟩ into |𝑦⟩.\n ///\n /// # Input\n /// ## c\n /// Constant number to add to |𝑦⟩.\n /// ## y\n /// Quantum register of second summand and target; must not be empty.\n operation AddConstant(c : Int, y : Qubit[]) : Unit is Adj + Ctl {\n // We are using this version instead of the library version that is\n // based on Fourier angles to show an advantage of sparse simulation\n // in this sample.\n let n = Length(y);\n Fact(n > 0, \"Bit width must be at least 1\");\n Fact(c >= 0, \"constant must not be negative\");\n Fact(c < 2^n, \"constant must be smaller than {2^n)}\");\n if c != 0 {\n // If c has j trailing zeroes than the j least significant bits of y\n // won't be affected by the addition and can therefore be ignored by\n // applying the addition only to the other qubits and shifting c\n // accordingly.\n let j = NTrailingZeroes(c);\n use x = Qubit[n - j];\n within {\n ApplyXorInPlace(c >>> j, x);\n } apply {\n IncByLE(x, y[j...]);\n }\n }\n }\n\n /// # Summary\n /// Performs greater-than-or-equals comparison to a constant.\n ///\n /// # Description\n /// Toggles output qubit `target` if and only if input register `x` is\n /// greater than or equal to `c`.\n ///\n /// # Input\n /// ## c\n /// Constant value for comparison.\n /// ## x\n /// Quantum register to compare against.\n /// ## target\n /// Target qubit for comparison result.\n ///\n /// # Reference\n /// This construction is described in [Lemma 3, arXiv:2201.10200]\n operation CompareGreaterThanOrEqualConstant(\n c : Int,\n x : Qubit[],\n target : Qubit)\n : Unit is Adj+Ctl {\n let bitWidth = Length(x);\n if c == 0 {\n X(target);\n } elif c >= (2^bitWidth) {\n // do nothing\n } elif c == (2^(bitWidth - 1)) {\n CNOT(Tail(x), target);\n } else {\n // normalize constant\n let l = NTrailingZeroes(c);\n let cNormalized = c >>> l;\n let xNormalized = x[l...];\n let bitWidthNormalized = Length(xNormalized);\n use qs = Qubit[bitWidthNormalized - 1];\n let cs1 = [Head(xNormalized)] + Most(qs);\n Fact(Length(cs1) == Length(qs),\n \"Arrays should be of the same length.\");\n within {\n for i in 0..Length(cs1)-1 {\n let op =\n cNormalized &&& (1 <<< (i+1)) != 0 ?\n ApplyAnd | ApplyOr;\n op(cs1[i], xNormalized[i+1], qs[i]);\n }\n } apply {\n CNOT(Tail(qs), target);\n }\n }\n }\n\n /// # Summary\n /// Inverts a given target qubit if and only if both control qubits are in\n /// the 1 state, using measurement to perform the adjoint operation.\n ///\n /// # Description\n /// Inverts `target` if and only if both controls are 1, but assumes that\n /// `target` is in state 0. The operation has T-count 4, T-depth 2 and\n /// requires no helper qubit, and may therefore be preferable to a CCNOT\n /// operation, if `target` is known to be 0.\n /// The adjoint of this operation is measurement based and requires no T\n /// gates.\n /// Although the Toffoli gate (CCNOT) will perform faster in in simulations,\n /// this version has lower T gate requirements.\n ///\n /// # Input\n /// ## control1\n /// First control qubit\n /// ## control2\n /// Second control qubit\n /// ## target\n /// Target auxiliary qubit; must be in state 0\n ///\n /// # References\n /// - Cody Jones: \"Novel constructions for the fault-tolerant\n /// Toffoli gate\",\n /// Phys. Rev. A 87, 022328, 2013\n /// [arXiv:1212.5069](https://arxiv.org/abs/1212.5069)\n /// doi:10.1103/PhysRevA.87.022328\n /// - Craig Gidney: \"Halving the cost of quantum addition\",\n /// Quantum 2, page 74, 2018\n /// [arXiv:1709.06648](https://arxiv.org/abs/1709.06648)\n /// doi:10.1103/PhysRevA.85.044302\n /// - Mathias Soeken: \"Quantum Oracle Circuits and the Christmas\n /// Tree Pattern\",\n /// [Blog article from December 19, 2019](https://msoeken.github.io/blog_qac.html)\n /// (note: explains the multiple controlled construction)\n operation ApplyAnd(control1 : Qubit, control2 : Qubit, target : Qubit)\n : Unit is Adj {\n body (...) {\n H(target);\n T(target);\n CNOT(control1, target);\n CNOT(control2, target);\n within {\n CNOT(target, control1);\n CNOT(target, control2);\n }\n apply {\n Adjoint T(control1);\n Adjoint T(control2);\n T(target);\n }\n H(target);\n S(target);\n }\n adjoint (...) {\n H(target);\n if (M(target) == One) {\n X(target);\n CZ(control1, control2);\n }\n }\n }\n\n /// # Summary\n /// Applies X to the target if any of the controls are 1.\n operation ApplyOr(control1 : Qubit, control2 : Qubit, target : Qubit)\n : Unit is Adj {\n within {\n ApplyToEachA(X, [control1, control2]);\n } apply {\n ApplyAnd(control1, control2, target);\n X(target);\n }\n }\n}\n"
81
81
  }
82
82
  ];
@@ -690,14 +690,15 @@ class LanguageService {
690
690
  }
691
691
  /**
692
692
  * @param {string} notebook_uri
693
+ * @param {INotebookMetadata} notebook_metadata
693
694
  * @param {(ICell)[]} cells
694
695
  */
695
- update_notebook_document(notebook_uri, cells) {
696
+ update_notebook_document(notebook_uri, notebook_metadata, cells) {
696
697
  const ptr0 = passStringToWasm0(notebook_uri, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
697
698
  const len0 = WASM_VECTOR_LEN;
698
699
  const ptr1 = passArrayJsValueToWasm0(cells, wasm.__wbindgen_export_0);
699
700
  const len1 = WASM_VECTOR_LEN;
700
- wasm.languageservice_update_notebook_document(this.__wbg_ptr, ptr0, len0, ptr1, len1);
701
+ wasm.languageservice_update_notebook_document(this.__wbg_ptr, ptr0, len0, addHeapObject(notebook_metadata), ptr1, len1);
701
702
  }
702
703
  /**
703
704
  * @param {string} notebook_uri
@@ -134,7 +134,7 @@ export interface IRelatedInformation {
134
134
  }
135
135
 
136
136
  export interface IWorkspaceConfiguration {
137
- targetProfile?: "full" | "base";
137
+ targetProfile?: TargetProfile;
138
138
  packageType?: "exe" | "lib";
139
139
  }
140
140
 
@@ -144,7 +144,7 @@ export interface ICompletionList {
144
144
 
145
145
  export interface ICompletionItem {
146
146
  label: string;
147
- kind: "function" | "interface" | "keyword" | "module" | "property";
147
+ kind: "function" | "interface" | "keyword" | "module" | "property" | "variable" | "typeParameter";
148
148
  sortText?: string;
149
149
  detail?: string;
150
150
  additionalTextEdits?: ITextEdit[];
@@ -197,6 +197,14 @@ export interface ICell {
197
197
  code: string;
198
198
  }
199
199
 
200
+ export interface INotebookMetadata {
201
+ targetProfile?: "unrestricted" | "base";
202
+ }
203
+
204
+
205
+ export type TargetProfile = "base" | "unrestricted";
206
+
207
+
200
208
  /**
201
209
  */
202
210
  export class DebugService {
@@ -278,9 +286,10 @@ export class LanguageService {
278
286
  close_document(uri: string): void;
279
287
  /**
280
288
  * @param {string} notebook_uri
289
+ * @param {INotebookMetadata} notebook_metadata
281
290
  * @param {(ICell)[]} cells
282
291
  */
283
- update_notebook_document(notebook_uri: string, cells: (ICell)[]): void;
292
+ update_notebook_document(notebook_uri: string, notebook_metadata: INotebookMetadata, cells: (ICell)[]): void;
284
293
  /**
285
294
  * @param {string} notebook_uri
286
295
  * @param {(string)[]} cell_uris
Binary file
@@ -134,7 +134,7 @@ export interface IRelatedInformation {
134
134
  }
135
135
 
136
136
  export interface IWorkspaceConfiguration {
137
- targetProfile?: "full" | "base";
137
+ targetProfile?: TargetProfile;
138
138
  packageType?: "exe" | "lib";
139
139
  }
140
140
 
@@ -144,7 +144,7 @@ export interface ICompletionList {
144
144
 
145
145
  export interface ICompletionItem {
146
146
  label: string;
147
- kind: "function" | "interface" | "keyword" | "module" | "property";
147
+ kind: "function" | "interface" | "keyword" | "module" | "property" | "variable" | "typeParameter";
148
148
  sortText?: string;
149
149
  detail?: string;
150
150
  additionalTextEdits?: ITextEdit[];
@@ -197,6 +197,14 @@ export interface ICell {
197
197
  code: string;
198
198
  }
199
199
 
200
+ export interface INotebookMetadata {
201
+ targetProfile?: "unrestricted" | "base";
202
+ }
203
+
204
+
205
+ export type TargetProfile = "base" | "unrestricted";
206
+
207
+
200
208
  /**
201
209
  */
202
210
  export class DebugService {
@@ -278,9 +286,10 @@ export class LanguageService {
278
286
  close_document(uri: string): void;
279
287
  /**
280
288
  * @param {string} notebook_uri
289
+ * @param {INotebookMetadata} notebook_metadata
281
290
  * @param {(ICell)[]} cells
282
291
  */
283
- update_notebook_document(notebook_uri: string, cells: (ICell)[]): void;
292
+ update_notebook_document(notebook_uri: string, notebook_metadata: INotebookMetadata, cells: (ICell)[]): void;
284
293
  /**
285
294
  * @param {string} notebook_uri
286
295
  * @param {(string)[]} cell_uris
@@ -352,7 +361,7 @@ export interface InitOutput {
352
361
  readonly languageservice_update_configuration: (a: number, b: number) => void;
353
362
  readonly languageservice_update_document: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
354
363
  readonly languageservice_close_document: (a: number, b: number, c: number) => void;
355
- readonly languageservice_update_notebook_document: (a: number, b: number, c: number, d: number, e: number) => void;
364
+ readonly languageservice_update_notebook_document: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
356
365
  readonly languageservice_close_notebook_document: (a: number, b: number, c: number, d: number, e: number) => void;
357
366
  readonly languageservice_get_completions: (a: number, b: number, c: number, d: number) => number;
358
367
  readonly languageservice_get_definition: (a: number, b: number, c: number, d: number) => number;
@@ -686,14 +686,15 @@ export class LanguageService {
686
686
  }
687
687
  /**
688
688
  * @param {string} notebook_uri
689
+ * @param {INotebookMetadata} notebook_metadata
689
690
  * @param {(ICell)[]} cells
690
691
  */
691
- update_notebook_document(notebook_uri, cells) {
692
+ update_notebook_document(notebook_uri, notebook_metadata, cells) {
692
693
  const ptr0 = passStringToWasm0(notebook_uri, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
693
694
  const len0 = WASM_VECTOR_LEN;
694
695
  const ptr1 = passArrayJsValueToWasm0(cells, wasm.__wbindgen_export_0);
695
696
  const len1 = WASM_VECTOR_LEN;
696
- wasm.languageservice_update_notebook_document(this.__wbg_ptr, ptr0, len0, ptr1, len1);
697
+ wasm.languageservice_update_notebook_document(this.__wbg_ptr, ptr0, len0, addHeapObject(notebook_metadata), ptr1, len1);
697
698
  }
698
699
  /**
699
700
  * @param {string} notebook_uri
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qsharp-lang",
3
3
  "description": "qsharp language package for quantum development",
4
- "version": "1.0.24-dev",
4
+ "version": "1.0.25-dev",
5
5
  "license": "MIT",
6
6
  "engines": {
7
7
  "node": ">=16.17.0"