Projecten en aangepaste bibliotheken maken en beheren Q#

In dit artikel leert u hoe u projecten maakt, beheert en deelt Q# . Een Q# project is een mapstructuur met meerdere Q# bestanden die toegang hebben tot elkaars bewerkingen en functies. Projecten helpen u uw broncode logisch te ordenen. U kunt projecten ook gebruiken als aangepaste bibliotheken waartoe u toegang hebt vanuit externe bronnen.

Vereisten

Als u Python-programma's wilt uitvoeren, hebt u ook het volgende nodig:

  • Een Python-omgeving waarop Python en Pip zijn geïnstalleerd.

  • De qdkPython bibliotheek met de azure extra.

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

Hoe Q# projecten werken

Een Q# project bevat een manifestbestand met de Q# naam qsharp.jsonen een of meer .qs bestanden .qsc in een opgegeven mapstructuur. U kunt een Q# project handmatig of rechtstreeks maken in VS Code.

Wanneer u een .qs of .qsc bestand opent in VS Code, zoekt de compiler in de omringende mappenhiërarchie naar het manifestbestand en bepaalt de reikwijdte van het project. Als de compiler geen manifestbestand vindt, werkt de compiler in één bestandsmodus.

Wanneer u de project_root instelt in een bestand Jupyter Notebook of Python, zoekt de compiler naar het manifestbestand in de map project_root.

Een extern Q#-project is een standaardproject Q# dat zich in een andere map of in een openbare GitHub opslagplaats bevindt en fungeert als een aangepaste bibliotheek. Een extern project maakt gebruik van export instructies voor het definiëren van de functies en bewerkingen die toegankelijk zijn voor externe programma's. Programma's definiëren het externe project als een afhankelijkheid in hun manifestbestand en gebruiken import instructies voor toegang tot de items in het externe project, zoals bewerkingen, functies, structs en naamruimten. Zie Projecten gebruiken als externe afhankelijkheden voor meer informatie.

Q# Een project definiëren

Een Q# project wordt gedefinieerd door de aanwezigheid van een qsharp.json manifestbestand en een src map, die beide zich in de hoofdmap van het project moeten bevinden. De src map bevat de Q# bronbestanden. Voor Q# programma's en externe projecten detecteert de Q# compiler automatisch de projectmap. Voor Python programma's en Jupyter Notebook bestanden moet u de projectmap Q# specificeren met een qsharp.init oproep. De mapstructuur voor een Q# project is echter hetzelfde voor alle typen programma's.

De mapstructuur en -hiërarchie voor een Q# project.

De projectmap voor Q# programma's definiëren

Wanneer u een .qs-bestand opent in VS Code, zoekt de Q#-compiler omhoog in de mapstructuur naar een manifestbestand. Als de compiler een manifestbestand vindt, bevat de compiler alle Q# bestanden in de map en de /src bijbehorende submappen. De items die in elk bestand zijn gedefinieerd, worden beschikbaar voor alle andere bestanden in het project.

Denk bijvoorbeeld aan de volgende mapstructuur:

  • Teleportation_project
    • qsharp.json
    • Src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Wanneer u het bestand /src/TeleportOperation/PrepareState/PrepareStateLib.qsopent, doet de Q# compiler het volgende:

  1. /src/TeleportOperation/PrepareState/Controleert op qsharp.json .
  2. /src/TeleportOperationControleert op qsharp.json .
  3. /srcControleert op qsharp.json .
  4. /Teleportation_project Controleert qsharp.json en vindt het bestand.
  5. /Teleportation_project Stelt de hoofdmap van het project in en bevat alle .qs bestanden onder .qsc de /src map in het project. Als het manifestbestand.

Notitie

Als u expliciete verwijzingen naar .qs en .qsc bestandspaden opneemt in qsharp.json, dan laadt de compiler deze bestanden en doorloopt het automatische detectieproces niet. Expliciete bestandspadverwijzingen zijn alleen nodig wanneer u een bibliotheek definieert die kan worden geladen vanuit een Git-verwijzing.

