Estruturas de Dados e ModelaçãoData Structures and Modeling

Estruturas clássicas de dadosClassical Data Structures

Juntamente com tipos definidos pelo utilizador para representar conceitos quânticos, o cânone também fornece operações, funções e tipos para trabalhar com dados clássicos utilizados no controlo de sistemas quânticos.Along with user-defined types for representing quantum concepts, the canon also provides operations, functions, and types for working with classical data used in the control of quantum systems. Por exemplo, a Reversed function função toma uma matriz como entrada e devolve a mesma matriz em ordem inversa.For instance, the Reversed function function takes an array as input and returns the same array in reverse order. Isto pode então ser usado numa matriz de tipo para evitar ter de Qubit[] aplicar portões desnecessários de $\operatorname{SWAP}$ ao converter entre representações quânticas de inteiros.This can then be used on an array of type Qubit[] to avoid having to apply unnecessary $\operatorname{SWAP}$ gates when converting between quantum representations of integers. Da mesma forma, vimos na secção anterior que os tipos do formulário (Int, Int -> T) podem ser úteis para representar coleções de acesso aleatório, pelo que a LookupFunction function função fornece uma maneira conveniente de construir tais tipos a partir de tipos de matrizes.Similarly, we saw in the previous section that types of the form (Int, Int -> T) can be useful for representing random access collections, so the LookupFunction function function provides a convenient way of constructing such types from array types.

ParesPairs

O cânone suporta a notação de estilo funcional para pares, complementando o acesso a tuples por desconstrução:The canon supports functional-style notation for pairs, complementing accessing tuples by deconstruction:

let pair = (PauliZ, register); // type (Pauli, Qubit[])
ApplyToEach(H, Snd(pair)); // No need to deconstruct to access the register.

MatrizesArrays

O cânone fornece várias funções para manipular matrizes.The canon provides several functions for manipulating arrays. Estas funções são de tipo parametrizado, e assim podem ser usadas com matrizes de qualquer Q# tipo.These functions are type-parameterized, and thus can be used with arrays of any Q# type. Por exemplo, a Reversed function função devolve uma nova matriz cujos elementos estão em ordem inversa a partir da sua entrada.For instance, the Reversed function function returns a new array whose elements are in reverse order from its input. Isto pode ser usado para alterar a forma como um registo quântico é representado ao chamar operações:This can be used to change how a quantum register is represented when calling operations:

let leRegister = LittleEndian(register);
// QFT expects a BigEndian, so we can reverse before calling.
QFT(BigEndian(Reversed(leRegister!)));
// This is how the LittleEndianAsBigEndian function is implemented:
QFT(LittleEndianAsBigEndian(leRegister));

Da mesma forma, a Subarray function função pode ser usada para reencomendar ou tomar subconjuntos dos elementos de uma matriz:Similarly, the Subarray function function can be used to reorder or take subsets of the elements of an array:

// Applies H to qubits 2 and 5.
ApplyToEach(H, Subarray([2, 5], register));

Quando combinado com o controlo de fluxo, funções de manipulação de matrizes tais como Zipped function podem fornecer uma forma poderosa de expressar programas quânticos:When combined with flow control, array manipulation functions such as Zipped function can provide a powerful way to express quantum programs:

// Applies X₃ Y₁ Z₇ to a register of any size.
ApplyToEach(
    ApplyPauli(_, register),
    Map(
        EmbedPauli(_, _, Length(register)),
        Zipped([PauliX, PauliY, PauliZ], [3, 1, 7])
    )
);

OráculosOracles

Na fase de estimativa e amplificação da literatura o conceito de um oráculo aparece frequentemente.In the phase estimation and amplitude amplification literature the concept of an oracle appears frequently. Aqui o termo oráculo refere-se a uma blackbox subbroutina quântica que age sobre um conjunto de qubits e devolve a resposta como uma fase.Here the term oracle refers to a blackbox quantum subroutine that acts upon a set of qubits and returns the answer as a phase. Esta sub-rotina pode muitas vezes ser considerada como uma entrada para um algoritmo quântico que aceita o oráculo, além de alguns outros parâmetros, e aplica uma série de operações quânticas e tratando uma chamada para esta subbroutina quântica como se fosse um portão fundamental.This subroutine often can be thought of as an input to a quantum algorithm that accepts the oracle, in addition to some other parameters, and applies a series of quantum operations and treating a call to this quantum subroutine as if it were a fundamental gate. Obviamente, para implementar o algoritmo maior, deve ser fornecida uma decomposição concreta do oráculo em portões fundamentais, mas tal decomposição não é necessária para entender o algoritmo que chama o oráculo.Obviously, in order to actually implement the larger algorithm a concrete decomposition of the oracle into fundamental gates must be provided but such a decomposition is not needed in order to understand the algorithm that calls the oracle. Em Q# , esta abstração é representada por usar que as operações são valores de primeira classe, de modo que as operações podem ser passadas para implementações de algoritmos quânticos de forma de caixa preta.In Q#, this abstraction is represented by using that operations are first-class values, such that operations can be passed to implementations of quantum algorithms in a black-box manner. Além disso, os tipos definidos pelo utilizador são utilizados para rotular as diferentes representações do oráculo de uma forma tipo segura, dificultando a conflação acidental de diferentes tipos de operações de caixa preta.Moreover, user-defined types are used to label the different oracle representations in a type-safe way, making it difficult to accidentally conflate different kinds of black box operations.

