Olá Habitantes! Os computadores quânticos desencadearam uma nova revolução no computador e você tem uma grande chance de se juntar ao avanço tecnológico agora. Desenvolvedores, especialistas em computação gráfica e aspirantes a profissionais de TI encontrarão neste livro informações práticas sobre computação quântica que os programadores precisam. Em vez de estudar teoria e fórmulas, você imediatamente se concentrará em problemas específicos que demonstram as capacidades exclusivas da tecnologia quântica.
Eric Johnston, Nick Harrigan e Mercedes Gimeno-Segovia ajudam a desenvolver as habilidades e intuição necessárias, além de dominar as ferramentas necessárias para criar aplicativos quânticos. Você entenderá do que os computadores quânticos são capazes e como aplicá-lo na vida real. O livro consiste em três partes: - Programação de QPU: conceitos básicos de programação de processadores quânticos, realizando operações com qubits e teletransporte quântico. - Primitivas QPU: primitivas e métodos algorítmicos, amplificação de amplitude, transformada de Fourier quântica e estimativa de fase. - Praticar QPU: resolver problemas específicos usando primitivas QPU, métodos de busca quântica e algoritmo de decomposição de Shor.
Estrutura do livro
. , , (GPU), , .
— , QPU. , ( , ). (QPU) , QPU.
. I , .
I. QPU
, QPU: , , . QPU.
II. QPU
. , , . « », . , , QPU. QPU, , .
III. QPU
QPU — II — , QPU. .
, , , , .
— , QPU. , ( , ). (QPU) , QPU.
. I , .
I. QPU
, QPU: , , . QPU.
II. QPU
. , , . « », . , , QPU. QPU, , .
III. QPU
QPU — II — , QPU. .
, , , , .
Dados reais
Os aplicativos QPU completos são desenvolvidos para trabalhar com dados reais que não são de treinamento. Os dados reais nem sempre estão limitados aos inteiros básicos que chegamos até agora. Portanto, a questão de como representar dados mais complexos em QPU vale o esforço, e boas estruturas de dados podem ser tão importantes quanto bons algoritmos. Neste capítulo, tentaremos responder a duas perguntas que foram ignoradas anteriormente:
- Como representar tipos de dados complexos no registro QPU? Um número inteiro positivo pode ser representado em codificação binária simples. Mas e quanto aos números irracionais, ou mesmo tipos de dados compostos, como vetores ou matrizes? Essa questão adquire uma nova profundidade quando consideramos que a superposição e a fase relativa podem fornecer novas opções de codificação quântica para esses tipos de dados.
- , QPU? , WRITE . , QPU . , , , QPU , .
Vamos começar com a primeira pergunta. Ao descrever representações de QPU para tipos de dados de complexidade crescente, chegaremos à introdução de estruturas de dados quânticas completas e do conceito de memória de acesso aleatório quântica (QRAM). Quantum RAM é um recurso crítico para muitas aplicações práticas de QPU.
O material dos capítulos subsequentes será altamente dependente das estruturas de dados apresentadas neste capítulo. Por exemplo, a chamada codificação de amplitude complexa que será descrita para dados vetoriais é central para todos os aplicativos de aprendizado de máquina quântica introduzidos no Capítulo 13.
Dados não alvo
Como codificar dados numéricos não inteiros no registro QPU? As duas maneiras padrão de representar esses valores em binário são representações de ponto fixo e de ponto flutuante. Embora a representação de ponto flutuante seja mais flexível (e adaptável ao intervalo de valores que precisam ser representados com um certo número de bits), por causa do alto valor dos qubits e nosso desejo de simplicidade, a representação de ponto fixo é um melhor lugar para começar.
Números de pontos fixos são freqüentemente descritos em notação Q (infelizmente, Q neste caso não significa "quantum"). Isso ajuda a remover a ambigüidade sobre onde os bits fracionários terminam e os bits inteiros começam. A notação Qn.m denota um registrador de n bits, os m bits dos quais são para a parte fracionária (e, portanto, o restante (n - m) contém a parte inteira). É claro que você pode usar a mesma notação para especificar como o registro QPU deve ser usado para codificar um número de ponto fixo. Por exemplo, na Fig. 9.1 mostra um registro QPU de oito qubit, que codifica o valor 3,640625 na representação de ponto fixo Q8.6.
No exemplo dado, o número selecionado pode ser codificado com precisão na representação de ponto fixo, porque 3,640625 =
Claro, essa sorte nem sempre é encontrada. Aumentar o número de bits na parte inteira de um registrador de ponto fixo expande o intervalo de valores inteiros que podem ser representados, enquanto aumentar o número de bits na parte fracionária melhora a precisão da parte fracionária de um número. Quanto mais qubits na parte fracionária, mais provável é que alguma combinação
possa representar com precisão um determinado número.

