Compartir a través de


Creación y administración de Q# proyectos y bibliotecas personalizadas

En este artículo, aprenderá a crear, administrar y compartir Q# proyectos. Q# los proyectos son estructuras de carpetas con varios Q# archivos que pueden tener acceso a las operaciones y funciones del otro. Los proyectos son útiles para organizar lógicamente el código fuente. También puede usar proyectos como bibliotecas personalizadas a las que se puede acceder desde orígenes externos.

Requisitos previos

Para ejecutar programas de Python, también necesita lo siguiente:

  • Un entorno de Python con Python y Pip instalados.
  • Azure Quantum qsharp y azure-quantum los paquetes.

Cómo Q# funcionan los proyectos

Un Q# proyecto contiene un Q# archivo de manifiesto, denominado qsharp.json y uno o varios archivos *.qs en una estructura de carpetas especificada. Cuando un usuario abre un archivo *.qs en VS Code o establece en project_root un archivo de Jupyter Notebook o Python, el compilador busca la jerarquía de carpetas circundantes para el archivo de manifiesto y determina el ámbito del proyecto. Si no se encuentra ningún archivo de manifiesto, el compilador funciona en un modo de archivo único. Puede crear un Q# proyecto manualmente o directamente en VS Code.

Un proyecto externo Q# es un proyecto estándar Q# que reside en otro directorio o en un repositorio público de GitHub y actúa como una biblioteca personalizada. Un proyecto externo usa export instrucciones para definir a qué funciones y operaciones se puede acceder mediante programas externos. Los programas definen el proyecto externo como una dependencia en su archivo de manifiesto y usan import instrucciones para tener acceso a los elementos (operaciones, funciones, estructuras y espacios de nombres) en el proyecto externo. Para obtener más información, consulte Uso de proyectos como dependencias externas.

Definición de un Q# proyecto

Un Q# proyecto se define mediante la presencia de un archivo de manifiesto, denominado qsharp.json, y una carpeta src (que contiene los Q# archivos de origen), ambos deben estar en la carpeta raíz del proyecto. En el caso Q# de programas y proyectos externos, el Q# compilador detecta automáticamente la carpeta del proyecto. Para programas de Python y Cuadernos de Jupyter Notebook, debe especificar la carpeta del Q# proyecto con una qsharp.init llamada. Sin embargo, la estructura de carpetas de un Q# proyecto sigue siendo la misma para todos los tipos de programas.

Estructura y jerarquía de carpetas de un Q# proyecto.

