当前位置:网站首页>Q_06_02 类型模型

Q_06_02 类型模型

2022-08-09 13:02:00 MOVCat

类型模型 

本节展示Q#类型模型并描述用于指定和处理类型的语法。

原始类型

Q#提供了几种基本类型,其中构造了所有其他类型:

  • Int类型表示一个64位有符号(二进制补码)整数。
  • Double类型表示一个双精度浮点数。
  • Bool类型表示一个布尔值,无论是true还是false
  • Qubit类型表示量子比特或量子比特。Qubit对用户是不透明的;除了将它们传递给另一个操作之外,唯一可能的操作是测试身份(等同性)。最终,通过调用Q#标准库中的操作来实现对Qubit的操作。
  • Pauli类型代表了单量子位Pauli组的一个元素。这种类型用于表示旋转的基本操作并指定测量的基础。这种类型是一种具有四种可能的价值观的区别联盟: PauliIPauliXPauliYPauliZ
  • Result类型表示测量结果。这种类型是具有两种可能值的区分联合: OneZeroZero表示测量+1特征值;One表示-1特征值。
  • Range类型表示一系列整数。
  • String类型是一系列对创建后的用户而言不透明的Unicode字符序列。这种类型用于将消息报告给经典主机。

请注意,这意味着truefalsePauliIPauliXPauliYPauliZOneZero都是Q#中的保留符号。

数组类型

给定任何有效的Q# 'T ,有一个类型表示一个类型为'T的值的数组。这个数组类型表示为'T[] ;例如, Qubit[]Int[][]

在第二个例子中,请注意,这表示一个可能锯齿状的数组数组,而不是一个矩形的二维数组。 Q#不包括对矩形多维数组的支持。

元组类型

给定任何有效的Q#类型'T1'T2'T3等,有一种类型代表类型为'T1'T2'T3等的值的元组。这个元组类型表示为('T1, 'T2, 'T3, …)任何数量的类型都可以拼凑在一起。空元组()与F#中的unit等效。

可以创建元组的数组,元组的元组,元组的元组等等。

元组实例是不可变的。 Q#没有提供一种机制来改变一旦创建的元组内容。

单身元组等价