Een manifestbestand maken

Een manifestbestand is een JSON-bestand genaamd qsharp.json dat optionele author, license, en lints velden kan bevatten. Het minimaal levensvatbare manifestbestand is de tekenreeks {}. Wanneer u een Q# project in VS Code maakt, wordt er een minimaal manifestbestand voor u gegenereerd.

{}

Voorbeelden van manifestbestanden

In de volgende voorbeelden ziet u hoe manifestbestanden het bereik van uw Q# project definiëren.

  • In dit voorbeeld author is dit het enige opgegeven veld, dus alle .qs bestanden in deze map en de bijbehorende submappen zijn opgenomen in het Q# project.

    {
        "author":"Microsoft"
    }
    
  • Binnen een Q# project kunt u ook het manifestbestand gebruiken om de VS CodeQ# Linter-instellingen af te stemmen. Standaard zijn de drie Linter-regels:

    • needlessParens: standaard = allow

    • divisionByZero: standaard = warn

    • redundantSemicolons: standaard = warn

      U kunt elke regel in het manifestbestand instellen op allow, warnof error. Voorbeeld:

      {
          "author":"Microsoft",
          "lints": [
              {
                "lint": "needlessParens",
                "level": "allow"
              },
              {
                "lint": "redundantSemicolons",
                "level": "warn"
              },
              {
                "lint": "divisionByZero",
                "level": "error"
              }
            ]
      }
      
  • U kunt het manifestbestand ook gebruiken om een extern Q# project te definiëren als een afhankelijkheid en externe toegang tot bewerkingen en functies in dat externe project. Zie Projecten gebruiken als externe afhankelijkheden voor meer informatie.

Q# projectvereisten en -eigenschappen

De volgende vereisten en configuraties zijn van toepassing op alle Q# projecten.

  • Alle .qs bestanden die u in het project wilt opnemen, moeten zich onder een map bevinden met de naam src, die zich in de hoofdmap van het Q# project moet bevinden. Wanneer u een Q# project in VS Code maakt, wordt de /src map automatisch gemaakt.

  • Het manifestbestand moet zich op hetzelfde niveau bevinden als de src map. Wanneer u een project in VS Code maakt, wordt er automatisch een minimaal manifestbestand gemaakt.

  • Gebruik import instructies om te verwijzen naar bewerkingen en functies van andere bestanden in het project.

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

    U kunt ze ook afzonderlijk verwijzen naar de naamruimte.

    MyMathLib.Multiply(x,y); 
    

Alleen voor Q# projecten

  • U kunt een invoerpuntbewerking definiëren in slechts één .qs bestand in een Q# project. Dit is standaard de Main() bewerking.
  • U moet het bestand met de definitie van het .qs toegangspunt onder het manifestbestand plaatsen op projectmapniveau.
  • Alle bewerkingen en functies in het Q# project die vanuit een .qs weergave zijn opgeslagen in de cache, worden weergegeven in voorspellende tekst in VS Code.
  • Als de naamruimte voor een geselecteerde bewerking of functie nog niet is geïmporteerd, voegt VS Code automatisch de benodigde import instructie toe.

Hoe maak je een Q#-project

