/// <summary> /// Gets an identifier and argument tuple for the built-in operation NoOp. /// </summary> private (TypedExpression, TypedExpression) GetNoOp() { var opInfo = BuiltIn.NoOp; var properties = new[] { OpProperty.Adjointable, OpProperty.Controllable }; var characteristics = new CallableInformation( ResolvedCharacteristics.FromProperties(properties), new InferredCallableInformation(((BuiltInKind.Operation)opInfo.Kind).IsSelfAdjoint, false)); var unitType = ResolvedType.New(ResolvedTypeKind.UnitType); var operationType = ResolvedType.New(ResolvedTypeKind.NewOperation( Tuple.Create(unitType, unitType), characteristics)); var args = new TypedExpression( ExpressionKind.UnitValue, TypeArgsResolution.Empty, unitType, new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); var typeArgs = ImmutableArray.Create(unitType); var identifier = new TypedExpression( ExpressionKind.NewIdentifier( Identifier.NewGlobalCallable(opInfo.FullName), QsNullable <ImmutableArray <ResolvedType> > .NewValue(typeArgs)), typeArgs .Zip(((BuiltInKind.Operation)opInfo.Kind).TypeParameters, (type, param) => Tuple.Create(opInfo.FullName, param, type)) .ToImmutableArray(), operationType, new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); return(identifier, args); }
/// <summary> /// Creates a value tuple expression containing the given expressions. /// </summary> private TypedExpression CreateValueTupleExpression(params TypedExpression[] expressions) => new TypedExpression( ExpressionKind.NewValueTuple(expressions.ToImmutableArray()), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewTupleType(expressions.Select(expr => expr.ResolvedType).ToImmutableArray())), new InferredExpressionInformation(false, expressions.Any(exp => exp.InferredInformation.HasLocalQuantumDependency)), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
// Takes a single TypedExpression of type Result and puts in into a // value array expression with the given expression as its only item. static TypedExpression BoxResultInArray(TypedExpression expression) => new TypedExpression( ExpressionKind.NewValueArray(ImmutableArray.Create(expression)), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Result))), new InferredExpressionInformation(false, expression.InferredInformation.HasLocalQuantumDependency), QsNullable <Range> .Null);
internal static TypedExpression CreateCallLikeExpression(TypedExpression id, TypedExpression args, TypeArgsResolution typeRes) => new TypedExpression ( ExpressionKind.NewCallLikeExpression(id, args), typeRes, ResolvedType.New(ResolvedTypeKind.UnitType), new InferredExpressionInformation(false, true), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null );
internal static TypedExpression CreateValueTupleExpression(params TypedExpression[] expressions) => new TypedExpression ( ExpressionKind.NewValueTuple(expressions.ToImmutableArray()), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewTupleType(expressions.Select(expr => expr.ResolvedType).ToImmutableArray())), new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null );
internal static ResolvedType GetOperationType(IEnumerable <OpProperty> props, ResolvedType argumentType) { var characteristics = new CallableInformation( ResolvedCharacteristics.FromProperties(props), InferredCallableInformation.NoInformation); return(ResolvedType.New(ResolvedTypeKind.NewOperation( Tuple.Create(argumentType, ResolvedType.New(ResolvedTypeKind.UnitType)), characteristics))); }
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> /// Creates an operation call from the conditional control API, given information /// about which operation to call and with what arguments. /// </summary> private TypedExpression CreateControlCall(BuiltIn opInfo, IEnumerable <OpProperty> properties, TypedExpression args, IEnumerable <ResolvedType> typeArgs) { var characteristics = new CallableInformation( ResolvedCharacteristics.FromProperties(properties), new InferredCallableInformation(((BuiltInKind.Operation)opInfo.Kind).IsSelfAdjoint, false)); var unitType = ResolvedType.New(ResolvedTypeKind.UnitType); var operationType = ResolvedType.New(ResolvedTypeKind.NewOperation( Tuple.Create(args.ResolvedType, unitType), characteristics)); // Build the surrounding control call var identifier = new TypedExpression( ExpressionKind.NewIdentifier( Identifier.NewGlobalCallable(opInfo.FullName), typeArgs.Any() ? QsNullable <ImmutableArray <ResolvedType> > .NewValue(typeArgs.ToImmutableArray()) : QsNullable <ImmutableArray <ResolvedType> > .Null), typeArgs .Zip(((BuiltInKind.Operation)opInfo.Kind).TypeParameters, (type, param) => Tuple.Create(opInfo.FullName, param, type)) .ToImmutableArray(), operationType, new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); // Creates type resolutions for the call expression var opTypeArgResolutions = typeArgs .SelectMany(x => x.Resolution is ResolvedTypeKind.TupleType tup ? tup.Item : ImmutableArray.Create(x)) .Where(x => x.Resolution.IsTypeParameter) .Select(x => (x.Resolution as ResolvedTypeKind.TypeParameter).Item) .GroupBy(x => (x.Origin, x.TypeName)) .Select(group => { var typeParam = group.First(); return(Tuple.Create(typeParam.Origin, typeParam.TypeName, ResolvedType.New(ResolvedTypeKind.NewTypeParameter(typeParam)))); }) .ToImmutableArray(); return(new TypedExpression( ExpressionKind.NewCallLikeExpression(identifier, args), opTypeArgResolutions, unitType, new InferredExpressionInformation(false, true), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null)); }
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; }
/// <summary> /// Creates an array literal with the given items, setting the range information to Null. /// If no items are given, creates an empty array of type Unit[]. /// The resolved types for all of the given expressions must match, /// none of the given expressions should have a local quantum dependency, /// and all range information should be stripped from each given expression. /// </summary> internal static TypedExpression CreateValueArray(params TypedExpression[] expressions) { ResolvedType type = null; if (expressions.Any()) { type = expressions.First().ResolvedType; QsCompilerError.Verify(expressions.All(expr => expr.ResolvedType.Equals(type))); } else { type = ResolvedType.New(ResolvedTypeKind.UnitType); } return(new TypedExpression ( ExpressionKind.NewValueArray(expressions.ToImmutableArray()), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(type)), new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null )); }
/// <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 void ParseUdt() { string[] comments = { "# Summary", "Represents a single primitive term in the set of all dynamical generators, e.g.", "Hermitian operators, for which there exists a map from that generator", "to time-evolution by that that generator, through \"EvolutionSet\".", "", "# Description", "The first element", "(Int[], Double[]) is indexes that single term -- For instance, the Pauli string", "XXY with coefficient 0.5 would be indexed by ([1,1,2], [0.5]). Alternatively,", "Hamiltonians parameterized by a continuous variable, such as X cos φ + Y sin φ,", "might for instance be represented by ([], [φ]). The second", "element indexes the subsystem on which the generator acts on.", "", "# Remarks", "> [!WARNING]", "> The interpretation of an `GeneratorIndex` is not defined except", "> with reference to a particular set of generators.", "", "# Example", "Using <xref:microsoft.quantum.canon.paulievolutionset>, the operator", "$\\pi X_2 X_5 Y_9$ is represented as:", "```qsharp", "let index = GeneratorIndex(([1; 1; 2], [PI()]), [2; 5; 9]);", "```", "", "# See Also", "- @\"microsoft.quantum.canon.paulievolutionset\"", "- @\"microsoft.quantum.canon.evolutionset\"" }; string expected = @"### YamlMime:QSharpType uid: microsoft.quantum.canon.generatorindex name: GeneratorIndex type: newtype namespace: Microsoft.Quantum.Canon summary: |- Represents a single primitive term in the set of all dynamical generators, e.g. Hermitian operators, for which there exists a map from that generator to time-evolution by that that generator, through ""EvolutionSet"". The first element (Int[], Double[]) is indexes that single term -- For instance, the Pauli string XXY with coefficient 0.5 would be indexed by ([1,1,2], [0.5]). Alternatively, Hamiltonians parameterized by a continuous variable, such as X cos φ + Y sin φ, might for instance be represented by ([], [φ]). The second element indexes the subsystem on which the generator acts on. remarks: |- > [!WARNING] > The interpretation of an `GeneratorIndex` is not defined except > with reference to a particular set of generators. ### Examples Using <xref:microsoft.quantum.canon.paulievolutionset>, the operator $\pi X_2 X_5 Y_9$ is represented as: ```qsharp let index = GeneratorIndex(([1; 1; 2], [PI()]), [2; 5; 9]); ``` syntax: newtype GeneratorIndex = ((Int[], Double[]), Int[]); seeAlso: - microsoft.quantum.canon.paulievolutionset - microsoft.quantum.canon.evolutionset ... "; var intArrayType = ResolvedType.New(QsType.NewArrayType(ResolvedType.New(QsType.Int))); var doubleArrayType = ResolvedType.New(QsType.NewArrayType(ResolvedType.New(QsType.Double))); var innerTuple = new ResolvedType[] { intArrayType, doubleArrayType }.ToImmutableArray(); var innerTupleType = ResolvedType.New(QsType.NewTupleType(innerTuple)); var baseTuple = new ResolvedType[] { innerTupleType, intArrayType }.ToImmutableArray(); var baseType = ResolvedType.New(QsType.NewTupleType(baseTuple)); var anonymousItem = QsTuple <QsTypeItem> .NewQsTupleItem(QsTypeItem.NewAnonymous(baseType)); var typeItems = QsTuple <QsTypeItem> .NewQsTuple(ImmutableArray.Create(anonymousItem)); var generatorIndexType = new QsCustomType(MakeFullName("GeneratorIndex"), ImmutableArray <QsDeclarationAttribute> .Empty, NonNullable <string> .New("GeneratorRepresentation.qs"), ZeroLocation, baseType, typeItems, comments.ToImmutableArray(), QsComments.Empty); var udt = new DocUdt("Microsoft.Quantum.Canon", generatorIndexType); var stream = new StringWriter(); udt.WriteToFile(stream); var s = stream.ToString(); Assert.Equal(expected, s); }
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); }
internal QirValues(GenerationContext context, Constants constants) { this.sharedState = context; this.Unit = new SimpleValue(constants.UnitValue, ResolvedType.New(ResolvedTypeKind.UnitType)); }
/// <summary> /// Creates an operation call from the conditional control API for non-literal Result comparisons. /// The equalityScope and inequalityScope cannot both be null. /// </summary> private TypedExpression CreateApplyConditionallyExpression(TypedExpression conditionExpr1, TypedExpression conditionExpr2, QsScope equalityScope, QsScope inequalityScope) { QsCompilerError.Verify(equalityScope != null || inequalityScope != null, $"Cannot have null for both equality and inequality scopes when creating ApplyConditionally expressions."); var(isEqualityValid, equalityId, equalityArgs) = this.IsValidScope(equalityScope); var(isInequaltiyValid, inequalityId, inequalityArgs) = this.IsValidScope(inequalityScope); if (!isEqualityValid && equalityScope != null) { return(null); // ToDo: Diagnostic message - equality block exists, but is not valid } if (!isInequaltiyValid && inequalityScope != null) { return(null); // ToDo: Diagnostic message - inequality block exists, but is not valid } if (equalityScope == null) { (equalityId, equalityArgs) = this.GetNoOp(); } else if (inequalityScope == null) { (inequalityId, inequalityArgs) = this.GetNoOp(); } // Get characteristic properties from global id var props = ImmutableHashSet <OpProperty> .Empty; if (equalityId.ResolvedType.Resolution is ResolvedTypeKind.Operation op) { props = op.Item2.Characteristics.GetProperties(); if (inequalityId != null && inequalityId.ResolvedType.Resolution is ResolvedTypeKind.Operation defaultOp) { props = props.Intersect(defaultOp.Item2.Characteristics.GetProperties()); } } BuiltIn controlOpInfo; (bool adj, bool ctl) = (props.Contains(OpProperty.Adjointable), props.Contains(OpProperty.Controllable)); if (adj && ctl) { controlOpInfo = BuiltIn.ApplyConditionallyCA; } else if (adj) { controlOpInfo = BuiltIn.ApplyConditionallyA; } else if (ctl) { controlOpInfo = BuiltIn.ApplyConditionallyC; } else { controlOpInfo = BuiltIn.ApplyConditionally; } // Takes a single TypedExpression of type Result and puts in into a // value array expression with the given expression as its only item. TypedExpression BoxResultInArray(TypedExpression expression) => new TypedExpression( ExpressionKind.NewValueArray(ImmutableArray.Create(expression)), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Result))), new InferredExpressionInformation(false, expression.InferredInformation.HasLocalQuantumDependency), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); var equality = this.CreateValueTupleExpression(equalityId, equalityArgs); var inequality = this.CreateValueTupleExpression(inequalityId, inequalityArgs); var controlArgs = this.CreateValueTupleExpression( BoxResultInArray(conditionExpr1), BoxResultInArray(conditionExpr2), equality, inequality); var targetArgsTypes = ImmutableArray.Create(equalityArgs.ResolvedType, inequalityArgs.ResolvedType); return(this.CreateControlCall(controlOpInfo, props, controlArgs, targetArgsTypes)); }
private (ResolvedSignature, IEnumerable <QsSpecialization>) MakeSpecializations( QsQualifiedName callableName, ResolvedType paramsType, SpecializationImplementation bodyImplementation) { QsSpecialization MakeSpec(QsSpecializationKind kind, ResolvedSignature signature, SpecializationImplementation impl) => new QsSpecialization( kind, callableName, ImmutableArray <QsDeclarationAttribute> .Empty, this.CurrentCallable.Callable.SourceFile, QsNullable <QsLocation> .Null, QsNullable <ImmutableArray <ResolvedType> > .Null, signature, impl, ImmutableArray <string> .Empty, QsComments.Empty); var adj = this.CurrentCallable.Adjoint; var ctl = this.CurrentCallable.Controlled; var ctlAdj = this.CurrentCallable.ControlledAdjoint; bool addAdjoint = false; bool addControlled = false; bool isSelfAdjoint = false; if (this.InWithinBlock) { addAdjoint = true; addControlled = false; } else if (this.InBody) { if (adj != null && adj.Implementation is SpecializationImplementation.Generated adjGen) { addAdjoint = adjGen.Item.IsInvert; isSelfAdjoint = adjGen.Item.IsSelfInverse; } if (ctl != null && ctl.Implementation is SpecializationImplementation.Generated ctlGen) { addControlled = ctlGen.Item.IsDistribute; } if (ctlAdj != null && ctlAdj.Implementation is SpecializationImplementation.Generated ctlAdjGen) { addAdjoint = addAdjoint || (ctlAdjGen.Item.IsInvert && ctl.Implementation.IsGenerated); addControlled = addControlled || (ctlAdjGen.Item.IsDistribute && adj.Implementation.IsGenerated); isSelfAdjoint = isSelfAdjoint || ctlAdjGen.Item.IsSelfInverse; } } else if (ctlAdj != null && ctlAdj.Implementation is SpecializationImplementation.Generated gen) { addControlled = this.InAdjoint && gen.Item.IsDistribute; addAdjoint = this.InControlled && gen.Item.IsInvert; isSelfAdjoint = gen.Item.IsSelfInverse; } var props = new List <OpProperty>(); if (addAdjoint) { props.Add(OpProperty.Adjointable); } if (addControlled) { props.Add(OpProperty.Controllable); } var newSig = new ResolvedSignature( this.CurrentCallable.Callable.Signature.TypeParameters, paramsType, ResolvedType.New(ResolvedTypeKind.UnitType), new CallableInformation(ResolvedCharacteristics.FromProperties(props), new InferredCallableInformation(isSelfAdjoint, false))); var controlledSig = new ResolvedSignature( newSig.TypeParameters, ResolvedType.New(ResolvedTypeKind.NewTupleType(ImmutableArray.Create( ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Qubit))), newSig.ArgumentType))), newSig.ReturnType, newSig.Information); var specializations = new List <QsSpecialization>() { MakeSpec(QsSpecializationKind.QsBody, newSig, bodyImplementation) }; if (addAdjoint) { specializations.Add(MakeSpec( QsSpecializationKind.QsAdjoint, newSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Invert))); } if (addControlled) { specializations.Add(MakeSpec( QsSpecializationKind.QsControlled, controlledSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Distribute))); } if (addAdjoint && addControlled) { specializations.Add(MakeSpec( QsSpecializationKind.QsControlledAdjoint, controlledSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Distribute))); } return(newSig, specializations); }
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); }
public void ExcludeInaccessible() { var elements = new[] { AccessModifier.DefaultAccess, AccessModifier.Internal } .SelectMany(access => { var source = NonNullable <string> .New("Tests.qs"); 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, modifiers: new Modifiers(access), sourceFile: 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, modifiers: new Modifiers(access), sourceFile: 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 => NonNullable <string> .New("")); var ns = new QsNamespace(CanonName, elements.ToImmutableArray(), emptyLookup); var docNs = new DocNamespace(ns); var stream = new MemoryStream(); docNs.WriteToStream(stream, null); var expected = @"### YamlMime:QSharpNamespace uid: microsoft.quantum.canon name: Microsoft.Quantum.Canon operations: - uid: microsoft.quantum.canon.defaultaccessoperation summary: '' newtypes: - uid: microsoft.quantum.canon.defaultaccesstype summary: '' ... "; var actual = Encoding.UTF8.GetString(stream.ToArray()); Assert.Equal(expected, actual); }