可以创建一个单元(单元)元组, ('T1) ,如(5)([1;2;3])但是,Q#将单个元组视为完全等同于封闭类型的值。也就是说, 5(5)5(((5)))之间或(5, (6))(5, 6)(5, (6))之间没有差别。

这种等同适用于所有目的,包括分配和表达。(5)+35+3同样有效,并且两个表达式都将评估为8

我们将这个属性称为单一元组等价

用户定义的类型

AQ#文件可以基于标准类型定义新的命名类型。任何合法类型都可以用作用户定义类型的基础。

用户定义的类型可以在任何其他类型的地方使用。特别是,可以定义用户定义类型的数组并将用户定义类型包含为元组类型的元素。

不可能创建递归类型结构。也就是说,定义用户定义类型的类型可能不是包含用户定义类型元素的元组类型。更一般地说,用户定义的类型可能没有循环依赖关系,所以下面一组类型定义是非法的:

Q#
 newtype TypeA = (Int, TypeB);
newtype TypeB = (Double, TypeC);
newtype TypeC = (TypeA, Range); 

用户定义类型实例的可变性与用户定义类型基本类型实例的可变性相同。具体来说,基于元组的用户定义类型的实例是不可变的;基于数组的用户定义类型的实例可能是可变的。

类型兼容性

实际上,用户定义的类型是基类型的子类型。因此,用户定义类型的值可以在预计基类型值的任何位置使用。这是递归应用的。

例如,假设IntPair类型是一个具有基本类型(Int, Int)的用户定义类型,并且类型IntPair2是具有基本类型IntPair的用户定义类型。类型IntPair2的值可以用在IntPair2IntPair(Int, Int)类型的值的任何位置。IntPair类型的值可以用在IntPair类型的值或(Int, Int)值的任何位置。

基于相同基本类型的不同用户定义类型被视为不同和不相关的类型。在前面的示例中,如果IntPair3也是基类型(Int, Int)的用户定义类型,那么IntPairIntPair3是不相关的,如果期望另一个值,则值1不能使用。

操作和功能类型

AQ# 操作是一个量子子程序。也就是说,这是一个包含量子操作的可调用例程。

AQ# 函数是量子算法中使用的经典子程序。它可能包含经典代码,但不包含量子操作。函数不能分配或借用量子位,也不能调用操作。但是,可以将它们的操作或量子位传递给处理。

操作和功能一起被称为可召集

所有Q#可调参数都被视为输入单个值并返回单个值作为输出。输入和输出值都可以是元组。没有结果的可调参数返回空元组, () ;没有输入的可调参数将空元组作为输入。

任何可调用的基本签名都被写为('Tinput => 'Tresult)('Tinput -> 'Tresult) ,其中'Tinput'Tresult都是类型说明符。第一种形式,用=> ,用于操作;第二种形式,用->表示函数。例如, ((Qubit, Pauli) => Result)表示可能的单量子位测量操作的签名。

函数类型完全由其签名指定。例如,计算角度正弦的函数应该有类型(Double -> Double)

操作 - 但不是功能 - 可以允许应用一个或多个仿函数。函数是元操作,它生成一个基本操作的变体;见下面的Functors

操作类型由其签名和它们支持的函数列表指定。例如,Pauli X操作具有类型(Qubit => () : Adjoint, Controlled)不支持任何函子的操作类型仅由它的签名来指定,没有跟踪:

类型参数化的函数和操作

可调用签名可能包含类型参数。类型参数用带有单引号前缀的符号表示;例如, 'A是合法的类型参数。类型参数化的函数和操作与许多编程语言中的泛型函数类似,但Q#不提供完整的泛型类型/函数功能。

类型参数可能会在单个签名中出现多次。例如,一个将另一个函数应用于数组的每个元素并返回收集结果的函数将具有签名(('A[], 'A->'A) -> 'A[])类似地,返回两个操作组合的函数可能具有签名((('A=>'B), ('B=>'C)) -> ('A=>'C))

当调用一个类型参数化的可调用对象时,具有相同类型参数的所有参数必须是相同类型的,或者与相同类型兼容;那是。

Q#没有提供一种约束可能被类型参数替代的可能类型的机制。因此,类型参数主要用于数组上的函数和编写可调参数。

类型兼容性

支持附加函子的操作可以用于任何使用较少函子的操作,但预期具有相同的签名。例如,类型(Qubit=>():Adjoint)的操作可用于预期类型(Qubit=>())的操作的任何位置。

Q#对于可调用的返回类型是协变的:可返回类型'A的可调用对象与具有相同输入类型和'A兼容的结果类型的可调用对象兼容。

Q#与输入类型相反:一个可接受的类型'A作为输入与具有相同结果类型的可调用以及与'A兼容的输入类型兼容。

也就是说,给定以下类型定义:

 newtype IntPair : (Int, Int) 
newtype IntPairTransform : ((Int, Int) -> (Int, Int))
newType IntPairTransform2 : ((Int, Int) -> IntPair)   
newType IntPairTransform3 : (IntPair -> (Int, Int)) 

以下是事实:

  • IntPairTransform类型的值可以用IntPairTransform类型的单个参数来调用。
  • 调用IntPairTransform类型的函数的IntPairTransform可能不适用于需要IntPair类型的值的情况。
  • IntPairTransform2类型的值可以在预期IntPairTransform时使用,但反之亦然
  • IntPairTransform3被期望时,可以使用IntPairTransform3类型的值,但反之亦然

函子

Q#中的函数是一个工厂,它定义了另一个操作的新操作。在定义新操作的实现时,函子可以访问基本操作的实现。因此,仿函数可以执行比传统的更高级函数更复杂的功能。

通过将函数应用于操作来使用仿函数,并返回新的操作。例如,对Y操作应用Adjoint函子得到的操作写为(Adjoint Y)然后可以像任何其他操作一样调用新操作。因此, (Adjoint Y)(q1)将伴随函子应用于Y操作以生成新操作,并将该新操作应用于q1

同样, (Controlled X)(controls, target)

Q#中的两个标准函数是AdjointControlled

伴随

在量子计算中,伴随操作是操作的复共轭转置。对于实现单一运算符的操作,伴随点是操作的逆向操作。对于一个简单的操作,只需要对一组量子位调用一系列其他的单一操作,就可以通过在相同的量子位上以相反的顺序应用子操作的伴随来计算伴侣。

给定一个操作表达式,可以使用Adjoint函数形成一个新的操作表达式,基本操作表达式包含在圆括号()新操作与基本操作具有相同的签名和类型。特别是,新操作还允许Adjoint ,并且只有在基本操作完成时才允许Controlled

例如, (Adjoint QFT)指定QFT操作的伴随点。

受控

只有当所有控制量子位都处于指定状态时,操作的受控版本才是有效应用基本操作的新操作。如果控制量子位处于叠加状态,则将基本操作连贯地应用于叠加的适当部分。因此,经常使用受控操作来产生纠缠。

在Q#中,受控版本总是采用一系列控制量子位,并且指定的状态总是针对所有控制量子位处于计算( PauliZOne状态 ket1

中。基于其他状态的控制可以通过在受控操作之前将适当的克利福德操作应用于控制量子位,然后在受控操作之后应用克利弗舞蹈的逆向来实现。例如,在受控操作之前和之后对控制量子位应用X操作将导致操作对该量子位的Zero状态( ket0)进行控制;应用H操作将控制PauliXZero状态 ket+ mathrel= ket0+ ket1/ sqrt2

,而不是PauliZZero状态。

给定一个操作表达式,可以使用Controlled仿函数形成一个新的操作表达式,并将基本操作表达式括在圆括号()新操作的签名基于基本操作的签名。结果类型是相同的,但输入类型是一个具有量子比特数组的二元组,其将控制量子位作为第一个元素并将基本操作的参数作为第二个元素。如果基本操作没有引用() ,那么受控版本的输入类型就是控制量子位的数组。新操作允许Controlled ,并且只有在基本操作完成时才允许Adjoint

如果基本函数只有一个参数,那么单值元组等价将在这里发挥作用。例如, Controlled(X)X操作的受控版本。X具有类型(Qubit => () : Adjoint, Controlled) ,所以Controlled(X)具有类型((Qubit[], (Qubit)) => () : Adjoint, Controlled) ;由于单变元等价,这与((Qubit[], Qubit) => () : Adjoint, Controlled)

同样, Controlled(Rz)Rz操作的受控版本。Rz类型是((Double, Qubit) => () : Adjoint, Controlled) ,所以Controlled(Rz)类型是((Qubit[], (Double, Qubit)) => () : Adjoint, Controlled)例如, ((Controlled(Rz))(controls, (0.1, target))将是Controlled(Rz)的有效调用。

原网站

版权声明
本文为[MOVCat]所创,转载请带上原文链接,感谢
https://blog.csdn.net/f980511/article/details/80217270