Voer de volgende stappen uit om een Q# project te maken:

  1. Ga in de VS Code Verkenner naar de map die u wilt gebruiken als hoofdmap voor het Q# project.

  2. Open het menu Beeld en kies Opdrachtpalet.

  3. Voer QDK: Maak projectQ# aan. VS Code maakt een minimaal manifestbestand in de map en voegt een /src map toe met een Main.qs sjabloonbestand.

  4. Bewerk het manifestbestand voor uw project. Zie voorbeelden van manifestbestanden.

  5. Voeg uw Q# bronbestanden toe en organiseer deze onder de /src map.

  6. Als u het project Q# opent vanuit een Python-programma of Jupyter Notebook, stelt u het pad naar de map root in met qsharp.init. In dit voorbeeld wordt ervan uitgegaan dat uw programma zich in de /src map van het Q# project bevindt:

    qsharp.init(project_root = '../Teleportation_project')
    
  7. Als u alleen Q#-bestanden in VS Code gebruikt, zoekt de compiler naar een manifestbestand wanneer u een Q#-bestand opent en bepaalt de hoofdmap van het project. Vervolgens scant de compiler /src en de subdirectories daarvan voor .qs- en .qsc-bestanden.

Notitie

U kunt in plaats daarvan handmatig het manifestbestand en de /src map maken.

Voorbeeldproject

Dit kwantumteleportatieprogramma is een voorbeeld van een Q# project dat wordt uitgevoerd op de lokale simulator in VS Code. Als u het programma wilt uitvoeren op Azure Quantum hardware- of simulators van derden, raadpleegt u Get gestart met Q#-programma's en VS Code voor stappen om uw programma te compileren en verbinding te maken met uw Azure Quantum-werkruimte.

Dit voorbeeld heeft de volgende mapstructuur:

  • Teleportation_project
    • qsharp.json
    • Src
      • Main.qs
      • TeleportOperations
        • TeleportLib.qs
        • PrepareState
          • PrepareStateLib.qs

Het manifestbestand bevat de auteurs - en licentievelden :

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

Q# bronbestanden

Het hoofdbestand Main.qs bevat het toegangspunt en verwijst naar de TeleportOperations.TeleportLib naamruimte van 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);
        }
    }

Het TeleportLib.qs bestand definieert de Teleport bewerking en roept de PrepareBellPair bewerking aan vanuit het PrepareStateLib.qs bestand.

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

Het PrepareStateLib.qs bestand bevat een standaard herbruikbare operatie om een Bell-paar te maken.

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

De programma's uitvoeren

Kies het tabblad voor de omgeving waarin u uw programma uitvoert.

Als u dit programma wilt uitvoeren, opent u het Main.qs bestand in VS Code en kiest u Uitvoeren.

Projecten configureren Q# als externe afhankelijkheden

U kunt projecten configureren Q# als een externe afhankelijkheid voor andere projecten, vergelijkbaar met een bibliotheek, om functies en bewerkingen in het externe Q# project beschikbaar te maken voor andere Q# projecten. Een externe afhankelijkheid kan zich op een netwerkschijf bevinden of worden gepubliceerd in een openbare GitHub-opslagplaats.

Als u een Q# project als een externe afhankelijkheid wilt gebruiken, moet u het volgende doen:

  • Voeg het externe project toe als een afhankelijkheid in het manifestbestand van het aanroepende project.
  • Als het externe project wordt gepubliceerd naar GitHub, voegt u de eigenschap files toe aan het manifestbestand van het externe project.
  • Voeg export statements toe aan het externe project.
  • Voeg import statements toe aan het aanroepende project.

De manifestbestanden configureren

Externe Q#-projecten kunnen zich bevinden op een lokale of netwerkstationshare of u kunt ze publiceren naar een openbare GitHub opslagplaats.

Het manifestbestand van het aanroepende project

Als u een afhankelijkheid wilt toevoegen aan een extern project op een netwerkschijf, definieert u de afhankelijkheid in het manifest-bestand van het aanroepende project.

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

In het voorgaande manifestbestand MyDependency is een door de gebruiker gedefinieerde tekenreeks die de naamruimte identificeert wanneer u een bewerking aanroept. Als u bijvoorbeeld een afhankelijkheid met de naam MyMathFunctionsmaakt, kunt u een functie aanroepen vanuit die afhankelijkheid met MyMathFunctions.MyFunction().

Als u een afhankelijkheid wilt toevoegen aan een project dat is gepubliceerd naar een openbare GitHub opslagplaats, gebruikt u het volgende voorbeeldmanifestbestand:

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

