在本文中,您將瞭解如何建立、管理和共用 Q# 專案。 專案是一種 Q# 資料夾結構,其中包含多個 Q# 文件,可以存取彼此的操作和功能。 專案可協助您以邏輯方式組織原始程式碼。 你也可以把專案當作自訂函式庫,從外部來源存取。
必要條件
- 在你的Azure訂閱中加入一個Azure Quantum工作區。 要建立工作區,請參見 Create a Azure Quantum workspace。
- Visual Studio Code (VS Code),並安裝了 Microsoft Quantum Development Kit (QDK) 以及 Python 擴充功能。
- 要將外部專案發佈到公開的 GitHub 倉庫,你需要擁有 GitHub 帳號。
要執行 Python 程式,你還需要:
安裝了一個包含 Python 的 Python 環境。
qdkPython 函式庫,包含azure附加功能。python -m pip install --upgrade "qdk[azure]"
項目的運作方式Q#
專案Q#包含一個名為qsharp.json的Q#清單檔案,以及一個或多個位於指定資料夾結構中的.qs和.qsc檔案。 您可以手動建立Q#專案,或直接在VS Code中建立。
當你在 VS Code 中開啟 .qs 或 .qsc 檔案時,編譯器會搜尋相鄰資料夾階層中的清單檔案,並判定專案的範圍。 如果編譯器找不到清單檔案,編譯器就會以單一檔案模式運作。
當你在 project_root 或 Jupyter Notebook 檔案中設定 Python 時,編譯器會尋找 project_root 資料夾中的清單檔。
外部 Q# 專案是一個標準的 Q# 專案,位於另一個目錄或公共GitHub倉庫中,並作為自訂函式庫使用。 外部專案使用陳述式來 export 定義外部程式可存取的函數和作業。 程式會將外部專案定義為其資訊清單檔案中的相依性,並使用 import 陳述式來存取外部專案中的項目,例如作業、函數、結構和命名空間。 如需詳細資訊,請參閱 使用專案作為外部相依性。
Q#定義專案
Q#專案的定義是由根目錄中必須存在的qsharp.json清單檔案和src資料夾所決定的。 資料夾包含srcQ#來源檔案。 對於 Q# 程式和外部專案, Q# 編譯器會自動偵測專案資料夾。 對於 Python 程式和 Jupyter Notebook 檔案,你必須用 Q# 呼叫來指定 專案資料夾。 不過,專案的 Q# 資料夾結構對於所有類型的程式都相同。
定義 Q# 程式專案的資料夾
當您在.qs中開啟VS Code檔案時,Q#編譯器會向上搜尋資料夾結構中的資訊清單檔案。 如果編譯器找到清單檔案,編譯器就會包含該Q#目錄及其子目錄中的所有/src檔案。 每個檔案中定義的項目將可供專案內的所有其他檔案使用。
例如,請考慮下列資料夾結構:
-
Teleportation_project
- qsharp.json
-
src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
當您開啟檔案 /src/TeleportOperation/PrepareState/PrepareStateLib.qs時,編譯器會 Q# 執行下列動作:
- 檢查
/src/TeleportOperation/PrepareState/以尋找qsharp.json。 - 檢查
/src/TeleportOperation以尋找qsharp.json。 - 檢查
/src以尋找qsharp.json。 - 檢查
/Teleportation_projectqsharp.json並找到了檔案。 - 建立
/Teleportation_project為專案的根目錄,並包含專案目錄下.qs的所有.qsc和/src檔案。 如果是清單檔案。
注意
如果您在qsharp.json中明確包含.qs和.qsc檔案路徑,編譯器會載入這些檔案,而不會進行自動尋找程序。 只有在你定義函式庫可從 Git 參考載入時,才需要明確的檔案路徑參考。
建立清單文件
清單檔案是一個名為 qsharp.json JSON 的檔案,可以包含可選 author的 、 license和 lints 欄位。 最小可行的指令清單檔是字串 {}。 當您在Q#中建立VS Code專案時,會為您建立一個最小化的 manifest 檔案。
{}
指令清單檔案範例
以下範例說明清單檔案如何定義您的 Q# 專案範圍。
在此範例中,
author是唯一指定的欄位,因此該目錄及其子目錄中的所有.qs檔案都包含在專案中 Q# 。{ "author":"Microsoft" }在 Q# 專案中,您也可以使用資訊清單檔案來微調 VS CodeQ# Linter 設定。 根據預設,三個 Linter 規則為:
needlessParens:預設值 =allowdivisionByZero:預設 =warnredundantSemicolons:預設值 =warn您可以將資訊清單檔案中的每個規則設定為
allow、 或warnerror。 例如:{ "author":"Microsoft", "lints": [ { "lint": "needlessParens", "level": "allow" }, { "lint": "redundantSemicolons", "level": "warn" }, { "lint": "divisionByZero", "level": "error" } ] }
您也可以使用指令清單檔,將外部 Q# 專案定義為相依性,並遠端訪問該外部專案中的作業和函式。 如需詳細資訊,請參閱 使用專案作為外部相依性。
Q# 專案需求和屬性
下列需求和組態適用於所有 Q# 專案。
.qs您要包含在專案中的所有檔案都必須位於名為src的資料夾下,該資料夾必須位於專案的Q#根資料夾下。 當您在Q#中建立VS Code專案時,會自動建立/src資料夾。資訊清單檔案應與資料夾位於
src同一層級。 當您在VS Code中建立Q#專案時,系統會自動建立一個最小的清單檔案。使用
import語句從專案中的其他檔案中引用操作和函式。import MyMathLib.*; //imports all the callables in the MyMathLib namespace ... Multiply(x,y);或者,使用命名空間個別參考它們。
MyMathLib.Multiply(x,y);
僅適用於 Q# 專案
- 您只能在專案中的一個
.qs檔案中定義入口操作,該Q#操作是默認的作業。 - 您必須將
.qs具有進入點定義的檔案放在資訊清單檔案下方的專案目錄層級。 - 專案中所有從Q#快取的作業和函數將在
.qs的預測文本顯示中表現出來。 - 如果尚未匯入所選作業或函式的命名空間,則 VS Code 會自動新增必要的
import陳述式。
如何建立 Q# 專案
若要建立 Q# 專案,請遵循下列步驟:
在VS Code檔案總管中,前往您要用作Q#專案根資料夾的資料夾。
開啟 [檢視] 功能表,然後選擇 [命令面板]。
輸入 QDK:建立 Q# 專案。 VS Code 在資料夾中建立最小資訊清單檔案,並新增具有
/src範本檔案的Main.qs資料夾。編輯專案的資訊清單檔案。 請參閱 指令清單檔案範例。
在
/src資料夾內新增並組織您的Q#原始檔案。如果你是從 Q# 程式或 Python 存取 Jupyter Notebook 專案,請用 設定
qsharp.init。 此範例假設您的程式位於專案的/src資料夾中Q#:qsharp.init(project_root = '../Teleportation_project')如果你只在 VS Code 中使用 Q# 檔案,VS Code 編譯器會在你開啟 Q# 檔案之後搜尋清單檔案,並判斷專案根目錄。 接著,編譯器會掃描
/src及其子目錄中的.qs和.qsc檔案。
注意
你可以手動建立清單檔案和 /src 資料夾。
範例專案
這個量子傳輸程式是運行於Q#本地模擬器中的專案範例VS Code。 若要在 Azure Quantum 硬體或第三方模擬器上執行程式,請參閱 開始使用 Q# 程式和 VS Code 來了解編譯程式並連接到 Azure Quantum 工作區的步驟。
此範例具有下列目錄結構:
-
傳送計畫
- qsharp.json
-
src
- Main.qs
-
TeleportOperations
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
指令清單檔案包含 作者 和 授權 欄位:
{
"author":"Microsoft",
"license":"MIT"
}
Q# 來源檔案
主檔案Main.qs包含入口點,並從TeleportLib.qs中參考TeleportOperations.TeleportLib的命名空間。
import TeleportOperations.TeleportLib.Teleport; // references the Teleport operation from TeleportLib.qs
operation Main() : Unit {
use msg = Qubit();
use target = Qubit();
H(msg);
Teleport(msg, target); // calls the Teleport() operation from TeleportLib.qs
H(target);
if M(target) == Zero {
Message("Teleported successfully!");
Reset(msg);
Reset(target);
}
}
該TeleportLib.qs檔案定義Teleport運算,並從PrepareBellPair檔案中呼叫PrepareStateLib.qs運算。
import TeleportOperations.PrepareState.PrepareStateLib.*; // references the namespace in PrepareStateLib.qs
operation Teleport(msg : Qubit, target : Qubit) : Unit {
use here = Qubit();
PrepareBellPair(here, target); // calls the PrepareBellPair() operation from PrepareStateLib.qs
Adjoint PrepareBellPair(msg, here);
if M(msg) == One { Z(target); }
if M(here) == One { X(target); }
Reset(here);
}
該 PrepareStateLib.qs 檔案包含建立貝爾配對的標準可重複使用操作。
operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
H(left);
CNOT(left, right);
}
執行程式
選擇你執行程式的環境標籤。
若要執行此程式,請開啟檔案Main.qsVS Code,然後選擇 [執行]。
將 Q# 專案配置為外部相依專案
你可以將專案設定 Q# 為其他專案的外部相依,類似函式庫,讓外部 Q# 專案中的函式與操作可供其他 Q# 專案使用。 外部相依可以存在於磁碟分享,或發佈到公開的 GitHub 倉庫。
若要將 Q# 專案作為外部相依性使用,您必須:
- 將外部專案新增為呼叫專案的指令清單檔中的相依性。
- 如果外部專案已發佈給 GitHub,則在外部專案的清單檔案中新增
files屬性。 - 將
export敘述新增至外部專案。 - 將
import語句新增到呼叫的專案。
設定資訊清單檔案
外部 Q# 專案可以存在於本地或網路磁碟共享中,或是發佈到公開的 GitHub 倉庫。
呼叫的專案指令清單檔
若要將相依性新增至磁碟驅動器共用上的外部專案,請在呼叫專案的指令清單檔中定義相依性。
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyDependency": {
"path": "/path/to/project/folder/on/disk"
}
}
}
在前述的清單檔案中, MyDependency 是使用者定義的字串,當你呼叫操作時用來識別命名空間。 例如,如果您建立名為 MyMathFunctions 的相依關係,則可以使用 MyMathFunctions.MyFunction() 呼叫該相依關係中的函數。
若要在已發佈到公開 GitHub 倉庫的專案中新增相依性,請使用以下範例清單檔案:
{
"author": "Microsoft",
"dependencies": {
"MyDependency": {
"github": {
"owner": "GitHubUser",
"repo": "GitHubRepoName",
"ref": "CommitHash",
"path": "/path/to/dependency"
}
}
}
}
注意
對於 GitHub 依赖项,ref 指的是 GitHub refspec。
Microsoft 建議您一律使用 commit hash,以便可以依賴特定版本的依賴項。
外部專案清單檔案
如果你的外部 Q# 專案發佈到公開的 GitHub 倉庫,則必須在外部專案的清單檔案中新增 files 屬性,包含專案所使用的所有檔案。
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
這個 files 屬性是針對透過使用本地檔案路徑的 "path" 導入外部專案時可選的。
files 屬性僅適用於發佈給 GitHub 的專案。
使用 export 陳述式
若要讓呼叫專案可存取外部專案中的函數和作業,請使用 陳述 export 式。 您可以匯出檔案中的任何或所有可調用項。 你不能使用通配符語法,所以必須具體指明每個你想匯出的可呼叫物件。
operation Operation_A() : Unit {
...
}
operation Operation_B() : Unit {
...
}
// makes just Operation_A available to calling programs
export Operation_A;
// makes Operation_A and Operation_B available to calling programs
export Operation_A, Operation_B, etc.;
// makes Operation_A available as 'OpA'
export Operation_A as OpA;
使用 import 陳述式
若要讓外部相依關係中的項目可供使用,請使用 import 呼叫程式中的陳述式。 這個 import 語句會使用你在清單檔案中為相依定義的命名空間。
例如,請考慮下列資訊清單檔案中的相依性:
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyMathFunctions": {
"path": "/path/to/project/folder/on/disk"
}
}
}
使用下列程式碼匯入可呼叫項目:
import MyMathFunctions.MyFunction; // imports "MyFunction()" from the namespace
...
此 import 陳述式也支援萬用字元語法和別名。
// imports all items from the "MyMathFunctions" namespace
import MyMathFunctions.*;
// imports the namespace as "Math", all items are accessible via "Math.<callable>"
import MyMathFunctions as Math;
// imports a single item, available in the local scope as "Add"
import MyMathFunctions.MyFunction as Add;
// imports can be combined on one line
import MyMathFunctions.MyFunction, MyMathFunctions.AnotherFunction as Multiply;
范例外部專案
在此範例中,使用與前述相同的傳送程式,但將呼叫程式與可呼叫程式分成不同的專案。
在本機磁碟機上建立兩個資料夾,例如
Project_A和Project_B。在每個資料夾中建立專案 Q# 。 如需詳細資訊,請參閱 如何建立 Q# 專案中的步驟。
在
Project_A中的呼叫程式中,將以下程式碼複製到資訊清單檔案中,但根據需要編輯Project_B的路徑:{ "author": "Microsoft", "license": "MIT", "dependencies": { "MyTeleportLib": { "path": "/Project_B" } } }在
Project_A中,將以下程式碼複製到Main.qs:import MyTeleportLib.Teleport; // imports the Teleport operation from the MyTeleportLib namespace defined in the manifest file operation Main() : Unit { use msg = Qubit(); use target = Qubit(); H(msg); Teleport(msg, target); // calls the Teleport() operation from the MyTeleportLib namespace H(target); if M(target) == Zero { Message("Teleported successfully!"); Reset(msg); Reset(target); } }在
Project_B中,將以下程式碼複製到Main.qs:operation Teleport(msg : Qubit, target : Qubit) : Unit { use here = Qubit(); PrepareBellPair(here, target); Adjoint PrepareBellPair(msg, here); if M(msg) == One { Z(target); } if M(here) == One { X(target); } Reset(here); } operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl { H(left); CNOT(left, right); } export Teleport; // makes the Teleport operation available to external programs注意
你不需要匯出
PrepareBellPair操作,如果你的程式Project_A並未直接呼叫該操作。PrepareBellPair運算已被Teleport運算存取,因為PrepareBellPair在Project_B的局部範圍內。若要執行程式,請開啟
/Project_A/Main.qs並 VS Code 選擇 [執行]。
專案和隱含命名空間
在專案中 Q# ,如果你沒有指定程式中的 .qs 命名空間,編譯器就會使用該檔名作為命名空間。 然後,當您從外部依賴參照可呼叫項目時,請使用語法 <dependencyName>.<namespace>.<callable>。 然而,如果檔案名稱 Main.qs為 ,編譯器會假設命名空間與呼叫語法為 <dependencyName>.<callable>。 例如: import MyTeleportLib.Teleport 。
因為您可能有多個專案文件,所以在參照可呼叫物件時,需要考慮正確的語法。 例如,假設專案具有下列檔案結構:
-
/src
- Main.qs
- 數學函數.qs
下列程式碼會呼叫外部相依性:
import MyTeleportLib.MyFunction; // "Main" namespace is implied
import MyTeleportLib.MathFunctions.MyFunction; // "Math" namespace must be explicit
如需命名空間行為的詳細資訊,請參閱 使用者命名空間。