Definición de la carpeta del proyecto (Q# programas)

Cuando se abre un archivo *.qs en VS Code, el Q# compilador busca hacia arriba en la estructura de carpetas un archivo de manifiesto. Si encuentra un archivo de manifiesto, el compilador incluye todos los Q# archivos en el directorio /src o cualquiera de sus subdirectorios. Los elementos de cada archivo están disponibles para todos los demás archivos del proyecto.

Por ejemplo, dada esta estructura de carpetas:

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

al abrir el archivo /src/TeleportOperation/PrepareState/PrepareStateLib.qs, el Q# compilador:

  1. Comprueba /src/TeleportOperation/PrepareState/ para qsharp.json.
  2. Comprueba /src/TeleportOperation para qsharp.json.
  3. Comprueba /src para qsharp.json.
  4. Comprueba / si hay qsharp.json.
  5. Establece / como directorio raíz del proyecto e incluye todos los archivos *.qs en la raíz del proyecto, según la configuración del archivo de manifiesto.

Crear un archivo de manifiesto

Un archivo de manifiesto es un archivo de .json simple denominado qsharp.json que, opcionalmente, puede incluir campos de autor, licencia y lints . El archivo de manifiesto mínimo viable es la cadena {}. Al crear un Q# proyecto en VS Code, se crea automáticamente un archivo de manifiesto mínimo.

{}

Ejemplos de archivos de manifiesto

A continuación se muestran algunos ejemplos de cómo los archivos de manifiesto pueden definir el ámbito del Q# proyecto.

  • En este ejemplo, author es el único campo especificado y, por tanto, todos los archivos *.qs de este directorio y todos sus subdirectorios se incluyen en el Q# proyecto.

    {
        "author":"Microsoft",
        "license": "MIT"
    }
    
  • Dentro de un Q# proyecto, también puede usar el archivo de manifiesto para ajustar la configuración de LINTER de VS Code Q# . De forma predeterminada, las tres reglas de Linter son:

    • needlessParens: valor predeterminado = allow
    • divisionByZero: valor predeterminado = warn
    • redundantSemicolons: valor predeterminado = warn

    Con el archivo de manifiesto, puede establecer cada regla allowen , warno error, por ejemplo.

    {
        "author":"Microsoft",
        "lints": [
            {
              "lint": "needlessParens",
              "level": "allow"
            },
            {
              "lint": "redundantSemicolons",
              "level": "warn"
            },
            {
              "lint": "divisionByZero",
              "level": "error"
            }
          ]
    }
    
  • También puede usar el archivo de manifiesto para definir un proyecto externo Q# como una dependencia y acceder de forma remota a las operaciones y funciones de ese proyecto externo. Para obtener más información, consulte Uso de proyectos como dependencias externas.

Q# requisitos y propiedades del proyecto

Los siguientes requisitos y configuraciones se aplican a todos los Q# proyectos.

  • Todos los archivos *.qs que desea incluir en el proyecto deben estar en una carpeta denominada src, que debe estar en la carpeta raíz de Q#. Al crear un Q# proyecto en VS Code, la /src carpeta se crea automáticamente.

  • El archivo de manifiesto debe estar en el mismo nivel que la carpeta src . Al crear un Q# proyecto en VS Code, se crea automáticamente un archivo mínimo.

  • Use import instrucciones para hacer referencia a operaciones y funciones de otros archivos del proyecto.

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

    o hacer referencia a ellos individualmente con el espacio de nombres

    MyMathLib.Multiply(x,y);  
    

Solo para Q# proyectos

  • Solo un archivo *.qs de un Q# proyecto puede tener un punto de entrada definido, definido por una sola Main() operación.
  • El archivo *.qs con la definición del punto de entrada se puede encontrar en cualquier nivel por debajo del archivo de manifiesto.
  • Cualquier operación o función que se almacena en caché desde un archivo *.qs en cualquier parte del Q# proyecto se muestra en texto predictivo en VS Code.
  • Si aún no se importa el espacio de nombres de una operación o función seleccionada, VS Code agrega automáticamente la instrucción necesaria import .

Pasos para crear un Q# proyecto

Estos pasos se aplican a todos los Q# proyectos.

  1. En el explorador de archivos de VS Code, haga clic con el botón derecho en la carpeta que desea usar para la carpeta raíz del Q# proyecto y seleccione Crear Q# proyecto, o abra la carpeta y seleccione Ver > paleta >Q#de comandos: Crear un Q# proyecto....

  2. VS Code crea un archivo de manifiesto mínimo en la carpeta y agrega una /src carpeta con un Main.qs archivo de plantilla.

  3. Edite el archivo de manifiesto según sea necesario. Consulte Ejemplos de archivos de manifiesto.

  4. Agregue y organice los Q# archivos de origen en la /src carpeta .

  5. Si accede al Q# proyecto desde un programa de Python o Jupyter Notebook, establezca la ruta de acceso de la carpeta raíz mediante qsharp.init. En este ejemplo se supone que el programa está en la carpeta /src del Q# proyecto:

    qsharp.init(project_root = '../Teleportation_project')
    
  6. Si solo Q# usa archivos en VS Code, al abrir un Q# archivo, el compilador busca un archivo de manifiesto, determina la carpeta raíz del proyecto y, a continuación, examina la subcarpeta de los archivos *.qs.

Nota:

También puede crear manualmente el archivo de manifiesto y la carpeta en el /src paso 2.

Proyecto de ejemplo

Este programa de teletransportación cuántica es un ejemplo de un Q# proyecto basado en la estructura de una sola carpeta mostrada anteriormente y se ejecuta en el simulador local en VS Code. Para ejecutar el programa en hardware de Azure Quantum o simuladores de terceros, consulte Introducción a Q# los programas y VSCode para ver los pasos para compilar el programa y conectarse al área de trabajo de Azure.

En el ejemplo se usa esta estructura de directorios:

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

El archivo de manifiesto contiene los campos de autor y licencia :

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

Q# archivos de origen

El archivo principal, Main.qs, contiene el punto de entrada y hace referencia al TeleportOperations.TeleportLib espacio de nombres 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 la Teleport() operación y llama a la PrepareBellPair() operación desde 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);
    }

El archivo PrepareStateLib.qs contiene una operación reutilizable estándar para crear un par bell.

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

Ejecución de los programas

Seleccione la pestaña del entorno en el que ejecuta el programa.

Para ejecutar este programa, abra el archivo Main.qs en VS Code y seleccione Ejecutar.

Configuración de Q# proyectos como dependencias externas

Un Q# proyecto también se puede configurar como una dependencia externa para otros proyectos, actuando de forma muy similar a una biblioteca, donde las funciones y las operaciones del proyecto externo Q# están disponibles para varios Q# proyectos. Una dependencia externa puede residir en un recurso compartido de unidades o publicarse en un repositorio público de GitHub.

Para usar un Q# proyecto como dependencia externa, debe:

  • Agregue el proyecto externo como dependencia en el archivo de manifiesto del proyecto que llama.
  • Si el proyecto externo se publica en GitHub, agregue la propiedad "files" al archivo de manifiesto del proyecto externo.
  • Agregue instrucciones export al proyecto externo.
  • Agregue instrucciones import al proyecto que llama.

