Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Conforme elaborado com mais detalhes na descrição do tipo de dados qubit, as computações quânticas são executadas na forma de efeitos colaterais de operações que têm suporte nativo no processador quântico de destino. Estes são, de fato, os únicos efeitos colaterais em Q#. Como todos os tipos são imutáveis, não há efeitos colaterais que afetam um valor explicitamente representado em Q#. Portanto, desde que uma implementação de um determinado callable não chame direta ou indiretamente nenhuma dessas operações implementadas nativamente, sua execução sempre produzirá a mesma saída, dada a mesma entrada.
Q# permite que você divida explicitamente tais cálculos puramente determinísticos em funções . Como o conjunto de instruções com suporte nativo não é fixo e integrado ao próprio idioma, mas totalmente configurável e expresso como uma biblioteca de Q#, o determinismo é garantido exigindo que as funções só possam chamar outras funções e não possam chamar nenhuma operação. Além disso, as instruções nativas que não são determinísticas, ou seja, porque afetam o estado quântico, são representadas como operações. Com essas duas restrições, as funções podem ser avaliadas assim que o valor de entrada é conhecido e, em princípio, nunca precisam ser avaliadas mais de uma vez para a mesma entrada.
Q#, portanto, distingue entre dois tipos de callables: operações e funções. Todos os callables assumem um único argumento (potencialmente com valor de tupla) como entrada e produzem um único valor (tupla) como saída. Sintaticamente, o tipo de operação é expresso como <TIn> => <TOut> is <Char>, em que <TIn> deve ser substituído pelo tipo de argumento, <TOut> deve ser substituído pelo tipo de retorno e <Char> deve ser substituído pelas características de operação . Se nenhuma característica precisar ser especificada, a sintaxe será simplificada para <TIn> => <TOut>. Da mesma forma, os tipos de função são expressos como <TIn> -> <TOut>.
Além dessa garantia de determinismo, há pouca diferença entre operações e funções. Ambos são valores de primeira classe que podem ser passados livremente; eles podem ser usados como valores ou argumentos retornados para outros callables, conforme mostrado no exemplo a seguir:
function Pow<'T>(op : 'T => Unit, pow : Int) : 'T => Unit {
return PowImpl(op, pow, _);
}
Ambos podem ser instanciados com base em uma definição parametrizada por tipo, por exemplo, a função de tipo parametrizadoPow anterior e podem ser parcialmente aplicadas como feito na instrução return no exemplo.
Características da operação
Além das informações sobre o tipo de entrada e saída, o tipo de operação contém informações sobre as características de uma operação. Essas informações, por exemplo, descrevem quais functors têm suporte na operação. Além disso, a representação interna também contém informações relevantes para otimização que são inferidas pelo compilador.
As características de uma operação são um conjunto de rótulos predefinidos e internos. Eles são expressos na forma de uma expressão especial que faz parte da assinatura de tipo. A expressão consiste em um dos conjuntos predefinidos de rótulos ou de uma combinação de expressões de características por meio de um operador binário com suporte.
Há dois conjuntos predefinidos, Adj e Ctl.
-
Adjé o conjunto que contém um único rótulo indicando que uma operação é adjacente, o que significa que dá suporte aoAdjointfunctor e a transformação quântica aplicada pode ser "desfeita", ou seja, ela pode ser invertida. -
Ctlé o conjunto que contém um único rótulo que indica que uma operação é controlável, o que significa que dá suporte aoControlledfunctor e sua execução pode ser condicionada ao estado de outros qubits.
Os dois operadores com suporte como parte das expressões de características são a união definida + e a interseção definida *.
No EBNF (formulário Backus-Naur Estendido),
predefined = "Adj" | "Ctl";
characteristics = predefined
| "(", characteristics, ")"
| characteristics ("+"|"*") characteristics;
Como seria de esperar, * tem precedência maior do que + e ambos são associativos à esquerda. O tipo de uma operação unitária, por exemplo, é expresso como <TIn> => <TOut> is Adj + Ctl, em que <TIn> deve ser substituído pelo tipo do argumento de operação e <TOut> substituído pelo tipo do valor retornado.
Observação
Indicar as características de uma operação nesse formulário tem duas vantagens principais; por um lado, novos rótulos podem ser introduzidos sem ter exponencialmente muitas palavras-chave de linguagem para todas as combinações de rótulos. Mais importante, usar expressões para indicar as características de uma operação também dá suporte a parametrizações sobre características de operação no futuro.