Condividi tramite


Come creare e gestire progetti e librerie personalizzate

Questo articolo illustra come creare, gestire e condividere progetti. Un progetto è una struttura di cartelle con più file che possono accedere tra loro operazioni e funzioni. I progetti consentono di organizzare logicamente il codice sorgente. È anche possibile usare progetti come librerie personalizzate a cui è possibile accedere da origini esterne.

Prerequisiti

  • Un'area di lavoro Azure Quantum nella sottoscrizione Azure. Per creare un'area di lavoro, vedere Creare un'area di lavoro Azure Quantum.
  • () con le estensioni installate () e .
  • Per pubblicare il progetto esterno in un repository di GitHub pubblico, è necessario disporre di un account GitHub.

Per eseguire programmi Python, è necessario anche:

  • Ambiente Python con Python e Pip installato.

  • La libreria qdkPython con l'extra azure.

    python -m pip install --upgrade "qdk[azure]"
    

Funzionamento dei progetti

Un progetto contiene un file manifesto denominato, insieme a uno o più file specifici, in una struttura di cartelle specificata. È possibile creare un progetto manualmente o direttamente in .

Quando si apre un file o in , il compilatore cerca il file manifesto nella gerarchia di cartelle circostanti e determina l'ambito del progetto. Se il compilatore non trova un file manifesto, il compilatore opera in una singola modalità file.

Quando si imposta il project_root in un file Jupyter Notebook o Python, il compilatore cerca il file manifesto nella cartella project_root.

Un progetto Q# esterno è un progetto Q# standard che si trova in un'altra directory o in un repository GitHub pubblico e funge da libreria personalizzata. Un progetto esterno usa istruzioni per definire le funzioni e le operazioni accessibili da programmi esterni. I programmi definiscono il progetto esterno come dipendenza nel file manifest e usano istruzioni per accedere agli elementi del progetto esterno, ad esempio operazioni, funzioni, struct e namespace. Per ulteriori informazioni, vedere l'uso di progetti come dipendenze esterne.

Definire un progetto

Un progetto è definito dalla presenza di un file manifesto e di una cartella, entrambi presenti nella cartella radice del progetto. La cartella contiene i file di origine. Per i programmi e i progetti esterni, il compilatore rileva automaticamente la cartella del progetto. Per Python programmi e Jupyter Notebook file, è necessario specificare la cartella del progetto Q# con una chiamata qsharp.init. Tuttavia, la struttura di cartelle per un progetto è la stessa per tutti i tipi di programmi.

Struttura di cartelle e gerarchia per un progetto.

Definire la cartella del progetto per i programmi

Quando si apre un file in , il compilatore cerca verso l'alto nella struttura di cartelle un file manifesto. Se il compilatore trova un file manifesto, il compilatore include tutti i file nella directory e le relative sottodirectory. Gli elementi definiti in ogni file diventano disponibili per tutti gli altri file all'interno del progetto.

Si consideri ad esempio la struttura di cartelle seguente:

  • Progetto_teletrasporto
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Quando si apre il file , il compilatore esegue le operazioni seguenti:

  1. Controlla per .
  2. Controlla per .
  3. Controlla per .
  4. Controlla e trova il file.
  5. Stabilisce come directory radice del progetto e include tutti i file e nella directory del progetto. Se il file manifest.

Nota

Se si includono riferimenti espliciti a e percorsi di file in , il compilatore carica tali file e non esegue il processo di individuazione automatica. I riferimenti espliciti al percorso del file sono necessari solo quando si definisce una libreria da caricare da un riferimento Git.

Creare un file manifesto

Un file manifesto è un file JSON denominato che può includere campi facoltativi , e . Il file manifesto minimo praticabile è la stringa . Quando si crea un progetto in , viene creato automaticamente un file manifesto minimo.

{}

Esempi di file manifesto

Gli esempi seguenti illustrano come i file manifesto definiscono l'ambito del progetto.

  • In questo esempio, è l'unico campo specificato, quindi tutti i file in questa directory e le relative sottodirectory vengono inclusi nel progetto.

    {
        "author":"Microsoft"
    }
    
  • All'interno di un progetto, è anche possibile usare il file manifesto per ottimizzare le impostazioni Linter. Per impostazione predefinita, le tre regole Linter sono:

    • : default =

    • : default =

    • : default =

      È possibile impostare ogni regola nel file manifesto su , o . Per esempio:

      {
          "author":"Microsoft",
          "lints": [
              {
                "lint": "needlessParens",
                "level": "allow"
              },
              {
                "lint": "redundantSemicolons",
                "level": "warn"
              },
              {
                "lint": "divisionByZero",
                "level": "error"
              }
            ]
      }
      
  • È anche possibile usare il file manifesto per definire un progetto esterno come dipendenza e accedere in remoto a operazioni e funzioni in tale progetto esterno. Per ulteriori informazioni, vedere l'uso di progetti come dipendenze esterne.