Embora possamos mencionar brevemente o uso da representação de ponto fixo nos capítulos seguintes, ela desempenha um papel extremamente importante na experimentação com dados reais em pequenos registradores QPU. Ao trabalhar com diferentes métodos de codificação, você precisa monitorar cuidadosamente qual codificação específica foi usada para dados em um determinado registro QPU para interpretar corretamente o estado de seus qubits.
QRAM
Os registradores QPU podem armazenar representações de diferentes valores numéricos, mas como armazenar esses valores neles? Os dados inicializados manualmente ficam desatualizados muito rapidamente. O que realmente precisamos é a capacidade de ler valores da memória, buscando valores armazenados em um endereço binário. O programador trabalha com a memória de acesso aleatório tradicional usando dois registradores: um é inicializado com um endereço de memória e o outro permanece não inicializado. A memória de acesso aleatório grava no segundo registro os dados binários armazenados no endereço especificado pelo primeiro registro, como mostrado na Fig. 9.2.

A memória tradicional pode ser usada para armazenar os valores destinados a inicializar os registradores QPU? Claro, a ideia parece atraente.
Se você deseja inicializar o registro QPU com apenas um valor tradicional (complemento de dois, ponto fixo ou codificação binária simples), então a RAM é adequada. O valor desejado é simplesmente armazenado na memória, e write () e read () são usados para escrever ou ler do registrador QPU. É esse mecanismo limitado que foi usado pelo código JavaScript QCEngine para interagir com os registros QPU até agora.
Por exemplo, o código de amostra na Listagem 9.1, que recebe um array a e implementa a operação a [2] + = 1 ;, busca implicitamente esse array de valores da RAM para inicializar o registro QPU. O circuito é mostrado na Fig. 9,3.

Código de amostra
Este exemplo pode ser feito online em http://oreilly-qc.github.io?p=9-1.
Listagem 9.1. Usando QPU para aumentar o número na memória
var a = [4, 3, 5, 1];
qc.reset(3);
var qreg = qint.new(3, 'qreg');
qc.print(a);
increment(2, qreg);
qc.print(a);
function increment(index, qreg)
{
qreg.write(a[index]);
qreg.add(1);
a[index] = qreg.read();
}
É importante notar que neste caso simples, não apenas a RAM tradicional é usada para armazenar o inteiro, mas também o processador tradicional indexa o array para selecionar e transmitir a QPU do valor desejado.
Embora esse uso de RAM permita que os registradores QPU sejam inicializados com valores binários simples, ele tem sérias limitações. E se você precisar inicializar o registro QPU com a sobreposição dos valores armazenados? Por exemplo, suponha que na RAM, o valor 3 (110) seja armazenado no endereço 0x01 e o valor 5 (111) seja armazenado no endereço 0x11. Como preparo o registro de entrada em uma superposição desses dois valores?
Com a RAM tradicional e a operação tradicional complicada de write (), isso não funcionará. Os processadores quânticos, assim como seus ancestrais de tubo antes, precisarão de equipamentos de memória fundamentalmente novos - quânticos por natureza. Conheça a Quantum Random Access Memory (QRAM) permite que você leia e grave dados no nível quântico. Já existem algumas idéias sobre como construir QRAM fisicamente, mas é importante notar que a história pode muito bem se repetir e processadores quânticos incrivelmente poderosos podem aparecer muito antes de haver qualquer hardware de memória quântica funcional.
Vale a pena explicar um pouco mais precisamente o que o QRAM faz. Como a memória tradicional, QRAM recebe dois registros como entrada: o registro de endereço QPU para o endereço de memória e o registro de saída QPU, que retorna o valor armazenado no endereço fornecido. Para QRAM, ambos os registros são compostos de qubits. Isso significa que no registrador de endereço é possível definir uma superposição de células de memória e, como consequência, obter uma sobreposição dos valores correspondentes no registrador de saída (Fig. 9.4).