Notitie

Voor GitHub afhankelijkheden verwijst ref naar een GitHub refspec. Microsoft raadt u aan altijd een commit-hash te gebruiken, zodat u kunt vertrouwen op een specifieke versie van uw afhankelijkheid.

Het manifestbestand van het externe project

Als uw externe Q#-project wordt gepubliceerd naar een openbare GitHub opslagplaats, moet u de eigenschap files toevoegen aan het manifestbestand van het externe project, inclusief alle bestanden die het project gebruikt.

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

De files eigenschap is optioneel voor een extern project dat u importeert via "path" met een lokaal bestandsimportpad. De eigenschap files is alleen vereist voor projecten die zijn gepubliceerd naar GitHub.

Gebruik de export instructie

Gebruik de export instructie om functies en bewerkingen in een extern project toegankelijk te maken voor het aanroepen van projecten. U kunt enkele of alle aanroepbare items in het bestand exporteren. U kunt geen jokertekensyntaxis gebruiken, dus u moet elk aanroepbaar opgeven dat u wilt exporteren.

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;

Gebruik de import instructie

Als u items van een externe afhankelijkheid beschikbaar wilt maken, gebruikt u de statements import van het aanroepende programma. De import instructie maakt gebruik van de naamruimte die u definieert voor de afhankelijkheid in het manifestbestand.

Denk bijvoorbeeld aan de afhankelijkheid in het volgende manifestbestand:

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

Importeer de aanroepbare items met de volgende code:

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

...

De import instructie ondersteunt ook wildcardsyntaxis en aliassen.

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

Voorbeeld van extern project

In dit voorbeeld gebruikt u hetzelfde teleportatieprogramma als in het vorige voorbeeld, maar scheidt u het belprogramma en de aanroepbare bestanden in verschillende projecten.

  1. Maak twee mappen op uw lokale schijf, bijvoorbeeld Project_A en Project_B.

  2. Maak een Q# project in elke map. Zie de stappen in Een project maken Q#voor meer informatie.

  3. Kopieer Project_Ain het aanroepende programma de volgende code naar het manifestbestand, maar bewerk het pad indien nodig voor Project_B:

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. Kopieer Project_Ade volgende code in 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);
        }
    }   
    
  5. Kopieer Project_Bde volgende code in 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
    

    Notitie

    U hoeft de PrepareBellPair-bewerking niet te exporteren als uw programma in Project_A die bewerking niet direct aanroept. De PrepareBellPair bewerking is al toegankelijk voor de Teleport bewerking omdat PrepareBellPair deze zich in het lokale bereik van Project_Bbevindt.

  6. Open /Project_A/Main.qs in VS Code en kies Uitvoeren om het programma uit te voeren.

Projecten en impliciete naamruimten

In Q# projecten, als u geen naamruimte in een .qs programma opgeeft, gebruikt de compiler de bestandsnaam als de naamruimte. Vervolgens, wanneer u naar een aanroepbare vanuit een externe afhankelijkheid verwijst, gebruikt u de syntaxis <dependencyName>.<namespace>.<callable>. Als het bestand echter de naam Main.qs heeft, gaat de compiler ervan uit dat de naamruimte en de aanroepende syntaxis <dependencyName>.<callable> is. Bijvoorbeeld: import MyTeleportLib.Teleport.

Omdat u mogelijk meerdere projectbestanden hebt, moet u rekening houden met de juiste syntaxis wanneer u verwijst naar aanroepbare bestanden. Denk bijvoorbeeld aan een project met de volgende bestandsstructuur:

  • /Src
    • Main.qs
    • MathFunctions.qs

Met de volgende code worden aanroepen naar de externe afhankelijkheid uitgevoerd:

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

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

Zie Gebruikersnaamruimten voor meer informatie over het gedrag van de naamruimte.