requisiti e proprietà del progetto

I requisiti e le configurazioni seguenti si applicano a tutti i progetti.

  • Tutti i file che si desidera includere nel progetto devono trovarsi in una cartella denominata , che deve trovarsi nella cartella radice del progetto. Quando si crea un progetto in , la cartella viene creata automaticamente.

  • Il file manifesto deve essere allo stesso livello della cartella. Quando si crea un progetto in , viene creato automaticamente un file manifesto minimo.

  • Utilizzare le istruzioni per fare riferimento alle operazioni e funzioni da altri file nel progetto.

    import MyMathLib.*;  //imports all the callables in the MyMathLib namespace
    
    ...
    
    Multiply(x,y);
    

    In alternativa, fai riferimento a ciascuno singolarmente utilizzando il namespace.

    MyMathLib.Multiply(x,y); 
    

Solo per progetti

  • È possibile definire un'operazione di punto di ingresso in un solo file di un progetto, ovvero l'operazione per impostazione predefinita.
  • È necessario inserire il file con la definizione del punto di ingresso in una directory del progetto al di sotto del livello del file manifesto.
  • Tutte le operazioni e le funzioni nel progetto che sono memorizzate nella cache da una visualizzazione appaiono in un testo predittivo in .
  • Se lo spazio dei nomi per un'operazione o una funzione selezionata non è ancora importato, aggiunge automaticamente l'istruzione necessaria .

Come creare un progetto

Per creare un progetto, seguire questa procedura:

  1. In Esplora File passa alla cartella che si vuole usare come cartella radice per il progetto.

  2. Aprire il menu Visualizza e scegliere Riquadro comandi.

  3. Immettere : Crea progetto. crea un file manifesto minimo nella cartella e aggiunge una cartella con un file modello.

  4. Modificare il file manifest per il progetto. Vedere Esempi di file manifesto.

  5. Aggiungere e organizzare i file di origine nella cartella .

  6. Se si accede al progetto Q# da un programma Python o Jupyter Notebook, impostare il percorso della cartella root con qsharp.init. Questo esempio presuppone che il programma si trova nella cartella del progetto:

    qsharp.init(project_root = '../Teleportation_project')
    
  7. Se si usano solo file in , il compilatore cerca un file manifesto quando si apre un file e determina la cartella radice del progetto. Quindi, il compilatore analizza e le relative sottodirectory cercando i file .

Nota

È possibile creare manualmente il file manifesto e la cartella.

Progetto di esempio

Questo programma di teletrasporto quantistico è un esempio di progetto eseguito nel simulatore locale in . Per eseguire il programma in Azure Quantum simulatori hardware o di terze parti, vedere Introduzione ai programmi Q# e VS Code per i passaggi per compilare il programma e connettersi all'area di lavoro Azure Quantum.

In questo esempio è presente la struttura di directory seguente:

  • Progetto_teletrasporto
    • qsharp.json
    • src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Il file manifesto contiene i campi autore e licenza :

{
    "author":"Microsoft",
    "license":"MIT"
}

file di origine

Il file principale contiene il punto di ingresso e fa riferimento allo spazio dei nomi da .

    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);
        }
    }

Il file definisce l'operazione e chiama l'operazione dal file.

    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);
    }

Il file contiene un'operazione riutilizzabile standard per creare una coppia Bell.

    operation PrepareBellPair(left : Qubit, right : Qubit) : Unit is Adj + Ctl {
        H(left);
        CNOT(left, right);
    }

Eseguire i programmi

Scegliere la scheda per l'ambiente in cui si esegue il programma.

Per eseguire questo programma, aprire il file in e scegliere Esegui.

Configurare i progetti come dipendenze esterne

È possibile configurare i progetti come dipendenza esterna per altri progetti, in modo analogo a una libreria, per rendere disponibili funzioni e operazioni nel progetto esterno ad altri progetti. Una dipendenza esterna può risiedere su un'unità condivisa o essere pubblicata su un repository GitHub pubblico.

Per usare un progetto come dipendenza esterna, è necessario:

  • Aggiungere il progetto esterno come dipendenza nel file manifesto del progetto chiamante.
  • Se il progetto esterno viene pubblicato in GitHub, aggiungere la proprietà files al file manifesto del progetto esterno.
  • Aggiungere istruzioni al progetto esterno.
  • Aggiungere istruzioni al progetto chiamante.

Configurare i file manifesto

I progetti Q# esterni possono risiedere in una condivisione di unità di rete o locale oppure pubblicarli in un repository GitHub pubblico.