Portanto, o QRAM realmente permite que os valores armazenados na superposição sejam lidos. As amplitudes complexas exatas da superposição a serem obtidas no registro de saída são determinadas pela superposição fornecida no registro de endereço. Na fig. A Figura 9.2 mostra as diferenças ao realizar a mesma operação de incremento na Listagem 9.1 (Figura 9.5), mas usando QRAM para acessar os dados em vez de operações de leitura / gravação QPU. A letra "A" denota o registro no qual o endereço QRAM (ou superposição) é transmitido. A letra "D" denota o registro no qual QRAM retorna a sobreposição correspondente de valores armazenados (dados).

Código de amostra
Este exemplo pode ser feito online em oreilly-qc.github.io?p=9-2 .
Listagem 9.2. Usando QPU para incrementar um número de QRAM - o registro de endereço pode conter sobreposição, o que fará com que o registro de saída contenha uma superposição de valores armazenados
var a = [4, 3, 5, 1];
var reg_qubits = 3;
qc.reset(2 + reg_qubits + qram_qubits());
var qreg = qint.new(3, 'qreg');
var addr = qint.new(2, 'addr');
var qram = qram_initialize(a, reg_qubits);
qreg.write(0);
addr.write(2);
addr.hadamard(0x1);
qram_load(addr, qreg);
qreg.add(1);
Esta descrição do QRAM pode parecer muito vaga - o que é hardware de memória quântica? Neste livro, não daremos uma descrição de como construir QRAM na prática (como, digamos, a maioria dos livros em C ++ não fornece uma descrição detalhada de como a memória tradicional funciona). Exemplos de código como o da Listagem 9.2 são executados usando um modelo simplificado que imita o comportamento do QRAM. No entanto, existem protótipos de tecnologias QRAM.
Embora a memória quântica seja um componente crítico de qualquer QPU sério, os detalhes da implementação provavelmente mudarão, como acontece com qualquer dispositivo de computação quântica. O que é importante para nós é a própria ideia de um recurso fundamental que se comporta como mostrado na Fig. 9.4, e os aplicativos poderosos que podem ser construídos em cima dele.
Com a memória quântica à sua disposição, você pode avançar para a construção de estruturas de dados quânticas complexas. De particular interesse são as estruturas que permitem representar dados vetoriais e matriciais.
Codificação vetorial
Digamos que você queira inicializar o registrador QPU para representar um vetor simples como a Equação 9.1.
Fórmula 9.1. Um exemplo de vetor para inicializar o registro QPU.

Os dados neste formato são freqüentemente encontrados em aplicativos de aprendizado de máquina quântica.
Talvez o método mais óbvio para codificar dados vetoriais seja representar cada componente como um registro QPU separado com uma representação binária adequada. Chamaremos isso (provavelmente o mais óbvio) de codificação de estado de método para vetores. O vetor do exemplo acima pode ser codificado em quatro registros de dois qubit, como mostrado na Fig. 9,6.