Tais oráculos aparecem em vários contextos diferentes, incluindo exemplos famosos como a pesquisa de Grover e algoritmos de simulação quântica.Such oracles appear in a number of different contexts, including famous examples such as Grover's search and quantum simulation algorithms. Aqui focamo-nos nos oráculos necessários para apenas duas aplicações: amplificação de amplitude e estimativa de fase.Here we focus on the oracles needed for just two applications: amplitude amplification and phase estimation. Primeiro discutiremos os oráculos de amplificação de amplitude antes de procedermos à estimativa de fase.We will first discuss amplitude amplification oracles before proceeding to phase estimation.

Oráculos de amplificação da amplitudeAmplitude Amplification Oracles

O algoritmo de amplificação da amplitude visa realizar uma rotação entre um estado inicial e um estado final, aplicando uma sequência de reflexões do estado.The amplitude amplification algorithm aims to perform a rotation between an initial state and a final state by applying a sequence of reflections of the state. Para que o algoritmo funcione, precisa de uma especificação de ambos os estados.In order for the algorithm to function, it needs a specification of both of these states. Estas especificações são dadas por dois oráculos.These specifications are given by two oracles. Estes oráculos funcionam quebrando as entradas em dois espaços, um subespaço "alvo" e um subespaço "inicial".These oracles work by breaking the inputs into two spaces, a "target" subspace and an "initial" subspace. Os oráculos identificam esses subespaços, à semelhança da forma como os operadores da Pauli identificam dois espaços, aplicando uma fase $\pm 1$ a estes espaços.The oracles identify such subspaces, similar to how Pauli operators identify two spaces, by applying a $\pm 1$ phase to these spaces. A principal diferença é que estes espaços não precisam de ser semi-espaços nesta aplicação.The main difference is that these spaces need not be half-spaces in this application. Note também que estes dois subespaços não são geralmente mutuamente exclusivos: haverá vetores que são membros de ambos os espaços.Also note that these two subspaces are not usually mutually exclusive: there will be vectors that are members of both spaces. Se isso não fosse verdade, então a amplificação da amplitude não teria qualquer efeito, por isso precisamos que o subespaço inicial tenha uma sobreposição não-zero com o subespaço alvo.If this were not true then amplitude amplification would have no effect so we need the initial subspace to have non-zero overlap with the target subspace.