File di manifest del progetto chiamante

Per aggiungere una dipendenza a un progetto esterno in una condivisione di unità, definire la dipendenza nel file manifesto del progetto chiamante.

{
    "author": "Microsoft",
    "license": "MIT",
    "dependencies": {
        "MyDependency": {
            "path": "/path/to/project/folder/on/disk"
        }
    }
}

Nel file manifesto precedente è una stringa definita dall'utente che identifica lo spazio dei nomi quando si chiama un'operazione. Ad esempio, se si crea una dipendenza denominata , è possibile chiamare una funzione da tale dipendenza con .

Per aggiungere una dipendenza a un progetto pubblicato in un repository di GitHub pubblico, usare il file manifesto di esempio seguente:

{
    "author": "Microsoft",
    "dependencies": {
        "MyDependency": {
            "github": {
                "owner": "GitHubUser",
                "repo": "GitHubRepoName",
                "ref": "CommitHash",
                "path": "/path/to/dependency"
            }
        }
    }
}

Nota

Per le dipendenze GitHub, ref fa riferimento a un GitHub refspec. consiglia di usare sempre un hash di commit in modo che sia possibile basarsi su una versione specifica della dipendenza.

File manifesto del progetto esterno

Se il progetto esterno Q# viene pubblicato in un repository di GitHub pubblico, è necessario aggiungere la proprietà files al file manifesto del progetto esterno, inclusi tutti i file usati dal progetto.

{
    "author": "Microsoft",
    "license": "MIT",
    "files": [ "src/MyMathFunctions.qs", "src/Strings/MyStringFunctions.qs" ]
}

La proprietà è facoltativa per un progetto esterno importato tramite un'importazione basata su filepath locale. La proprietà files è necessaria solo per i progetti pubblicati in GitHub.

Usare l'istruzione

Per rendere accessibili le funzioni e le operazioni in un progetto esterno per chiamare i progetti, usare l'istruzione . È possibile esportare qualsiasi o tutti i callable nel file. Non è possibile usare la sintassi con wildcard, pertanto è necessario specificare ogni funzione da esportare.

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;

Usare l'istruzione

Per rendere disponibili gli elementi da una dipendenza esterna, usare le istruzioni dal programma chiamante. L'istruzione utilizza lo spazio dei nomi che definisci per la dipendenza nel file manifest.

Si consideri ad esempio la dipendenza nel file manifesto seguente:

{
    "author": "Microsoft",
    "license": "MIT",
    "dependencies": {
        "MyMathFunctions": {
            "path": "/path/to/project/folder/on/disk"
        }
    }
}

Importare le funzioni richiamabili con il codice seguente:

import MyMathFunctions.MyFunction;  // imports "MyFunction()" from the namespace

...

L'istruzione supporta anche la sintassi wild card e gli alias.

// 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; 

Esempio di progetto esterno

Per questo esempio, utilizzare lo stesso programma di teletrasporto dell'esempio precedente, ma separare il programma chiamante e le funzioni chiamabili in progetti diversi.

  1. Creare due cartelle nell'unità locale, ad esempio e .

  2. Creare un progetto in ogni cartella. Per informazioni dettagliate, vedere la procedura descritta in Come creare un progetto.

  3. In , il programma chiamante, copia il codice seguente nel file di manifest, ma modifica il percorso secondo le necessità per :

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. In copiare il codice seguente in :

    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);
        }
    }   
    
  5. In copiare il codice seguente in :

        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

    Non è necessario esportare l'operazione se il tuo programma non la chiama direttamente. L'operazione è già accessibile dall'operazione perché si trova nell'ambito locale di .

  6. Per eseguire il programma, aprire in e scegliere Esegui.

Progetti e namespace impliciti

Nei progetti, se non si specifica uno spazio dei nomi in un programma, il compilatore usa il nome file come spazio dei nomi. Quindi, quando si fa riferimento a un oggetto chiamabile da una dipendenza esterna, si usa la sintassi . Tuttavia, se il file è denominato , il compilatore presuppone che lo spazio dei nomi e la sintassi chiamante sia . Ad esempio: .

Poiché potrebbero essere presenti più file di progetto, è necessario tenere conto della sintassi corretta quando si fa riferimento a oggetti chiamabili. Si consideri, ad esempio, un progetto con la struttura di file seguente:

  • /Src
    • Main.qs
    • MathFunctions.qs

Il codice seguente effettua chiamate alla dipendenza esterna:

import MyTeleportLib.MyFunction;        // "Main" namespace is implied

import MyTeleportLib.MathFunctions.MyFunction;   // "Math" namespace must be explicit 

Per ulteriori informazioni sul comportamento dei namespace, vedere Namespace utente.