Um dos problemas com a codificação de estado ingênuo é que ela desperdiça qubits - o recurso mais precioso de um QPU. No entanto, uma das vantagens dos vetores codificados por estado tradicionais é que eles não requerem memória quântica. Os componentes do vetor podem simplesmente ser armazenados na memória padrão e seus valores separados podem ser usados para controlar a preparação de cada registro individual de QPU. Mas essa vantagem também está subjacente à falha mais séria da codificação do estado do vetor: o armazenamento de dados vetoriais dessa forma tradicional nos impede de usar os recursos não tradicionais do QPU. Para aproveitar o poder do QPU, você precisa ser capaz de manipular as fases relativas das superposições, e isso não é fácil de fazer,se cada componente de um vetor realmente tratar seu processador quântico como uma coleção de registros binários tradicionais!
Em vez disso, você precisa descer ao nível quântico. Suponha que os componentes do vetor sejam armazenados na superposição das amplitudes de um registrador QPU. Uma vez que um registro QPU de n qubits pode existir em uma superposição com 2n amplitudes (e, portanto, haverá 2n círculos para experimentos com gravação circular), é possível representar a codificação de um vetor com n componentes em um registro QPU com ceil (log (n)) qubits.
Para o exemplo vetorial da Fórmula 9.1, esta abordagem exigiria um registrador de dois qubit - a ideia é encontrar um esquema quântico adequado para codificar os dados vetoriais na Figura 1. 9,7.

Vamos chamar essa codificação de dados vetoriais quânticos única de codificação de amplitude complexa. É importante apreciar as diferenças entre a codificação de amplitude complexa e a codificação de estado mais convencional. Mesa 9.1 compara os dois métodos de codificação para diferentes dados vetoriais. O último exemplo de codificação de estado precisará de quatro registradores de 7 bits, cada um dos quais usa uma representação de ponto fixo de Q7.7.
Tabela 9.1. Diferenças entre métodos de codificação de dados vetoriais (codificação de amplitude complexa e codificação de estado)

