public override QsSpecialization OnSpecializationDeclaration(QsSpecialization spec) { this.context.SetCurrentSpecialization(spec); spec = base.OnSpecializationDeclaration(spec); this.context.SetCurrentSpecialization(null); return(spec); }
/// <inheritdoc/> public override QsSpecialization OnControlledAdjointSpecialization(QsSpecialization spec) { this.SharedState.InControlledAdjoint = true; var rtrn = base.OnControlledAdjointSpecialization(spec); this.SharedState.InControlledAdjoint = false; return rtrn; }
/// <inheritdoc/> public override QsSpecialization OnBodySpecialization(QsSpecialization spec) { this.SharedState.InBody = true; var rtrn = base.OnBodySpecialization(spec); this.SharedState.InBody = false; return rtrn; }
/// <inheritdoc/> public override QsSpecialization OnControlledSpecialization(QsSpecialization spec) { this.SharedState.InControlled = true; var rtrn = base.OnControlledSpecialization(spec); this.SharedState.InControlled = false; return(rtrn); }
/// <inheritdoc/> public override QsSpecialization OnAdjointSpecialization(QsSpecialization spec) { this.SharedState.InAdjoint = true; var rtrn = base.OnAdjointSpecialization(spec); this.SharedState.InAdjoint = false; return(rtrn); }
internal CallableDetails(QsCallable callable) { this.Callable = callable; // ToDo: this may need to be adapted once we support type specializations this.Adjoint = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsAdjoint); this.Controlled = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlled); this.ControlledAdjoint = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlledAdjoint); // ToDo: this may need to be per-specialization this.TypeParameters = callable.Signature.TypeParameters.Any(param => param.IsValidName) ? QsNullable <ImmutableArray <ResolvedType> > .NewValue(callable.Signature.TypeParameters .Where(param => param.IsValidName) .Select(param => ResolvedType.New(ResolvedTypeKind.NewTypeParameter(new QsTypeParameter( callable.FullName, ((QsLocalSymbol.ValidName)param).Item, QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null)))) .ToImmutableArray()) : QsNullable <ImmutableArray <ResolvedType> > .Null; }
public override QsSpecialization OnSpecializationDeclaration(QsSpecialization spec) // short cut to avoid further evaluation { this.OnSourceFile(spec.SourceFile); return(spec); }
public void ParseOp() { ArgDeclType BuildArgument(string name, ResolvedType t) { var validName = QsLocalSymbol.NewValidName(NonNullable <string> .New(name)); var info = new InferredExpressionInformation(false, false); return(new ArgDeclType(validName, t, info, QsNullable <Tuple <int, int> > .Null, EmptyRange)); } string[] comments = { "# Summary", "Convenience function that performs state preparation by applying a ", "`statePrepUnitary` on the input state, followed by adiabatic state ", "preparation using a `adiabaticUnitary`, and finally phase estimation ", "with respect to `qpeUnitary`on the resulting state using a ", "`phaseEstAlgorithm`.", "", "# Input", "## statePrepUnitary", "An oracle representing state preparation for the initial dynamical", "generator.", "## adiabaticUnitary", "An oracle representing the adiabatic evolution algorithm to be used", "to implement the sweeps to the final state of the algorithm.", "## qpeUnitary", "An oracle representing a unitary operator $U$ representing evolution", "for time $\\delta t$ under a dynamical generator with ground state", "$\\ket{\\phi}$ and ground state energy $E = \\phi\\\\,\\delta t$.", "## phaseEstAlgorithm", "An operation that performs phase estimation on a given unitary operation.", "See [iterative phase estimation](/quantum/libraries/characterization#iterative-phase-estimation)", "for more details.", "## qubits", "A register of qubits to be used to perform the simulation.", "", "# Output", "An estimate $\\hat{\\phi}$ of the ground state energy $\\phi$", "of the generator represented by $U$." }; string expected = @"### YamlMime:QSharpType uid: microsoft.quantum.canon.adiabaticstateenergyunitary name: AdiabaticStateEnergyUnitary type: operation namespace: Microsoft.Quantum.Canon summary: |- Convenience function that performs state preparation by applying a `statePrepUnitary` on the input state, followed by adiabatic state preparation using a `adiabaticUnitary`, and finally phase estimation with respect to `qpeUnitary`on the resulting state using a `phaseEstAlgorithm`. syntax: 'operation AdiabaticStateEnergyUnitary (statePrepUnitary : (Qubit[] => Unit), adiabaticUnitary : (Qubit[] => Unit), qpeUnitary : (Qubit[] => Unit is Adj + Ctl), phaseEstAlgorithm : ((Microsoft.Quantum.Canon.DiscreteOracle, Qubit[]) => Double), qubits : Qubit[]) : Double' input: content: '(statePrepUnitary : (Qubit[] => Unit), adiabaticUnitary : (Qubit[] => Unit), qpeUnitary : (Qubit[] => Unit is Adj + Ctl), phaseEstAlgorithm : ((Microsoft.Quantum.Canon.DiscreteOracle, Qubit[]) => Double), qubits : Qubit[])' types: - name: statePrepUnitary summary: |- An oracle representing state preparation for the initial dynamical generator. isOperation: true input: types: - isArray: true isPrimitive: true uid: Qubit output: types: - isPrimitive: true uid: Unit - name: adiabaticUnitary summary: |- An oracle representing the adiabatic evolution algorithm to be used to implement the sweeps to the final state of the algorithm. isOperation: true input: types: - isArray: true isPrimitive: true uid: Qubit output: types: - isPrimitive: true uid: Unit - name: qpeUnitary summary: |- An oracle representing a unitary operator $U$ representing evolution for time $\delta t$ under a dynamical generator with ground state $\ket{\phi}$ and ground state energy $E = \phi\\,\delta t$. isOperation: true input: types: - isArray: true isPrimitive: true uid: Qubit output: types: - isPrimitive: true uid: Unit functors: - Adjoint - Controlled - name: phaseEstAlgorithm summary: |- An operation that performs phase estimation on a given unitary operation. See [iterative phase estimation](/quantum/libraries/characterization#iterative-phase-estimation) for more details. isOperation: true input: types: - uid: microsoft.quantum.canon.discreteoracle - isArray: true isPrimitive: true uid: Qubit output: types: - isPrimitive: true uid: Double - name: qubits summary: A register of qubits to be used to perform the simulation. isArray: true isPrimitive: true uid: Qubit output: content: Double types: - summary: |- An estimate $\hat{\phi}$ of the ground state energy $\phi$ of the generator represented by $U$. isPrimitive: true uid: Double ... "; var qubitArrayType = ResolvedType.New(QsType.NewArrayType(ResolvedType.New(QsType.Qubit))); var unitType = ResolvedType.New(QsType.UnitType); var doubleType = ResolvedType.New(QsType.Double); var oracleType = ResolvedType.New(QsType.NewUserDefinedType(new UserDefinedType(CanonName, NonNullable <string> .New("DiscreteOracle"), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null))); var noInfo = CallableInformation.NoInformation; var acFunctors = ResolvedCharacteristics.FromProperties(new[] { OpProperty.Adjointable, OpProperty.Controllable }); var acInfo = new CallableInformation(acFunctors, InferredCallableInformation.NoInformation); var qubitToUnitOp = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(qubitArrayType, unitType), noInfo)); var qubitToUnitOpAC = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(qubitArrayType, unitType), acInfo)); var phaseEstArgs = new ResolvedType[] { oracleType, qubitArrayType }.ToImmutableArray(); var phaseEstArgTuple = ResolvedType.New(QsType.NewTupleType(phaseEstArgs)); var phaseEstOp = ResolvedType.New(QsType.NewOperation(new SigTypeTuple(phaseEstArgTuple, doubleType), noInfo)); var typeParams = new QsLocalSymbol[] { }.ToImmutableArray(); var argTypes = new ResolvedType[] { qubitToUnitOp, qubitToUnitOp, qubitToUnitOpAC, phaseEstOp, qubitArrayType }.ToImmutableArray(); var argTupleType = ResolvedType.New(QsType.NewTupleType(argTypes)); var signature = new ResolvedSignature(typeParams, argTupleType, doubleType, noInfo); var args = new List <ArgDeclType> { BuildArgument("statePrepUnitary", qubitToUnitOp), BuildArgument("adiabaticUnitary", qubitToUnitOp), BuildArgument("qpeUnitary", qubitToUnitOpAC), BuildArgument("phaseEstAlgorithm", phaseEstOp), BuildArgument("qubits", qubitArrayType) } .ConvertAll(arg => QsTuple <ArgDeclType> .NewQsTupleItem(arg)) .ToImmutableArray(); var argTuple = QsTuple <ArgDeclType> .NewQsTuple(args); var specs = new QsSpecialization[] { }.ToImmutableArray(); var qsCallable = new QsCallable(QsCallableKind.Operation, MakeFullName("AdiabaticStateEnergyUnitary"), ImmutableArray <QsDeclarationAttribute> .Empty, NonNullable <string> .New("Techniques.qs"), ZeroLocation, signature, argTuple, specs, comments.ToImmutableArray(), QsComments.Empty); var callable = new DocCallable("Microsoft.Quantum.Canon", qsCallable); var stream = new StringWriter(); callable.WriteToFile(stream); var s = stream.ToString(); Assert.Equal(expected, s); }
public override QsSpecialization onSpecializationImplementation(QsSpecialization spec) => this.IsRelevant(spec.SourceFile) ? base.onSpecializationImplementation(spec) : spec;
/// <summary> /// Creates a separate callable for each intrinsic specialization, /// and replaces the specialization implementations of the original callable with a call to these. /// Self adjoint generation directives in intrinsic callables are replaced by a provided implementation. /// Type constructors and generic callables or callables that already define a target instruction name are left unchanged. /// </summary> /// <exception cref="ArgumentException"> /// An intrinsic callable contains non-intrinsic specializations /// or a non-intrinsic callable contains intrinsic specializations, /// or the a callable doesn't have a body specialization. /// </exception> /// <exception cref="InvalidOperationException"> /// A specialization has explicit type arguments; /// Monomorphization needs to run before separating target instructions. /// </exception> private static QsNamespace LiftIntrinsicSpecializations(QsNamespace ns) { var elements = ImmutableArray.CreateBuilder <QsNamespaceElement>(); foreach (var element in ns.Elements) { if (element is QsNamespaceElement.QsCallable c && c.Item.Signature.TypeParameters.Length == 0 && !c.Item.Kind.IsTypeConstructor) { if (c.Item.IsIntrinsic) { QsCallable callable = c.Item; if (!callable.Specializations.Any(spec => spec.Kind.IsQsBody)) { throw new ArgumentException("missing body specialization"); } else if (callable.Specializations.Any(spec => spec.TypeArguments.IsValue)) { throw new InvalidOperationException("specialization with type arguments"); } else if (callable.Specializations.Length == 1 && callable.Attributes.Any(BuiltIn.DefinesTargetInstruction)) { elements.Add(element); } else { QsQualifiedName GeneratedName(QsSpecializationKind kind) => new QsQualifiedName(callable.FullName.Namespace, $"{callable.FullName.Name}{SpecializationSuffix(kind)}"); var specializations = ImmutableArray.CreateRange(callable.Specializations.Select(spec => { var inferredInfo = spec.Signature.Information.InferredInformation; if (!inferredInfo.IsIntrinsic && !inferredInfo.IsSelfAdjoint) { throw new ArgumentException("non-intrinsic specialization for intrinsic callable"); } // Get the correct argument tuple both for the added intrinsic callable // and the generated provided specialization that replaces the intrinsic one. var argTuple = BuildSpecArgTuple(callable.ArgumentTuple, spec.Kind); // Create a separate callable for that specialization, // unless the specialization is not needed for a self-adjoint callable. var genCallableSignature = new ResolvedSignature( ImmutableArray <QsLocalSymbol> .Empty, spec.Signature.ArgumentType, spec.Signature.ReturnType, new CallableInformation( ResolvedCharacteristics.Empty, new InferredCallableInformation(isIntrinsic: true, isSelfAdjoint: false))); var genCallableName = GeneratedName( inferredInfo.IsSelfAdjoint && spec.Kind.IsQsAdjoint ? QsSpecializationKind.QsBody : inferredInfo.IsSelfAdjoint && spec.Kind.IsQsControlledAdjoint ? QsSpecializationKind.QsControlled : spec.Kind); if (!inferredInfo.IsSelfAdjoint || spec.Kind.IsQsBody || spec.Kind.IsQsControlled) { var genCallableBody = new QsSpecialization( QsSpecializationKind.QsBody, genCallableName, spec.Attributes, spec.Source, QsNullable <QsLocation> .Null, spec.TypeArguments, genCallableSignature, SpecializationImplementation.Intrinsic, spec.Documentation, spec.Comments); var genCallable = new QsCallable( callable.Kind, genCallableName, callable.Attributes, callable.Access, spec.Source, spec.Location, genCallableSignature, argTuple, ImmutableArray.Create(genCallableBody), ImmutableArray <string> .Empty, QsComments.Empty); elements.Add(QsNamespaceElement.NewQsCallable(genCallable)); } // Create a specialization that calls into the generated callable, // or the corresponding callable no callable for the specialization // has been added due to hte operation being self-adjoint. var genCallableType = callable.Kind == QsCallableKind.Operation ? OperationTypeFromSignature(genCallableSignature) : TypeKind.NewFunction(genCallableSignature.ArgumentType, genCallableSignature.ReturnType); var call = SyntaxGenerator.CallNonGeneric( IdentifierForCallable(genCallableName, genCallableType), SyntaxGenerator.ArgumentTupleAsExpression(argTuple)); var statement = new QsStatement( QsStatementKind.NewQsReturnStatement(call), LocalDeclarations.Empty, QsNullable <QsLocation> .Null, QsComments.Empty); var localDeclarations = new LocalDeclarations( SyntaxGenerator.ValidDeclarations(SyntaxGenerator.ExtractItems(argTuple))); return(spec.WithImplementation(SpecializationImplementation.NewProvided( argTuple, new QsScope(ImmutableArray.Create(statement), localDeclarations)))); })); // Create a callable that contains all specializations that // call into the generated callables for each specialization. var inlineAttribute = AttributeUtils.BuildAttribute(BuiltIn.Inline.FullName, SyntaxGenerator.UnitValue); var signature = new ResolvedSignature( ImmutableArray <QsLocalSymbol> .Empty, callable.Signature.ArgumentType, callable.Signature.ReturnType, new CallableInformation( callable.Signature.Information.Characteristics, new InferredCallableInformation(isSelfAdjoint: callable.IsSelfAdjoint, isIntrinsic: false))); var redirect = new QsCallable( callable.Kind, callable.FullName, ImmutableArray.Create(inlineAttribute), callable.Access, callable.Source, callable.Location, signature, callable.ArgumentTuple, specializations, callable.Documentation, callable.Comments); elements.Add(QsNamespaceElement.NewQsCallable(redirect)); } } else if (c.Item.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) { throw new ArgumentException("intrinsic specialization for non-intrinsic callable"); } else { elements.Add(element); } }