/// <summary> /// Constructs a DocCallable instance given a namespace name and a callable object. /// </summary> /// <param name="ns">The name of the namespace where this callable is defined</param> /// <param name="callableObj">The compiled callable</param> internal DocCallable(string ns, QsCallable callableObj) : base( ns, callableObj.FullName.Name, callableObj.Kind.IsFunction ? Utils.FunctionKind : Utils.OperationKind, callableObj.Documentation, callableObj.Attributes) { this.syntax = Utils.CallableToSyntax(callableObj); this.inputContent = Utils.CallableToArguments(callableObj); this.outputType = Utils.ResolvedTypeToString(callableObj.Signature.ReturnType); this.functors = new List <string>(); foreach (var functor in callableObj.Signature.Information.Characteristics.SupportedFunctors.ValueOr(ImmutableHashSet <QsFunctor> .Empty)) { if (functor.IsAdjoint) { this.functors.Add(Functors.Adjoint); } else if (functor.IsControlled) { this.functors.Add(Functors.Controlled); } } this.callable = callableObj; }
private static List <Parameter> GetParams(QsCallable callable) { return(SyntaxGenerator.ExtractItems(callable.ArgumentTuple) .Where(sym => !sym.Type.Resolution.IsUnitType) .Select(sym => MakeParameter(sym)) .ToList()); }
public override QsCallable OnCallableDeclaration(QsCallable callable) { callable = base.OnCallableDeclaration(callable); // If the callable didn't come from a Q# source file, then it // came in from a reference, and shouldn't be documented in this // project. if (!callable.IsInCompilationUnit()) { return(callable); } var isDeprecated = callable.IsDeprecated(out var replacement); var docComment = new DocComment( callable.Documentation, callable.FullName.Name, deprecated: isDeprecated, replacement: replacement ); var callableName = $"{callable.FullName.Namespace}.{callable.FullName.Name}"; // Validate input and type parameter names. var inputDeclarations = callable.ArgumentTuple.ToDictionaryOfDeclarations(); this.ValidateNames( callableName, "input", name => inputDeclarations.ContainsKey(name), docComment.Input.Keys, range: null, // TODO: provide more exact locations once supported by DocParser. source: callable.SourceFile ); this.ValidateNames( callableName, "type parameter", name => callable.Signature.TypeParameters.Any( typeParam => typeParam is QsLocalSymbol.ValidName validName && validName.Item == name.TrimStart('\'') ), docComment.TypeParameters.Keys, range: null, // TODO: provide more exact locations once supported by DocParser. source: callable.SourceFile ); this.writer?.WriteOutput(callable, docComment)?.Wait(); return(callable .AttributeBuilder() .MaybeWithSimpleDocumentationAttribute("Summary", docComment.Summary) .MaybeWithSimpleDocumentationAttribute("Description", docComment.Description) .MaybeWithSimpleDocumentationAttribute("Remarks", docComment.Remarks) .MaybeWithSimpleDocumentationAttribute("References", docComment.References) .WithListOfDocumentationAttributes("SeeAlso", docComment.SeeAlso) .WithListOfDocumentationAttributes("Example", docComment.Examples) .WithDocumentationAttributesFromDictionary("Input", docComment.Input) .MaybeWithSimpleDocumentationAttribute("Output", docComment.Output) .WithDocumentationAttributesFromDictionary("TypeParameter", docComment.TypeParameters) .Build()); }
public override QsCallable beforeCallable(QsCallable c) { if (this.IsRelevant(c.SourceFile) && c.FullName.Equals(this.IdentifierName)) { this.DeclarationLocation = new Tuple <NonNullable <string>, QsLocation>(c.SourceFile, c.Location); } return(base.beforeCallable(c)); }
public override QsCallable OnCallableDeclaration(QsCallable c) { this.SharedState.SetCurrentCallable(c.FullName); c = base.OnCallableDeclaration(c); this.SharedState.SetCurrentCallable(null); var comment = $" {String.Join(", ", this.SharedState.IdentifiersInCallable(c.FullName))}"; return(AddComments(c, " Contained identifiers:", comment, "")); }
public override QsCallable OnCallableDeclaration(QsCallable c) { if (!this.SharedState.WithTrimming) { var node = new CallGraphNode(c.FullName); this.SharedState.CurrentNode = node; this.SharedState.Graph.AddNode(node); } return(base.OnCallableDeclaration(c)); }
public override QsCallable OnCallableDeclaration(QsCallable c) { if (!c.SourceFile.EndsWith(".qs", StringComparison.OrdinalIgnoreCase)) { return(c); } Console.WriteLine($"Callable: {c.FullName} in {c.SourceFile}"); var transformed = c.ToCaseDriveAccessModifier(); Console.WriteLine($" modifier: {c.Modifiers.Access} -> modifier: {transformed.Modifiers.Access}"); return(transformed); }
/// <summary> /// Generates a syntax string for a callable. /// This is, more or less, the same as the start of the callable definition, before the /// first opening {. /// </summary> /// <param name="callable">The callable (operation or function) to create a syntax string for</param> /// <returns>The syntax string</returns> internal static string CallableToSyntax(QsCallable callable) { var sb = new StringBuilder(); sb.Append(callable.Kind == QsCallableKind.Function ? "function " : "operation "); sb.Append(callable.FullName.Name); sb.Append(" "); sb.Append(CallableToArguments(callable)); sb.Append(" : "); sb.Append(ResolvedTypeToString(callable.Signature.ReturnType)); return(sb.ToString()); }
public override QsCallable OnCallableDeclaration(QsCallable c) { if (this.SharedState.Functions.IsBuiltIn(c.FullName)) { return(c); } this.context.SetCurrentCallable(c); c = base.OnCallableDeclaration(c); this.context.SetCurrentCallable(null); return(c); }
public override QsCallable OnCallableDeclaration(QsCallable c) { // Don't validate intrinsics if (this.SharedState.IntrinsicCallableSet.Contains(c.FullName)) { return(c); } else { return(base.OnCallableDeclaration(c)); } }
public override QsCallable onCallableImplementation(QsCallable c) { if (!this.IsRelevant(c.SourceFile) || c.Location.IsNull) { return(c); } if (c.FullName.Equals(this.IdentifierName)) { this.DeclarationLocation = new Tuple <NonNullable <string>, QsLocation>(c.SourceFile, c.Location.Item); } return(base.onCallableImplementation(c)); }
public override QsCallable OnCallableDeclaration(QsCallable c) { var unmangledName = NameDecorator.OriginalNameFromMonomorphized(c.FullName); if (this.SharedState.Functions.BuiltIn.ContainsKey(unmangledName)) { return(c); } this.context.SetCurrentCallable(c); c = base.OnCallableDeclaration(c); this.context.SetCurrentCallable(null); return(c); }
public static QsCallable ToCaseDriveAccessModifier(this QsCallable c) { var accessModifier = char.IsUpper(c.FullName.Name[0]) ? AccessModifier.DefaultAccess : AccessModifier.Internal; if (accessModifier.IsDefaultAccess == c.Modifiers.Access.IsDefaultAccess) { return(c); } return(new QsCallable( c.Kind, c.FullName, c.Attributes, new Modifiers(accessModifier), c.SourceFile, c.Location, c.Signature, c.ArgumentTuple, c.Specializations, c.Documentation, c.Comments)); }
private (QsCallable, ResolvedType) GenerateOperation(QsScope contents) { var newName = UniqueVariableNames.PrependGuid(this.CurrentCallable.Callable.FullName); var knownVariables = contents.KnownSymbols.Variables; var parameters = QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTuple(knownVariables .Select(var => QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTupleItem(new LocalVariableDeclaration <QsLocalSymbol>( QsLocalSymbol.NewValidName(var.VariableName), var.Type, new InferredExpressionInformation(false, false), var.Position, var.Range))) .ToImmutableArray()); var paramTypes = ResolvedType.New(ResolvedTypeKind.UnitType); if (knownVariables.Length == 1) { paramTypes = knownVariables.First().Type; } else if (knownVariables.Length > 1) { paramTypes = ResolvedType.New(ResolvedTypeKind.NewTupleType(knownVariables .Select(var => var.Type) .ToImmutableArray())); } var(signature, specializations) = this.MakeSpecializations(newName, paramTypes, SpecializationImplementation.NewProvided(parameters, contents)); var generatedCallable = new QsCallable( QsCallableKind.Operation, newName, ImmutableArray <QsDeclarationAttribute> .Empty, new Modifiers(AccessModifier.Internal), this.CurrentCallable.Callable.SourceFile, QsNullable <QsLocation> .Null, signature, parameters, specializations.ToImmutableArray(), ImmutableArray <string> .Empty, QsComments.Empty); // Change the origin of all type parameter references to use the new name and make all variables immutable generatedCallable = UpdateGeneratedOp.Apply(generatedCallable, knownVariables, this.CurrentCallable.Callable.FullName, newName); return(generatedCallable, signature.ArgumentType); }
/// <summary> /// Returns a formatted argument string for a Q# callable. /// </summary> /// <param name="callable">The operation or function to create an argument string for</param> /// <returns>The argument string</returns> internal static string CallableToArguments(QsCallable callable) { void ProcessTuple(StringBuilder builder, QsTuple <LocalVariableDeclaration <QsLocalSymbol> > tuple, bool topLevel) { if (tuple.IsQsTupleItem) { var item = ((QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .QsTupleItem)tuple).Item; if (topLevel) { builder.Append('('); } // Assumes that the symbol will never be invalid builder.Append(((QsLocalSymbol.ValidName)item.VariableName).Item); builder.Append(" : "); builder.Append(ResolvedTypeToString(item.Type)); if (topLevel) { builder.Append(')'); } } else { var items = ((QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .QsTuple)tuple).Item; builder.Append('('); var first = true; foreach (var item in items) { if (!first) { builder.Append(", "); } first = false; ProcessTuple(builder, item, false); } builder.Append(')'); } } var args = callable.ArgumentTuple; var sb = new StringBuilder(); ProcessTuple(sb, args, true); return(sb.ToString()); }
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 QsCallable OnCallableDeclaration(QsCallable c) { var relevantAccessModifiers = this.SharedState.GetAccessModifiers.Apply(this.SharedState.TypeParams.Values) .Append(c.Access); c = new QsCallable( c.Kind, c.FullName, c.Attributes, relevantAccessModifiers.Min(), c.Source, c.Location, c.Signature, c.ArgumentTuple, c.Specializations, c.Documentation, c.Comments); return(base.OnCallableDeclaration(c)); }
/// <summary> /// Given a documentation comment describing a Q# function or operation /// declaration, writes a Markdown file documenting that callable /// declaration to <see cref="OutputPath" />. /// </summary> /// <param name="callable">The Q# callable being documented.</param> /// <param name="docComment"> /// The API documentation comment describing <paramref name="callable"/>. /// </param> /// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns> public async Task WriteOutput(QsCallable callable, DocComment docComment) { // Make a new Markdown document for the type declaration. var kind = callable.Kind.Tag switch { QsCallableKind.Tags.Function => "function", QsCallableKind.Tags.Operation => "operation", QsCallableKind.Tags.TypeConstructor => "type constructor", _ => "<unknown>", }; var title = $@"{callable.FullName.Name} {kind}"; var header = new Dictionary <string, object> { // DocFX metadata ["uid"] = callable.FullName.ToString(), ["title"] = title, // docs.ms metadata ["ms.date"] = DateTime.Today.ToString(), ["ms.topic"] = "article", // Q# metadata ["qsharp.kind"] = kind, ["qsharp.namespace"] = callable.FullName.Namespace, ["qsharp.name"] = callable.FullName.Name, ["qsharp.summary"] = docComment.Summary, }; var document = $@" # {title} Namespace: [{callable.FullName.Namespace}](xref:{callable.FullName.Namespace}) {this.packageLink} {docComment.Summary} ```{this.LanguageMode} { callable.Kind.Tag switch { QsCallableKind.Tags.Function => "function ", QsCallableKind.Tags.Operation => "operation ", QsCallableKind.Tags.TypeConstructor => "newtype ", _ => "" } }{callable.ToSyntax()} ``` " .MaybeWithSection("Description", docComment.Description) .MaybeWithSection( "Input", string.Join("\n", callable.ArgumentTuple.InputDeclarations().Select( (item) => { (var inputName, var resolvedType) = item; var documentation = docComment.Input.TryGetValue(inputName, out var inputComment) ? inputComment : string.Empty; return($"### {inputName} : {resolvedType.ToMarkdownLink()}\n\n{documentation}\n\n"); } )) ) .WithSection($"Output : {callable.Signature.ReturnType.ToMarkdownLink()}", docComment.Output) .MaybeWithSection( "Type Parameters", string.Join("\n", callable.Signature.TypeParameters.Select( typeParam => typeParam is QsLocalSymbol.ValidName name ? $@"### '{name.Item}{"\n\n"}{( docComment.TypeParameters.TryGetValue($"'{name.Item}", out var comment) ? comment : string.Empty )}" : string.Empty )) ) .MaybeWithSection("Remarks", docComment.Remarks) .MaybeWithSection("References", docComment.References) .MaybeWithSection( "See Also", string.Join("\n", docComment.SeeAlso.Select( seeAlso => AsSeeAlsoLink(seeAlso, callable.FullName.Namespace) )) ) .WithYamlHeader(header); // Open a file to write the new doc to. await this.WriteAllTextAsync( $"{callable.FullName.Namespace}.{callable.FullName.Name}.md", document ); }
public override QsCallable OnCallableDeclaration(QsCallable c) => c.AddAttributes(this.SharedState.AttributeSelection .Where(entry => entry.Item2(c)) .Select(entry => entry.Item1));
public static QsCallable Apply(QsCallable callable, TypeParameterResolutions typeParams, GetAccessModifiers getAccessModifiers) { var filter = new ReplaceTypeParamImplementations(typeParams, getAccessModifiers); return(filter.Namespaces.OnCallableDeclaration(callable)); }
public void ExcludeInaccessible() { var elements = new[] { Access.Public, Access.Internal } .SelectMany(access => { var source = new Source("Tests.qs", QsNullable <string> .Null); var unit = ResolvedType.New(QsType.UnitType); var signature = new ResolvedSignature( Array.Empty <QsLocalSymbol>().ToImmutableArray(), unit, unit, CallableInformation.NoInformation); var argumentTuple = QsTuple <ArgDeclType> .NewQsTuple(ImmutableArray.Create <QsTuple <ArgDeclType> >()); var callable = new QsCallable( kind: QsCallableKind.Operation, fullName: MakeFullName(access + "Operation"), attributes: ImmutableArray <QsDeclarationAttribute> .Empty, access, source: source, location: ZeroLocation, signature: signature, argumentTuple: argumentTuple, specializations: ImmutableArray.Create <QsSpecialization>(), documentation: ImmutableArray.Create <string>(), comments: QsComments.Empty); var typeItems = QsTuple <QsTypeItem> .NewQsTuple( ImmutableArray.Create(QsTuple <QsTypeItem> .NewQsTupleItem(QsTypeItem.NewAnonymous(unit)))); var type = new QsCustomType( fullName: MakeFullName(access + "Type"), attributes: ImmutableArray <QsDeclarationAttribute> .Empty, access, source: source, location: ZeroLocation, type: unit, typeItems: typeItems, documentation: ImmutableArray.Create <string>(), comments: QsComments.Empty); return(new[] { QsNamespaceElement.NewQsCallable(callable), QsNamespaceElement.NewQsCustomType(type) }); }); var emptyLookup = Array.Empty <ImmutableArray <string> >().ToLookup(x => ""); var ns = new QsNamespace(CanonName, elements.ToImmutableArray(), emptyLookup); var docNs = new DocNamespace(ns); var stream = new MemoryStream(); #pragma warning disable 618 // WriteToStream is obsolete. docNs.WriteToStream(stream, null); #pragma warning restore 618 var expected = @"### YamlMime:QSharpNamespace # This file is automatically generated. # Please do not modify this file manually, or your changes may be lost when # documentation is rebuilt. uid: microsoft.quantum.canon name: Microsoft.Quantum.Canon operations: - uid: microsoft.quantum.canon.publicoperation summary: '' newtypes: - uid: microsoft.quantum.canon.publictype summary: '' ... "; var actual = Encoding.UTF8.GetString(stream.ToArray()); Assert.Equal(expected, actual); }
private static QsCallable AddComments(QsCallable c, params string[] comments) => new QsCallable( c.Kind, c.FullName, c.Attributes, c.Modifiers, c.SourceFile, c.Location, c.Signature, c.ArgumentTuple, c.Specializations, c.Documentation, new QsComments(c.Comments.OpeningComments.AddRange(comments), c.Comments.ClosingComments));
public override QsCallable OnFunction(QsCallable c) => c; // Prevent anything in functions from being considered
public static QsCallable Apply(QsCallable qsCallable, ImmutableArray <LocalVariableDeclaration <NonNullable <string> > > parameters, QsQualifiedName oldName, QsQualifiedName newName) { var filter = new UpdateGeneratedOp(parameters, oldName, newName); return(filter.Namespaces.OnCallableDeclaration(qsCallable)); }
/// <inheritdoc/> public override QsCallable OnCallableDeclaration(QsCallable c) { this.SharedState.CurrentCallable = new LiftContent.CallableDetails(c); return(base.OnCallableDeclaration(c)); }
public static QsCallable Apply(QsCallable current, GetConcreteIdentifierFunc getConcreteIdentifier, ImmutableHashSet <QsQualifiedName> intrinsicCallableSet) { var filter = new ReplaceTypeParamCalls(getConcreteIdentifier, intrinsicCallableSet); return(filter.Namespaces.OnCallableDeclaration(current)); }
/// <summary> /// Generates a new operation with the body's contents. All the known variables at the /// start of the block will become parameters to the new operation, and the operation /// will have all the valid type parameters of the calling context as type parameters. /// The generated operation is returned, along with a call to the new operation is /// also returned with all the type parameters and known variables being forwarded to /// the new operation as arguments. /// /// The given body should be validated with the SharedState.IsValidScope before using this function. /// </summary> public bool LiftBody(QsScope body, out QsCallable callable, out QsStatement callStatement) { if (!this.IsValidScope) { callable = null; callStatement = null; return(false); } var(generatedOp, originalArgumentType) = this.GenerateOperation(body); var generatedOpType = ResolvedType.New(ResolvedTypeKind.NewOperation( Tuple.Create( originalArgumentType, ResolvedType.New(ResolvedTypeKind.UnitType)), generatedOp.Signature.Information)); // Forward the type parameters of the parent callable to the type arguments of the call to the generated operation. var typeArguments = this.CurrentCallable.TypeParameters; var generatedOpId = new TypedExpression( ExpressionKind.NewIdentifier( Identifier.NewGlobalCallable(generatedOp.FullName), typeArguments), typeArguments.IsNull ? TypeArgsResolution.Empty : typeArguments.Item .Select(type => Tuple.Create(generatedOp.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type)) .ToImmutableArray(), generatedOpType, new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); var knownSymbols = body.KnownSymbols.Variables; TypedExpression arguments = null; if (knownSymbols.Any()) { var argumentArray = knownSymbols .Select(var => new TypedExpression( ExpressionKind.NewIdentifier( Identifier.NewLocalVariable(var.VariableName), QsNullable <ImmutableArray <ResolvedType> > .Null), TypeArgsResolution.Empty, var.Type, var.InferredInformation, QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null)) .ToImmutableArray(); arguments = new TypedExpression( ExpressionKind.NewValueTuple(argumentArray), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewTupleType(argumentArray.Select(expr => expr.ResolvedType).ToImmutableArray())), new InferredExpressionInformation(false, argumentArray.Any(exp => exp.InferredInformation.HasLocalQuantumDependency)), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); } else { arguments = new TypedExpression( ExpressionKind.UnitValue, TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.UnitType), new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); } var call = new TypedExpression( ExpressionKind.NewCallLikeExpression(generatedOpId, arguments), typeArguments.IsNull ? TypeArgsResolution.Empty : typeArguments.Item .Select(type => Tuple.Create(this.CurrentCallable.Callable.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type)) .ToImmutableArray(), ResolvedType.New(ResolvedTypeKind.UnitType), new InferredExpressionInformation(false, true), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); // set output parameters callable = generatedOp; callStatement = new QsStatement( QsStatementKind.NewQsExpressionStatement(call), LocalDeclarations.Empty, QsNullable <QsLocation> .Null, QsComments.Empty); return(true); }
public override QsCallable onOperation(QsCallable c) => this.IsRelevant(c.SourceFile) ? base.onOperation(c) : c;
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); }
/// <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); } }