Para obter vetores com codificação de amplitude complexa em QCEngine, você pode usar a função amplitude_encode () conveniente. O programa na Listagem 9.3 pega um vetor de valores e uma referência a um registro QPU (que deve ser grande o suficiente) e prepara esse registro executando uma codificação de amplitude complexa no vetor.
Código de amostra
Este exemplo pode ser feito online em oreilly-qc.github.io?p=9-3 .
Listagem 9.3. Preparando vetores com codificação de amplitude complexa em QCEngine
// ,
// 2
var vector = [-1.0, 1.0, 1.0, 5.0, 5.0, 6.0, 6.0, 6.0];
//
//
var num_qubits = Math.log2(vector.length);
qc.reset(num_qubits);
var amp_enc_reg = qint.new(num_qubits, 'amp_enc_reg');
// amp_enc_reg
amplitude_encode(vector, amp_enc_reg);
Neste exemplo, o vetor é simplesmente passado como um array JavaScript armazenado na memória tradicional - embora tenhamos indicado que a codificação de amplitude complexa depende do QRAM. Como o QCEngine executa a codificação de amplitude complexa quando apenas a RAM do seu computador está disponível para o programa? Embora seja possível gerar um esquema de codificação de amplitude complexo sem QRAM, certamente não pode ser feito de forma eficiente. QCEngine fornece um modelo lento, mas viável do que pode ser alcançado com o acesso QRAM.
Limitações da codificação de amplitude complexa
A ideia por trás da codificação de amplitude complexa parece ótima no início - ela usa menos qubits e fornece ferramentas quânticas para trabalhar com dados vetoriais. Em qualquer aplicativo que usa esse mecanismo, há dois fatores importantes a serem considerados.
Problema 1: resultados quânticos
Você já deve ter notado a primeira dessas restrições: As superposições quânticas geralmente não podem ser lidas por READ. Nosso principal inimigo de novo! Se você distribuir os componentes do vetor sobre a superposição quântica, eles não poderão ser lidos novamente. Naturalmente, isso não cria nenhum problema especial ao transferir dados vetoriais da memória para a entrada de outro programa QPU. Porém, muitas vezes, os aplicativos QPU que recebem dados vetoriais com codificação de amplitude complexa na entrada também geram dados vetoriais com codificação de amplitude complexa na saída.
Portanto, o uso de codificação de amplitude complexa restringe severamente nossa capacidade de ler a saída do aplicativo com uma operação READ. Felizmente, muitas vezes é possível extrair informações úteis de resultados de codificação de amplitude complexos. Como você verá nos capítulos seguintes, embora não possa reconhecer os componentes individuais, você pode descobrir as propriedades globais dos vetores codificados desta forma. No entanto, a codificação de amplitude complexa não é uma panacéia e sua aplicação bem-sucedida requer atenção e engenhosidade.
Problema 2: o requisito para normalizar vetores
O segundo problema associado à codificação de amplitude complexa está oculto na tabela. 9,1 Dê uma olhada mais de perto na codificação de amplitude complexa dos primeiros dois vetores na tabela: [0,1,2,3] e [6,1,1,4]. As amplitudes complexas de um registro QPU de dois qubit podem assumir os valores [0,1,2,3] ou os valores [6,1,1,4]? Infelizmente não. Em capítulos anteriores, geralmente contornamos a discussão de amplitudes e fases relativas em favor de uma notação circular mais intuitiva. Embora essa abordagem fosse mais intuitiva, ela protegia você de uma regra numérica importante sobre amplitudes complexas: os quadrados das amplitudes complexas de um registro devem somar 1. Esse requisito, chamado normalização, faz sentido quando você lembra que os quadrados das amplitudes no registro correspondem às probabilidades de leitura. resultados diferentes.Uma vez que um resultado deve ser obtido, essas probabilidades (e, conseqüentemente, os quadrados de todas as amplitudes complexas) devem somar 1. Ao usar uma notação circular conveniente, é fácil esquecer a normalização, mas impõe uma restrição importante sobre qual vetor codificação de amplitude complexa pode ser aplicada aos dados. As leis da física não permitem a criação de um registro que esteja em superposição com amplitudes complexas [0,1,2,3] ou [6,1,1,4].estando em superposição com amplitudes complexas [0,1,2,3] ou [6,1,1,4].estando em superposição com amplitudes complexas [0,1,2,3] ou [6,1,1,4].
Para aplicar a codificação de amplitude complexa a dois vetores de problema da Tabela. 9.1, você primeiro precisa normalizá-los dividindo cada componente pela soma dos quadrados de todos os componentes. Por exemplo, na codificação de amplitude complexa do vetor [0,1,2,3], você primeiro precisa dividir todos os componentes por 3,74 para obter um vetor normalizado [0,00, 0,27, 0,53, 0,80], que agora é adequado para a codificação em amplitudes de superposição complexas.
A normalização de dados vetoriais tem algum efeito indesejado? Parece que os dados mudaram completamente! Na verdade, a normalização deixa a maioria das informações importantes inalteradas (na representação geométrica, ela apenas dimensiona o comprimento do vetor, deixando a direção inalterada). Podemos assumir que os dados normalizados substituem completamente os dados originais? Depende das necessidades do aplicativo QPU específico no qual você pretende usá-los. Lembre-se de que você pode armazenar o valor numérico do fator de normalização em um registro diferente, se necessário.
Codificação de amplitude complexa e gravação circular
À medida que você começa a pensar mais especificamente sobre os valores numéricos das amplitudes complexas dos registros, pode ser útil lembrar-se de como as amplitudes complexas são representadas em notação circular e perceber uma possível armadilha. As áreas preenchidas em notação circular representam os quadrados das amplitudes das amplitudes complexas do estado quântico. Em situações como codificação de amplitude complexa, onde as amplitudes complexas devem representar os componentes de um vetor com valores reais, isso significa que as áreas preenchidas são determinadas pelo quadrado do componente correspondente do vetor, e não pelo próprio componente. Na fig. 9.8 mostra como interpretar corretamente a representação do vetor [0,1,2,3] após a normalização em notação circular.

Agora você sabe o suficiente sobre vetores codificados em amplitude complexos para entender as aplicações QPU que serão apresentadas no livro. Mas para muitas aplicações, especialmente aquelas relacionadas ao aprendizado de máquina quântica, é necessário dar um passo adiante e usar o QPU para manipular não apenas vetores, mas também matrizes de dados inteiras. Como você codifica matrizes bidimensionais de números?
»Mais detalhes sobre o livro podem ser encontrados no site da Editora
» Índice
» Trecho
Para Habitantes desconto de 25% no cupom - Programação No
ato do pagamento da versão em papel do livro, é enviado um e-book para e-mail.