Vamos denotar o primeiro oráculo que precisamos para que a amplificação da amplitude seja $P _ 0$, definida para ter a seguinte ação.We will denote the first oracle that we need for amplitude amplification to be $P_0$, defined to have the following action. Para todos os estados $\ket{x}$ no subespaço "inicial" $P _ 0 \ket{x} = -\ket{x}$ e para todos os estados $\ket{y}$ que não estão neste subespaço temos $P _ 0 \ket{y} = \ket{y}$.For all states $\ket{x}$ in the "initial" subspace $P_0 \ket{x} = -\ket{x}$ and for all states $\ket{y}$ that are not in this subspace we have $P_0 \ket{y} = \ket{y}$. O oráculo que marca o subespaço alvo, $P_1$, assume exatamente a mesma forma.The oracle that marks the target subspace, $P_1$, takes exactly the same form. Para todos os estados $\ket{x}$ no subespaço alvo (i.e., para todos os estados que gostaria que o algoritmo fosse despahá-lo), $P_1\ket{x} = -\ket{x}$.For all states $\ket{x}$ in the target subspace (i.e., for all states that you'd like the algorithm to output), $P_1\ket{x} = -\ket{x}$. Da mesma forma, para todos os estados $\ket{y}$ que não estão no subespaço alvo $P_1\ket{y} = \ket{y}$.Similarly, for all states $\ket{y}$ that are not in the target subspace $P_1\ket{y} = \ket{y}$. Estas duas reflexões são então combinadas para formar um operador que decreta um único passo de amplificação de amplitude, $Q = -P_0 P_1$, onde o sinal de menos geral só é importante a considerar em aplicações controladas.These two reflections are then combined to form an operator that enacts a single step of amplitude amplification, $Q = -P_0 P_1$, where the overall minus sign is only important to consider in controlled applications. A amplificação amplitude prossegue tomando um estado inicial, $\ket{\psi}$ que está no subespaço inicial e, em seguida, executa $\ket{\psi} \mapsto Q^m \ket{\psi}$.Amplitude amplification then proceeds by taking an initial state, $\ket{\psi}$ that is in the initial subspace and then performs $\ket{\psi} \mapsto Q^m \ket{\psi}$. A realização de tal iteração garante que se começar com um estado inicial que se sobreponha a $\sin^2 (\theta)$ com o espaço marcado, então depois de $m$ iterações esta sobreposição torna-se $\sin^2 ([2m + 1] \theta)$.Performing such an iteration guarantees that if one starts with an initial state that has overlap $\sin^2(\theta)$ with the marked space then after $m$ iterations this overlap becomes $\sin^2([2m + 1] \theta)$. Por isso, normalmente queremos escolher $m$ para ser um parâmetro gratuito de tal forma que $[2m+1]\theta = \pi/2$; no entanto, tais escolhas rígidas não são tão importantes para algumas formas de amplificação da amplitude, tais como amplificação da amplitude fixa do ponto.We therefore typically wish to choose $m$ to be a free parameter such that $[2m+1]\theta = \pi/2$; however, such rigid choices are not as important for some forms of amplitude amplification such as fixed point amplitude amplification. Este processo permite-nos preparar um estado no subespaço marcado utilizando quadraticamente menos consultas à função de marcação e à função de preparação do estado do que seria possível num dispositivo estritamente clássico.This process allows us to prepare a state in the marked subspace using quadratically fewer queries to the marking function and the state preparation function than would be possible on a strictly classical device. É por isso que a amplificação da amplitude é um importante bloco de construção para muitas aplicações de computação quântica.This is why amplitude amplification is a significant building block for many applications of quantum computing.

Para entender como usar o algoritmo, é útil fornecer um exemplo que dá uma construção dos oráculos.In order to understand how to use the algorithm, it is useful to provide an example that gives a construction of the oracles. Considere executar o algoritmo de Grover para pesquisas de base de dados nesta definição.Consider performing Grover's algorithm for database searches in this setting. Na pesquisa de Grover, o objetivo é transformar o estado $\ket{+}{{\otimes n} = H^{\otimes n} \ket {0} $ em um dos (potencialmente) muitos estados marcados.In Grover's search the goal is to transform the state $\ket{+}^{\otimes n} = H^{\otimes n} \ket{0}$ into one of (potentially) many marked states. Para simplificar ainda mais, vamos apenas olhar para o caso em que o único estado marcado é $\ket {0} $.To further simplify, let's just look at the case where the only marked state is $\ket{0}$. Em seguida, temos dois oráculos: um que apenas marca o estado inicial $\ket{+}^{\otimes n}$ com um sinal de menos e outro que marca o estado marcado $\ket {0} $ com um sinal de menos.Then we have design two oracles: one that only marks the initial state $\ket{+}^{\otimes n}$ with a minus sign and another that marks the marked state $\ket{0}$ with a minus sign. Este último portão pode ser implementado utilizando a seguinte operação de processo, utilizando as operações de fluxo de controlo no cânone:The latter gate can be implemented using the following process operation, by using the control flow operations in the canon:

operation ReflectAboutAllZeros(register : Qubit[]) : Unit 
is Adj + Ctl {

    // Apply $X$ gates to every qubit.
    ApplyToEach(X, register);

    // Apply an $n-1$ controlled $Z$-gate to the $n^{\text{th}}$ qubit.
    // This gate will lead to a sign flip if and only if every qubit is
    // $1$, which happens only if each of the qubits were $0$ before step 1.
    Controlled Z(Most(register), Tail(register));

    // Apply $X$ gates to every qubit.
    ApplyToEach(X, register);
}

Este oráculo é então um caso especial da RAll1 operation operação, que permite rodar por uma fase arbitrária em vez do caso de reflexão $\phi = \pi$.This oracle is then a special case of the RAll1 operation operation, which allows for rotating by an arbitrary phase instead of the reflection case $\phi = \pi$. Neste caso, RAll1 é semelhante à operação do R1 operation prelúdio, na medida em que gira cerca de $\ket{11\cdots1}$ em vez do estado de um único qubit $\ket {1} $.In this case, RAll1 is similar to the R1 operation prelude operation, in that it rotates about $\ket{11\cdots1}$ instead of the single-qubit state $\ket{1}$.

O oráculo que marca o subespaço inicial pode ser construído da mesma forma.The oracle that marks the initial subspace can be constructed similarly. Em pseudocódigo:In pseudocode:

  1. Aplique $H de portas a cada qubit.Apply $H$ gates to every qubit.
  2. Aplique $X de portais a cada qubit.Apply $X$ gates to every qubit.
  3. Aplique um $n-1$ controlado $Z$-gate no $n^{\text{th}} qubit.Apply an $n-1$ controlled $Z$-gate to the $n^{\text{th}}$ qubit.
  4. Aplique $X de portais a cada qubit.Apply $X$ gates to every qubit.
  5. Aplique $H de portas a cada qubit.Apply $H$ gates to every qubit.

Desta vez, demonstramos também a utilização ApplyWith operation em conjunto com a RAll1 operation operação acima discutida:This time, we also demonstrate using ApplyWith operation together with the RAll1 operation operation discussed above:

operation ReflectAboutInitial(register : Qubit[]) : Unit
is Adj + Ctl {
    ApplyWithCA(ApplyToEach(H, _), ApplyWith(ApplyToEach(X, _), RAll1(_, PI()), _), register);
}

Podemos então combinar estes dois oráculos para rodar entre os dois estados e transformar deterministicamente $\ket{+}{\otimes n}$ a $\ket {0} $ usando uma série de camadas de portões Hadamard que é proporcional a $\sqrt{2^n}$ (ou seja, $m\propto \sqrt{2^n}$) contra as camadas de cerca de $2^n$ que seriam necessárias para preparar não deterministicamente o estado de $\ket$ {0} preparando e medindo o estado inicial até que o resultado seja observado $0$We can then combine these two oracles together to rotate between the two states and deterministically transform $\ket{+}^{\otimes n}$ to $\ket{0}$ using a number of layers of Hadamard gates that is proportional to $\sqrt{2^n}$ (ie $m\propto \sqrt{2^n}$) versus the roughly $2^n$ layers that would be needed to non-deterministically prepare the $\ket{0}$ state by preparing and measuring the initial state until the outcome $0$ is observed.

Oráculos de estimativa de fasePhase Estimation Oracles

Para a estimativa de fase, os oráculos são um pouco mais naturais.For phase estimation the oracles are somewhat more natural. O objetivo na estimativa de fase é conceber uma subrotina capaz de amostrar dos valores de uma matriz unitária.The aim in phase estimation is to design a subroutine that is capable of sampling from the eigenvalues of a unitary matrix. Este método é indispensável na simulação quântica porque para muitos problemas físicos na química e na ciência dos materiais estes valores eigenvalues dão as energias do estado terrestre dos sistemas quânticos que nos fornecem informações valiosas sobre os diagramas de fase de materiais e dinâmicas de reação para moléculas.This method is indispensable in quantum simulation because for many physical problems in chemistry and material science these eigenvalues give the ground-state energies of quantum systems which provides us valuable information about the phase diagrams of materials and reaction dynamics for molecules. Cada sabor da estimativa de fase precisa de uma entrada unitária.Every flavor of phase estimation needs an input unitary. Este unitário é habitualmente descrito por um de dois tipos de oráculos.This unitary is customarily described by one of two types of oracles.

Dica

Ambos os tipos de oráculo descritos abaixo estão cobertos nas amostras.Both of the oracle types described below are covered in the samples. Para saber mais sobre oráculos de consulta contínua, consulte a amostra phaseEstimation.To learn more about continuous query oracles, please see the PhaseEstimation sample. Para saber mais sobre oráculos de consulta discreta, consulte a amostra isingPhaseEstimation.To learn more about discrete query oracles, please see the IsingPhaseEstimation sample.

O primeiro tipo de oráculo, a que chamamos um oráculo de consulta discreta e que representa com o tipo definido pelo DiscreteOracle user defined type utilizador, envolve simplesmente uma matriz unitária.The first type of oracle, which we call a discrete query oracle and represent with the user-defined type DiscreteOracle user defined type, simply involves a unitary matrix. Se $U$ é o unitário cujos valores eigen valorizamos, então o oráculo para $U$ é simplesmente um substituto para uma sub-rotina que implementa $U$.If $U$ is the unitary whose eigenvalues we wish to estimate then the oracle for $U$ is simply a stand-in for a subroutine that implements $U$. Por exemplo, pode-se levar $U$ para ser o oráculo $Q$ definido acima para estimação de amplitude.For example, one could take $U$ to be the oracle $Q$ defined above for amplitude estimation. Os valores eigenvalues desta matriz podem ser usados para estimar a sobreposição entre os estados iniciais e alvo, $\sin^2(\theta)$, usando quadráticamente menos amostras do que seria necessário de outra forma.The eigenvalues of this matrix can be used to estimate the overlap between the initial and target states, $\sin^2(\theta)$, using quadratically fewer samples than one would need otherwise. Isto ganha a aplicação de estimativa de fase usando o oráculo Grover $Q$ como entrada o apelido de estimativa de amplitude.This earns the application of phase estimation using the Grover oracle $Q$ as input the moniker of amplitude estimation. Outra aplicação comum, amplamente utilizada na metrologia quântica, envolve estimar um pequeno ângulo de rotação.Another common application, widely used in quantum metrology, involves estimating a small rotation angle. Por outras palavras, queremos estimar $\theta$ para um portão de rotação desconhecido do formulário $R_z(\theta)$.In other words, we wish to estimate $\theta$ for an unknown rotation gate of the form $R_z(\theta)$. Nesses casos, a sub-rotina com a qual interagiríamos para aprender este valor fixo de $\theta$ para o portão é $$ \start{align} U & = R_z(\theta) \ \ & = \begin{bmatrix} e^{{-i \theta / 2} & \ \ 0 0 & e^{i\ita/2 \end{bmat}}In such cases, the subroutine that we would interact with in order to learn this fixed value of $\theta$ for the gate is $$ \begin{align} U & = R_z(\theta) \\ & = \begin{bmatrix} e^{-i \theta / 2} & 0 \\ 0 & e^{i\theta/2} \end{bmatrix}. \end{align} $$\end{align} $$

O segundo tipo de oráculo utilizado na estimativa de fase é o oráculo de consulta contínua, representado pelo ContinuousOracle user defined type tipo.The second type of oracle used in phase estimation is the continuous query oracle, represented by the ContinuousOracle user defined type type. Um oráculo de consulta contínua para estimativa de fase toma a forma $U(t)$ onde $t$ é um número real clássico conhecido.A continuous query oracle for phase estimation takes the form $U(t)$ where $t$ is a classically known real number. Se deixarmos $U$ ser um unitário fixo, então o oráculo de consulta contínua toma a forma $U(t) = U^t$.If we let $U$ be a fixed unitary then the continuous query oracle takes the form $U(t) = U^t$. Isto permite-nos consultar matrizes como $\sqrt{U}$, que não poderia ser implementada diretamente no modelo de consulta discreta.This allows us to query matrices such as $\sqrt{U}$, which could not be implemented directly in the discrete query model.

Este tipo de oráculo é valioso quando não se está a sondar um determinado unitário, mas sim deseja aprender as propriedades do gerador do unitário.This type of oracle is valuable when you're not probing a particular unitary, but rather wish to learn the properties of the generator of the unitary. Por exemplo, na simulação quântica dinâmica o objetivo é conceber circuitos quânticos que se aproximem intimamente $U(t)=e^{-i H t}$ para uma matriz hermitiana $H$ e tempo de evolução $t$.For example, in dynamical quantum simulation the goal is to devise quantum circuits that closely approximate $U(t)=e^{-i H t}$ for a Hermitian matrix $H$ and evolution time $t$. Os valores de eigen de $U(t)$ estão diretamente relacionados com os valores de $H$.The eigenvalues of $U(t)$ are directly related to the eigenvalues of $H$. Para ver isto, considere um eigenvector de $H$: $H \ket{E} = E\ket{E}$ então é fácil ver a partir da definição da série de potência da matriz expoente que $U(t) \ket{E} = e^i\phi}\ket{E}= e^{-iEt}}ket(t{E{E}.}To see this, consider an eigenvector of $H$: $H \ket{E} = E\ket{E}$ then it is easy to see from the power-series definition of the matrix exponential that $U(t) \ket{E} = e^{i\phi}\ket{E}= e^{-iEt}\ket{E}$. Assim, estimando a fase eigense de $U(t)$ dá o $E do eigenvalue $E$ assumindo que o eigenvector $\ket{E}$ é a entrada no algoritmo de estimativa de fase.Thus estimating the eigenphase of $U(t)$ gives the eigenvalue $E$ assuming the eigenvector $\ket{E}$ is input into the phase estimation algorithm. No entanto, neste caso, o valor $t$ pode ser escolhido a critério do utilizador, uma vez que para qualquer valor suficientemente pequeno de $t$ o $E$ pode ser invertido exclusivamente através de $E=-\phi/t$.However, in this case the value $t$ can be chosen at the user's discretion since for any sufficiently small value of $t$ the eigenvalue $E$ can be uniquely inverted through $E=-\phi/t$. Uma vez que os métodos de simulação quântica proporcionam a capacidade de realizar uma evolução fracionada, isto concede aos algoritmos de estimativa de fase uma liberdade adicional ao consultar o unitário, especificamente enquanto o modelo de consulta discreta permite que apenas unitários da forma $U^j$ se apliquem para o número inteiro $j$ a consulta contínua oráculo permite-nos aproximar unitários da forma $U^t$ para qualquer valor real $t$.Since quantum simulation methods provide the ability to perform a fractional evolution, this grants phase estimation algorithms an additional freedom when querying the unitary, specifically while the discrete query model allows only unitaries of the form $U^j$ to applied for integer $j$ the continuous query oracle allows us to approximate unitaries of the form $U^t$ for any real valued $t$. Isto é importante para espremer cada gota de eficiência fora dos algoritmos de estimativa de fase porque nos permite escolher precisamente a experiência que forneceria mais informações sobre $E$; que os métodos baseados em consultas discretas devem fazer com que se comprometam escolhendo o melhor número inteiro de consultas no algoritmo.This is important to squeeze every last ounce of efficiency out of phase estimation algorithms because it allows us to choose precisely the experiment that would provide the most information about $E$; whereas methods based on discrete queries must make do with compromising by choosing the best integer number of queries in the algorithm.

Como exemplo concreto disso, considere o problema de estimar não o ângulo de rotação de um portão, mas a frequência de procissão de um sistema quântico rotativo.As a concrete example of this, consider the problem of estimating not the rotation angle of a gate but the procession frequency of a rotating quantum system. O unitário que descreve tal dinâmica quântica é $U(t)=R_z (2\omega t)$ para o tempo de evolução $t$ e frequência desconhecida $\omega$.The unitary that describes such quantum dynamics is $U(t)=R_z(2\omega t)$ for evolution time $t$ and unknown frequency $\omega$. Neste contexto, podemos simular $U(t)$ para qualquer $t$ usando um único portão de $R_z$ e, como tal, não precisamos de nos restringir apenas a consultas discretas ao unitário.In this context, we can simulate $U(t)$ for any $t$ using a single $R_z$ gate and as such do not need to restrict ourselves to only discrete queries to the unitary. Tal modelo contínuo também tem a propriedade que frequências superiores a $2\pi$ podem ser aprendidas a partir de processos de estimativa de fase que usam consultas contínuas porque informações de fase que de outra forma seriam mascaradas pelos cortes de ramo da função logaritmo podem ser reveladas a partir dos resultados de experiências realizadas em valores não proporcionais de $t$.Such a continuous model also has the property that frequencies greater than $2\pi$ can be learned from phase estimation processes that use continuous queries because phase information that would otherwise be masked by the branch-cuts of the logarithm function can be revealed from the results of experiments performed on non-commensurate values of $t$. Assim, para problemas como este modelo de consulta contínua para a estimativa de fase oráculo não só são adequados, como também são preferíveis ao modelo de consulta discreta.Thus for problems such as this continuous query models for the phase estimation oracle are not only appropriate but are also preferable to the discrete query model. Por esta razão Q# tem funcionalidade para ambas as formas de consultas e deixa ao utilizador decidir sobre um algoritmo de estimativa de fase para adequar as suas necessidades e o tipo de oráculo que está disponível.For this reason Q# has functionality for both forms of queries and leave it to the user to decide upon a phase estimation algorithm to fit their needs and the type of oracle that is available.

Modelação dinâmica do geradorDynamical Generator Modeling

Os geradores da evolução do tempo descrevem como os estados evoluem através do tempo.Generators of time-evolution describe how states evolve through time. Por exemplo, a dinâmica de um estado quântico $\ket{\psi}$ é regida pela equação schrödinger $\ \start{end{d\ket{\psi(t)}}{d} & = H\ket{\psi(t)}, \end{align} $$ com uma matriz eremita $H$, conhecida como o Hamiltonian, como o gerador.For instance, the dynamics of a quantum state $\ket{\psi}$ is governed by the Schrödinger equation $$ \begin{align} i\frac{d \ket{\psi(t)}}{d t} & = H \ket{\psi(t)}, \end{align} $$ with a Hermitian matrix $H$, known as the Hamiltonian, as the generator of motion. Dado um estado inicial $\ket{\psi(0)}$ no momento $t=0$, a solução formal para esta equação no momento $t$ pode ser, em princípio, escrito $$ \start{align} \ket{\psi(t)} = U(t)\ket{\psi(0)}, \end{align} $$ onde a matriz exponencial $U(t)=e^{-i H t}} é conhecida como o operador unitário de evolução temporal.Given an initial state $\ket{\psi(0)}$ at time $t=0$, the formal solution to this equation at time $t$ may be, in principle, written $$ \begin{align} \ket{\psi(t)} = U(t)\ket{\psi(0)}, \end{align} $$ where the matrix exponential $U(t)=e^{-i H t}$ is known as the unitary time-evolution operator. Embora nos concentremos em geradores desta forma na seguinte, sublinhamos que o conceito se aplica mais amplamente, como a simulação de sistemas quânticos abertos, ou a equações diferenciais mais abstratas.Though we focus on generators of this form in the following, we emphasize that the concept applies more broadly, such as to the simulation of open quantum systems, or to more abstract differential equations.

Um objetivo primário da simulação dinâmica é implementar o operador de evolução temporal em algum estado quântico codificado em qubits de um computador quântico.A primary goal of dynamical simulation is to implement the time-evolution operator on some quantum state encoded in qubits of a quantum computer. Em muitos casos, o Hamiltonian pode ser dividido em uma soma de alguns $d$ termos mais simplesIn many cases, the Hamiltonian may be broken into a sum of some $d$ simpler terms

$$ \begin{align} H & = \sum^{d-1}{j=0} H_j, \end{align} $$$$ \begin{align} H & = \sum^{d-1}{j=0} H_j, \end{align} $$

onde a evolução do tempo por cada termo por si só é fácil de implementar num computador quântico.where time-evolution by each term alone is easy to implement on a quantum computer. Por exemplo, se $H_j$ for um operador Pauli $X_1X_2$ agindo nos 1º e 2º elementos do registo qubit, a qubits evolução temporal por ele $t pode ser implementada simplesmente chamando a operação Exp([PauliX,PauliX], t, qubits[1..2]) , que tem assinatura ((Pauli[], Double, Qubit[]) => Unit is Adj + Ctl) .For instance, if $H_j$ is a Pauli $X_1X_2$ operator acting on the 1st and 2nd elements of the qubit register qubits, time-evolution by it for any time $t$ may be implemented simply by calling the operation Exp([PauliX,PauliX], t, qubits[1..2]), which has signature ((Pauli[], Double, Qubit[]) => Unit is Adj + Ctl). Como discutido mais tarde na Simulação hamiltoniana, uma solução então é aproximar a evolução do tempo por $H$ com uma sequência de operações mais simplesAs discussed later in Hamiltonian Simulation, one solution then is to approximate time-evolution by $H$ with a sequence of simpler operations

$$ \begin{align} U(t) & = \esquerda( e^{-iH _ 0 t / r} e^{-iH _ 1 t / r} \cdots e^{-iH _ {d-1} t / r} \right){r} + \mathcal{O}(d^2\max_j \ # H _ j \ [^2 t^2/r), \end{align} $$$$ \begin{align} U(t) & = \left( e^{-iH_0 t / r} e^{-iH_1 t / r} \cdots e^{-iH_{d-1} t / r} \right)^{r} + \mathcal{O}(d^2 \max_j \|H_j\|^2 t^2/r), \end{align} $$

onde o inteiro $r > 0$ controla o erro de aproximação.where the integer $r > 0$ controls the approximation error.

A biblioteca de modelação de geradores dinâmicos fornece uma estrutura para codificar sistematicamente geradores complicados em termos de geradores mais simples.The dynamical generator modeling library provides a framework for systematically encoding complicated generators in terms of simpler generators. Tal descrição pode então ser passada para, digamos, a biblioteca de simulação para implementar a evolução do tempo através de um algoritmo de simulação de escolha, com muitos detalhes automaticamente tratados.Such a description may then be passed to, say, the simulation library to implement time-evolution by a simulation algorithm of choice, with many details automatically taken care of.

Dica

A biblioteca dinâmica do gerador descrita abaixo está coberta nas amostras.The dynamical generator library described below is covered in the samples. Para um exemplo baseado no modelo Ising, consulte a amostra isingGenerators.For an example based on the Ising model, please see the IsingGenerators sample. Para um exemplo baseado em hidrogénio molecular, consulte as amostras H2SimulationCmdLine e H2SimulationGUI.For an example based on molecular Hydrogen, please see the H2SimulationCmdLine and H2SimulationGUI samples.

Descrição completa de um geradorComplete Description of a Generator

No nível superior, uma descrição completa de um Hamiltonian está contida no EvolutionGenerator tipo definido pelo utilizador que tem dois componentes.:At the top level, a complete description of a Hamiltonian is contained in the EvolutionGenerator user-defined type which has two components.:

newtype EvolutionGenerator = (EvolutionSet, GeneratorSystem);

O GeneratorSystem tipo definido pelo utilizador é uma descrição clássica do Hamiltonian.The GeneratorSystem user-defined type is a classical description of the Hamiltonian.

newtype GeneratorSystem = (Int, (Int -> GeneratorIndex));

O primeiro elemento Int da tuple armazena o número de termos $d$ no Hamiltonian, e o segundo elemento (Int -> GeneratorIndex) é uma função que mapeia um índice inteiro em { $0,...,d-1$ } para um tipo definido pelo utilizador que identifica GeneratorIndex exclusivamente cada termo primitivo no Hamiltonian.The first element Int of the tuple stores the number of terms $d$ in the Hamiltonian, and the second element (Int -> GeneratorIndex) is a function that maps an integer index in ${0,1,...,d-1}$ to a GeneratorIndex user-defined type which uniquely identifies each primitive term in the Hamiltonian. Note que ao expressar a coleção de termos no Hamiltonian como uma função e não como uma GeneratorIndex[] matriz, isto permite a computação on-the-fly do GeneratorIndex que é especialmente útil ao descrever os hamiltonianos com um grande número de termos.Note that by expressing the collection of terms in the Hamiltonian as a function rather than as an array GeneratorIndex[], this allows for on-the-fly computation of the GeneratorIndex which is especially useful when describing Hamiltonians with a large number of terms.

Crucialmente, não impomos uma convenção sobre os termos primitivos identificados pelos GeneratorIndex são fáceis de simular.Crucially, we do not impose a convention on what primitive terms identified by the GeneratorIndex are easy-to-simulate. Por exemplo, os termos primitivos podem ser operadores de Pauli como discutido acima, mas também podem ser operadores de aniquilação e criação fermiónicas comumente usados na simulação de química quântica.For instance, primitive terms could be Pauli operators as discussed above, but they could also be Fermionic annihilation and creation operators commonly used in quantum chemistry simulation. Por si só, um não é insignificante, uma GeneratorIndex vez que não descreve como a evolução do tempo pelo termo que aponta pode ser implementada como um circuito quântico.By itself, a GeneratorIndex is meaningless as it does not describe how time-evolution by the term it points to may be implemented as a quantum circuit.

Isto é resolvido especificando um tipo definido pelo EvolutionSet utilizador que mapeia qualquer GeneratorIndex , extraído de algum conjunto canónico, para um operador unitário, o EvolutionUnitary , expresso como um circuito quântico.This is resolved by specifying an EvolutionSet user-defined type that maps any GeneratorIndex, drawn from some canonical set, to a unitary operator, the EvolutionUnitary, expressed as a quantum circuit. O EvolutionSet define a convenção de como um é GeneratorIndex estruturado, e também define o conjunto de possíveis GeneratorIndex .The EvolutionSet defines the convention of how a GeneratorIndex is structured, and also defines the set of possible GeneratorIndex.

newtype EvolutionSet = (GeneratorIndex -> EvolutionUnitary);

Geradores de Operador PauliPauli Operator Generators

Um exemplo concreto e útil de geradores são os hamiltonianos que são uma soma de operadores Pauli, cada um possivelmente com um coeficiente diferente.A concrete and useful example of generators are Hamiltonians that are a sum of Pauli operators, each possibly with a different coefficient. $$ \start{align} H & = \sum^{d-1}{j=0} a_j H_j, \end{align} $$ onde cada $\hat H_j$ é agora retirado do grupo Pauli.$$ \begin{align} H & = \sum^{d-1}{j=0} a_j H_j, \end{align} $$ where each $\hat H_j$ is now drawn from the Pauli group. Para estes sistemas, fornecemos o PauliEvolutionSet() tipo que define uma EvolutionSet convenção de como um elemento do grupo Pauli e um coeficiente podem ser identificados por um GeneratorIndex , que tem a seguinte assinatura.For such systems, we provide the PauliEvolutionSet() of type EvolutionSet that defines a convention for how an element of the Pauli group and a coefficient may be identified by a GeneratorIndex, which has the following signature.

newtype GeneratorIndex = ((Int[], Double[]), Int[]);

Na nossa codificação, o primeiro parâmetro Int[] especifica uma corda Pauli, onde $\hat I\rightarrow 0$, $\hat X\rightarrow 1$, $\hat Y\rightarrow 2$, e $\hat Z\rightarrow 3$.In our encoding, the first parameter Int[] specifies a Pauli string, where $\hat I\rightarrow 0$, $\hat X\rightarrow 1$, $\hat Y\rightarrow 2$, and $\hat Z\rightarrow 3$. O segundo parâmetro Double[] armazena o coeficiente da corda Pauli no Hamiltonian.The second parameter Double[] stores the coefficient of the Pauli string in the Hamiltonian. Note que apenas o primeiro elemento desta matriz é usado.Note that only the first element of this array is used. O terceiro parâmetro Int[] indexa os qubits em que esta corda Pauli age, e não deve ter elementos duplicados.The third parameter Int[] indexes the qubits that this Pauli string acts on, and must have no duplicate elements. Assim, o termo Hamiltonian $0,4 \hat X_0 \hat Y_8\hat I_2\hat Z_1$ pode ser representado comoThus the Hamiltonian term $0.4 \hat X_0 \hat Y_8\hat I_2\hat Z_1$ may be represented as

let generatorIndexExample = GeneratorIndex(([1,2,0,3], [0.4]]), [0,8,2,1]);

É PauliEvolutionSet() uma função que mapeia qualquer GeneratorIndex um deste formulário para uma com a seguinte EvolutionUnitary assinatura.The PauliEvolutionSet() is a function that maps any GeneratorIndex of this form to an EvolutionUnitary with the following signature.

newtype EvolutionUnitary = ((Double, Qubit[]) => Unit is Adj + Ctl);

O primeiro parâmetro representa uma duração temporal, que será multiplicada pelo coeficiente na GeneratorIndex evolução unitária.The first parameter represents a time-duration, that will be multiplied by the coefficient in the GeneratorIndex, of unitary evolution. O segundo parâmetro é o registo qubit em que os atos unitários.The second parameter is the qubit register the unitary acts on.

Geradores Time-DependentTime-Dependent Generators

Em muitos casos, também estamos interessados em modelar geradores dependentes do tempo, como pode ocorrer na equação schrödinger $$ \start{{d\ket{\psi(t)}}{d t} & = \hat H(t) \ket{\psi(t)}, \end{align} $$ onde o gerador $\hat H(t)$ é agora dependente do tempo.In many cases, we are also interested in modelling time-dependent generators, as might occur in the Schrödinger equation $$ \begin{align} i\frac{d \ket{\psi(t)}}{d t} & = \hat H(t) \ket{\psi(t)}, \end{align} $$ where the generator $\hat H(t)$ is now time-dependent. A extensão dos geradores independentes do tempo acima para este caso é simples.The extension from the time-independent generators above to this case is straightforward. Em vez de termos uma descrição fixa GeneratorSystem do Hamiltonian para sempre $t$, em vez disso temos o GeneratorSystemTimeDependent tipo definido pelo utilizador.Rather than having a fixed GeneratorSystem describing the Hamiltonian for all times $t$, we instead have the GeneratorSystemTimeDependent user-defined type.

newtype GeneratorSystemTimeDependent = (Double -> GeneratorSystem);

O primeiro parâmetro é um parâmetro de agenda contínua $s\in [0,1]$, e funções deste tipo devolvem um GeneratorSystem para esse horário.The first parameter is a continuous schedule parameter $s\in [0,1]$, and functions of this type return a GeneratorSystem for that schedule. Note que o parâmetro do horário pode estar relacionado linearmente com o parâmetro de tempo físico, por exemplo, $s = t / T$, durante algum tempo total de simulação $T$.Note that the schedule parameter may be linearly related to the physical time parameter e.g. $s = t / T$, for some total time of simulation $T$. No entanto, em geral, este não deve ser o caso.In general however, this need not be the case.

Da mesma forma, uma descrição completa deste gerador requer um EvolutionSet , e assim definimos um tipo definido EvolutionSchedule pelo utilizador.Similarly, a complete description of this generator requires an EvolutionSet, and so we define an EvolutionSchedule user-defined type.

newtype EvolutionSchedule = (EvolutionSet, GeneratorSystemTimeDependent);