Configuración de los archivos de manifiesto

Los proyectos externos Q# pueden residir en un recurso compartido de unidad de red o local, o publicarse en un repositorio público de GitHub.

El archivo de manifiesto del proyecto que llama

Para agregar una dependencia a un proyecto externo en un recurso compartido de unidad, defina la dependencia en el archivo de manifiesto del proyecto que llama.

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

donde "MyDependency" es una cadena definida por el usuario que identifica el espacio de nombres al llamar a una operación. Por ejemplo, si crea una dependencia denominada "MyMathFunctions", llamaría a una función desde esa dependencia con MyMathFunctions.MyFunction().

Para agregar una dependencia a un proyecto publicado en un repositorio público de GitHub

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

Nota:

En el caso de las dependencias de GitHub, "ref" hace referencia a una especificación refspec de GitHub. Microsoft recomienda usar siempre un hash de confirmación, por lo que puede confiar en una versión específica de la dependencia.

El archivo de manifiesto del proyecto externo

Si el proyecto externo Q# se publica en un repositorio público de GitHub, debe agregar la propiedad files al archivo de manifiesto del proyecto externo, incluidos todos los archivos usados en el proyecto.

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

La propiedad "files" es opcional para un proyecto externo que se importa a través "path" de (es decir, una importación basada en filepath local). Solo es necesario para los proyectos publicados en GitHub.

Uso de la instrucción export

Para que las funciones y las operaciones de un proyecto externo sean accesibles para llamar a proyectos, use la export instrucción . Puede exportar cualquiera o todos los elementos invocables en el archivo. No se admite la sintaxis de caracteres comodín, debe especificar cada al que se pueda llamar para exportar.

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;             

Uso de la instrucción import

Desde el programa de llamada, se usan import instrucciones para que los elementos de una dependencia externa estén disponibles. import Las instrucciones usan el espacio de nombres definido para la dependencia en el archivo de manifiesto. Por ejemplo, para esta dependencia

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

se importan los invocables como

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

La import instrucción también admite la sintaxis y los alias de comodín.

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

La instrucción usada open actualmente en Q#, que se usa para hacer referencia a bibliotecas y espacios de nombres, todavía se admite, pero finalmente quedará en desuso. Mientras tanto, puede actualizar opcionalmente los archivos actuales para usar la import instrucción . Por ejemplo, open Microsoft.Quantum.Diagnostics; se puede reemplazar por import Microsoft.Quantum.Diagnostics.*;. Tenga en cuenta también que, al usar la import instrucción con las bibliotecas estándar Q# , puede acortar el espacio de nombres raíz a Std. Por ejemplo, import Microsoft.Quantum.Diagnostics.*; puede escribirse como import Std.Diagnostics.*;.

Proyecto externo de ejemplo

En este ejemplo, usará el mismo programa de teletransportación que el ejemplo anterior, pero separará el programa de llamada y los invocables en proyectos diferentes.

  1. Cree dos carpetas en la unidad local, por ejemplo, "Project_A" y "Project_B".

  2. Cree un Q# proyecto en cada carpeta siguiendo los pasos descritos en Pasos para crear un Q# proyecto.

  3. En Project_A, el programa que llama, copie el código siguiente en el archivo de manifiesto y edite la ruta de acceso según sea necesario para Project_B

    {
      "author": "Microsoft",
      "license": "MIT",
      "dependencies": {
        "MyTeleportLib": {
          "path": "/Project_B" 
          }
        }
      }    
    
  4. En Project_A, copie el código siguiente en 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. En Project_B, copie el código siguiente en 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:

    Tenga en cuenta que no es necesario exportar la PrepareBellPair operación porque no se llama directamente desde el programa en Project_A. Dado que está en el ámbito local de Project_B, la operación ya es accesible Teleport .

  6. Para ejecutar el programa, abra /Project_A/Main.qs en VS Code y seleccione Ejecutar.

Proyectos y espacios de nombres implícitos

En Q# los proyectos, si no se especifica un espacio de nombres en un programa *.qs, el compilador usa el nombre de archivo como espacio de nombres. Al hacer referencia a un invocable desde una dependencia externa, se usa la sintaxis <dependencyName>.<espacio de nombres>.<invocable>. Sin embargo, si el archivo se denomina "Main.qs", el compilador asume el espacio de nombres y la sintaxis de llamada es <dependencyName>.<invocable>, como en el ejemplo anterior, import MyTeleportLib.Teleport.

Dado que no es raro tener varios archivos de proyecto, debe tener en cuenta la sintaxis correcta al hacer referencia a los invocables. Por ejemplo, en un proyecto con la siguiente estructura de archivos

  • src/
    • Main.qs
    • MathFunctions.qs

Las llamadas a la dependencia externa serían

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

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

Para obtener más información sobre el comportamiento del espacio de nombres, consulte Espacios de nombres de usuario.