Como criar e gerenciar Q# projetos e bibliotecas personalizadas
Neste artigo, você aprenderá a criar, gerenciar e compartilhar Q# projetos. Q# Projetos são estruturas de pastas com vários Q# arquivos que podem acessar as operações e funções uns dos outros. Os projetos são úteis para organizar logicamente seu código-fonte. Você também pode usar projetos como bibliotecas personalizadas que podem ser acessadas de fontes externas.
Pré-requisitos
- Um espaço de trabalho do Azure Quantum em sua assinatura do Azure. Para criar um espaço de trabalho, consulte Criar um espaço de trabalho do Azure Quantum.
- Visual Studio Code com a extensão Azure Quantum Development Kit e Python instalada.
- Uma conta do GitHub, se você estiver planejando publicar seu projeto externo em um repositório público do GitHub.
Para executar programas Python, você também precisa:
- Um ambiente Python com Python e Pip instalados.
- O Azure Quantum
qsharp
eazure-quantum
pacotes.
Como Q# funcionam os projetos
Um Q# projeto contém um Q# arquivo de manifesto, chamado qsharp.json, e um ou mais arquivos *.qs em uma estrutura de pastas especificada. Quando um usuário abre um arquivo *.qs no VS Code, ou define o project_root
em um arquivo Jupyter Notebook ou Python, o compilador procura o arquivo de manifesto na hierarquia de pastas ao redor e determina o escopo do projeto. Se nenhum arquivo de manifesto for encontrado, o compilador opera em um único modo de arquivo. Você pode criar um Q# projeto manualmente ou diretamente no VS Code.
Um projeto externo Q# é um projeto padrão Q# que reside em outro diretório ou em um repositório público do GitHub e atua como uma biblioteca personalizada. Um projeto externo usa export
instruções para definir quais funções e operações podem ser acessadas por programas externos. Os programas definem o projeto externo como uma dependência em seu arquivo de manifesto e usam import
instruções para acessar os itens (operações, funções, estruturas e namespaces) no projeto externo. Para obter mais informações, consulte Usando projetos como dependências externas.
Definir um Q# projeto
Um Q# projeto é definido pela presença de um arquivo de manifesto, chamado qsharp.json, e uma pasta src (que contém os Q# arquivos de origem), ambos os quais devem estar na pasta raiz do projeto. Para Q# programas e projetos externos, o Q# compilador deteta a pasta do projeto automaticamente. Para programas Python e Jupyter Notebooks, você deve Q# do projeto com uma qsharp.init
chamada. A estrutura de pastas para um Q# projeto, no entanto, permanece a mesma para todos os tipos de programas.
Definição da pasta do projeto (Q# programas)
Quando um arquivo *.qs é aberto no VS Code, o compilador procura um arquivo de manifesto Q# na estrutura de pastas. Se encontrar um arquivo de manifesto, o compilador incluirá todos os Q# arquivos no diretório /src ou em qualquer um de seus subdiretórios. Os itens de cada arquivo são disponibilizados para todos os outros arquivos dentro do projeto.
Por exemplo, dada esta estrutura de pastas:
-
Teleportation_project
- qsharp.json
-
SRC
- Main.qs
-
Operações de Teletransporte
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
quando você abre o arquivo /src/TeleportOperation/PrepareState/PrepareStateLib.qs, o Q# compilador:
- Verifica /src/TeleportOperation/PrepareState/ para qsharp.json.
- Verifica /src/TeleportOperation para qsharp.json.
- Verifica /src para qsharp.json.
- Verifica / se há qsharp.json.
- Estabelece / como o diretório raiz do projeto e inclui todos os arquivos *.qs sob a raiz no projeto, de acordo com as configurações do arquivo de manifesto.
Criar um arquivo de manifesto
Um arquivo de manifesto é um arquivo de .json simples chamado qsharp.json que pode opcionalmente incluir campos autor, licença e fiapos . O arquivo de manifesto mínimo viável é a cadeia de caracteres {}
. Quando você cria um Q# projeto no VS Code, um arquivo de manifesto mínimo é criado para você.
{}
Exemplos de arquivo de manifesto
A seguir estão alguns exemplos de como os arquivos de manifesto podem definir o escopo do seu Q# projeto.
Neste exemplo, autor é o único campo especificado e, portanto, todos os arquivos *.qs neste diretório e todos os seus subdiretórios são incluídos no Q# projeto.
{ "author":"Microsoft", "license": "MIT" }
Dentro de um Q# projeto, você também pode usar o arquivo de manifesto para ajustar as configurações do VS Code Q# Linter. Por padrão, as três regras do Linter são:
needlessParens
: padrão =allow
divisionByZero
: padrão =warn
redundantSemicolons
: padrão =warn
Usando o arquivo de manifesto, você pode definir cada regra como
allow
,warn
ou , porerror
exemplo{ "author":"Microsoft", "lints": [ { "lint": "needlessParens", "level": "allow" }, { "lint": "redundantSemicolons", "level": "warn" }, { "lint": "divisionByZero", "level": "error" } ] }
Você também pode usar o arquivo de manifesto para definir um projeto externo Q# como uma dependência e acessar remotamente operações e funções nesse projeto externo. Para obter mais informações, consulte Usando projetos como dependências externas.
Q# Requisitos e propriedades do projeto
Os seguintes requisitos e configurações aplicam-se a todos os Q# projetos.
Todos os arquivos *.qs que você deseja incluir no projeto devem estar em uma pasta chamada src, que deve estar sob a pasta raiz do Q#. Quando você cria um Q# projeto no VS Code, a
/src
pasta é criada automaticamente.O arquivo de manifesto deve estar no mesmo nível da pasta src . Quando você cria um Q# projeto no VS Code, um arquivo mínimo é criado automaticamente.
Use
import
instruções para fazer referência a operações e funções de outros arquivos no projeto.import MyMathLib.*; //imports all the callables in the MyMathLib namespace ... Multiply(x,y);
ou referenciando-os individualmente com o namespace
MyMathLib.Multiply(x,y);
Apenas para Q# projetos
- Apenas um arquivo *.qs em um Q# projeto pode ter um ponto de entrada definido, definido por uma única
Main()
operação. - O arquivo *.qs com a definição do ponto de entrada pode ser localizado em qualquer nível abaixo do arquivo de manifesto.
- Qualquer operação ou função armazenada em cache a partir de um arquivo *.qs em qualquer lugar do Q# projeto é exibida em texto preditivo no VS Code.
- Se o namespace de uma operação ou função selecionada ainda não for importado, o VS Code adicionará automaticamente a instrução necessária
import
.
Etapas para criar um Q# projeto
Estas etapas aplicam-se a todos os Q# projetos.
No explorador de ficheiros VS Code, clique com o botão direito do rato na pasta que pretende utilizar para a pasta raiz do projeto e selecione Criar projeto, ou abra a pasta e selecione Q#.Q#
O VS Code cria um arquivo de manifesto mínimo na pasta e adiciona uma
/src
pasta com um arquivo deMain.qs
modelo.Edite o arquivo de manifesto conforme necessário. Consulte Exemplos de arquivo de manifesto.
Adicione e organize seus Q# arquivos de
/src
origem na pasta.Se você estiver acessando o Q# projeto a partir de um programa Python ou Jupyter Notebook, defina o caminho da pasta raiz usando
qsharp.init
. Este exemplo pressupõe que seu programa esteja na pasta /src do Q# projeto:qsharp.init(project_root = '../Teleportation_project')
Se você estiver usando apenas Q# arquivos no VS Code, quando você abre um Q# arquivo, o compilador procura um arquivo de manifesto, determina a pasta raiz do projeto e, em seguida, verifica a subpasta em busca de arquivos *.qs.
Nota
Você também pode criar manualmente o arquivo de manifesto e a /src
pasta na etapa 2.
Exemplo de projeto
Este programa de teletransporte quântico é um exemplo de um Q# projeto baseado na estrutura de pasta única mostrada anteriormente e é executado no simulador local no VS Code. Para executar o programa no hardware do Azure Quantum ou em simuladores de terceiros, consulte Introdução aos programas Q# e do VSCode para obter as etapas para compilar seu programa e conectar-se ao seu espaço de trabalho do Azure.
O exemplo usa esta estrutura de diretório:
-
Teleportation_project
- qsharp.json
-
SRC
- Main.qs
-
Operações de Teletransporte
- TeleportLib.qs
-
PrepareState
- PrepareStateLib.qs
O arquivo de manifesto contém os campos autor e licença :
{
"author":"Microsoft",
"license":"MIT"
}
Q# arquivos de origem
O arquivo principal, Main.qs, contém o ponto de entrada e faz referência ao TeleportOperations.TeleportLib
namespace de TeleportLib.qs.
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 define a Teleport()
operação e chama a PrepareBellPair()
operação de 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);
}
O arquivo PrepareStateLib.qs contém uma operação reutilizável padrão para criar um par Bell.
operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
H(left);
CNOT(left, right);
}
Executando os programas
Selecione a guia para o ambiente no qual você está executando o programa.
Para executar este programa, abra o arquivo Main.qs no VS Code e selecione Executar.
Configurando Q# projetos como dependências externas
Um Q# projeto também pode ser configurado como uma dependência externa para outros projetos, agindo como uma biblioteca, onde as funções e operações no projeto externo Q# são disponibilizadas para vários Q# projetos. Uma dependência externa pode residir em um compartilhamento de unidade ou publicada em um repositório público do GitHub.
Para usar um Q# projeto como uma dependência externa, você precisa:
- Adicione o projeto externo como uma dependência no arquivo de manifesto do projeto chamador.
- Se o projeto externo for publicado no GitHub, adicione a propriedade "files" ao arquivo de manifesto do projeto externo.
- Adicione
export
instruções ao projeto externo. - Adicione
import
instruções ao projeto de chamada.
Configurando os arquivos de manifesto
Projetos externos Q# podem residir em um compartilhamento de unidade local ou de rede ou publicados em um repositório público do GitHub.
O arquivo de manifesto do projeto chamando
Para adicionar uma dependência a um projeto externo em um compartilhamento de unidade, defina a dependência no arquivo de manifesto do projeto chamador.
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyDependency": {
"path": "/path/to/project/folder/on/disk"
}
}
}
onde "MyDependency" é uma cadeia de caracteres definida pelo usuário que identifica o namespace ao chamar uma operação. Por exemplo, se você criar uma dependência chamada "MyMathFunctions", chamaria uma função dessa dependência com MyMathFunctions.MyFunction()
.
Para adicionar uma dependência a um projeto publicado em um repositório público do GitHub
{
"author": "Microsoft",
"dependencies": {
"MyDependency": {
"github": {
"owner": "GitHubUser",
"repo": "GitHubRepoName",
"ref": "CommitHash",
"path": "/path/to/dependency"
}
}
}
Nota
Para dependências do GitHub, "ref" refere-se a uma refspec do GitHub. A Microsoft recomenda sempre usar um hash de confirmação, para que você possa confiar em uma versão específica de sua dependência.
O arquivo de manifesto do projeto externo
Se seu projeto externo Q# for publicado em um repositório público do GitHub, você deverá adicionar a propriedade files ao arquivo de manifesto do projeto externo, incluindo todos os arquivos usados no projeto.
{
"author": "Microsoft",
"license": "MIT",
"files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}
A propriedade "files" é opcional para um projeto externo que está sendo importado via "path"
(ou seja, uma importação local baseada em caminho de arquivo). Ele só é necessário para projetos publicados no GitHub.
Usando a instrução de exportação
Para tornar funções e operações em um projeto externo acessíveis para chamar projetos, use a export
instrução. Você pode exportar qualquer um ou todos os chamáveis no arquivo. Não há suporte para sintaxe curinga, você deve especificar cada chamável para exportação.
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;
Usando a instrução import
A partir do programa de chamada, você usa import
instruções para disponibilizar itens de uma dependência externa.
import
As instruções usam o namespace definido para a dependência no arquivo de manifesto. Por exemplo, para esta dependência
{
"author": "Microsoft",
"license": "MIT",
"dependencies": {
"MyMathFunctions": {
"path": "/path/to/project/folder/on/disk"
}
}
}
você importa callables como
import MyMathFunctions.MyFunction; // imports "MyFunction()" from the namespace
...
A import
instrução também suporta sintaxe curinga e aliases
// 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;
Nota
A instrução usada open
atualmente no Q#, que é usada para fazer referência a bibliotecas e namespaces, ainda é suportada, mas será preterida eventualmente. Enquanto isso, você pode, opcionalmente, atualizar seus arquivos atuais para usar a import
instrução. Por exemplo, open Microsoft.Quantum.Diagnostics;
pode ser substituído por import Microsoft.Quantum.Diagnostics.*;
.
Observe também que, ao usar a import
instrução com as bibliotecas padrão Q# , você pode encurtar o namespace raiz para Std
. Por exemplo, import Microsoft.Quantum.Diagnostics.*;
pode ser escrito como import Std.Diagnostics.*;
.
Exemplo de projeto externo
Neste exemplo, você usará o mesmo programa de teletransporte do exemplo anterior, mas separará o programa de chamada e os chamáveis em projetos diferentes.
Crie duas pastas na sua unidade local, por exemplo "Project_A" e "Project_B".
Crie um Q# projeto em cada pasta seguindo as etapas em Etapas para criar um Q# projeto.
No Project_A, o programa de chamada, copie o código a seguir para o arquivo de manifesto, editando o caminho conforme necessário para Project_B
{ "author": "Microsoft", "license": "MIT", "dependencies": { "MyTeleportLib": { "path": "/Project_B" } } }
No Project_A, copie o seguinte código para 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); } }
No Project_B, copie o seguinte código para 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
Nota
Observe que a
PrepareBellPair
operação não precisa ser exportada porque não é chamada diretamente do seu programa no Project_A. Por estar no âmbito local do Project_B, já está acessível pela operaçãoTeleport
Para executar o programa, abra /Project_A/Main.qs no VS Code e selecione Executar.
Projetos e namespaces implícitos
Em Q# projetos, se um namespace não for especificado em um programa *.qs, o compilador usará o nome do arquivo como namespace. A referência a um chamável a partir de uma dependência externa usa a sintaxe <dependencyName>.<espaço para nomes>.<exigível>. No entanto, se o arquivo for chamado "Main.qs", o compilador assumirá o namespace e a sintaxe de chamada será <dependencyName>.<chamável>, como no exemplo anterior, import MyTeleportLib.Teleport
.
Como não é incomum ter vários arquivos de projeto, você precisa levar em conta a sintaxe correta ao fazer referência a chamáveis. Por exemplo, em um projeto com a seguinte estrutura de arquivos
- /src
- Main.qs
- MathFunctions.qs
os apelos à dependência externa seriam
import MyTeleportLib.MyFunction; // "Main" namespace is implied
import MyTeleportLib.MathFunctions.MyFunction; // "Math" namespace must be explicit
Para obter mais informações sobre o comportamento do namespace, consulte Namespaces de usuário.