@@ -259,7 +311,7 @@ public static string OperationVariants(this Type t, object op)
return OperationVariants(generic.OperationType, op);
}
- return OperationVariants(t.BaseType, op);
+ return OperationVariants(t.BaseType, op);
}
public static bool TryQSharpOperationType(Type t, out string typeName)
diff --git a/src/Simulation/Core/Udts/UDTPartial.cs b/src/Simulation/Core/Udts/UDTPartial.cs
index 8d586d4ee80..a97a92f870f 100644
--- a/src/Simulation/Core/Udts/UDTPartial.cs
+++ b/src/Simulation/Core/Udts/UDTPartial.cs
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
+#nullable enable
+
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -62,6 +64,18 @@ public ICallable Partial(object partialTuple)
return (ICallable)Activator.CreateInstance(partialType, new object[] { this, partialTuple });
}
+ ///
+ public RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ Debug.Assert(args.Value is P, $"Failed to retrieve runtime metadata for {typeof(U).Name}.");
+ var baseArgs = this.Apply((P) args.Value);
+ return new RuntimeMetadata()
+ {
+ Label = typeof(U).Name,
+ FormattedNonQubitArgs = baseArgs?.GetNonQubitArgumentsAsString() ?? "",
+ };
+ }
+
internal class DebuggerProxy
{
private readonly UDTPartial u;
diff --git a/src/Simulation/QsharpCore/Intrinsic.cs b/src/Simulation/QsharpCore/Intrinsic.cs
new file mode 100644
index 00000000000..76976a0f217
--- /dev/null
+++ b/src/Simulation/QsharpCore/Intrinsic.cs
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#nullable enable
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Intrinsic
+{
+ public partial class CNOT
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ Debug.Assert(args.Value is ValueTuple, $"Failed to retrieve runtime metadata for {this.ToString()}.");
+
+ if (args.Value is ValueTuple cnotArgs)
+ {
+ var (ctrl, target) = cnotArgs;
+ return new RuntimeMetadata()
+ {
+ Label = "X",
+ IsControlled = true,
+ Controls = new List() { ctrl },
+ Targets = new List() { target },
+ };
+ }
+
+ return null;
+ }
+ }
+
+ public partial class CCNOT
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ Debug.Assert(args.Value is ValueTuple, $"Failed to retrieve runtime metadata for {this.ToString()}.");
+
+ if (args.Value is ValueTuple ccnotArgs)
+ {
+ var (ctrl1, ctrl2, target) = ccnotArgs;
+ return new RuntimeMetadata()
+ {
+ Label = "X",
+ IsControlled = true,
+ Controls = new List() { ctrl1, ctrl2 },
+ Targets = new List() { target },
+ };
+ }
+
+ return null;
+ }
+ }
+
+ public partial class M
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ Debug.Assert(args.Value is Qubit, $"Failed to retrieve runtime metadata for {this.ToString()}.");
+
+ if (args.Value is Qubit target)
+ {
+ return new RuntimeMetadata()
+ {
+ Label = ((ICallable)this).Name,
+ IsMeasurement = true,
+ Targets = new List() { target },
+ };
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Simulation/QsharpCore/Measurement.cs b/src/Simulation/QsharpCore/Measurement.cs
new file mode 100644
index 00000000000..62cf6775fe1
--- /dev/null
+++ b/src/Simulation/QsharpCore/Measurement.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#nullable enable
+
+using System.Collections.Generic;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Measurement
+{
+ public partial class MResetX
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ var targets = new List();
+ var target = args.Value as Qubit;
+ if (target != null) targets.Add(target);
+
+ return new RuntimeMetadata()
+ {
+ Label = ((ICallable)this).Name,
+ IsMeasurement = true,
+ Targets = targets,
+ };
+ }
+ }
+
+ public partial class MResetY
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ var targets = new List();
+ var target = args.Value as Qubit;
+ if (target != null) targets.Add(target);
+
+ return new RuntimeMetadata()
+ {
+ Label = ((ICallable)this).Name,
+ IsMeasurement = true,
+ Targets = targets,
+ };
+ }
+ }
+
+ public partial class MResetZ
+ {
+ ///
+ public override RuntimeMetadata? GetRuntimeMetadata(IApplyData args)
+ {
+ var targets = new List();
+ var target = args.Value as Qubit;
+ if (target != null) targets.Add(target);
+
+ return new RuntimeMetadata()
+ {
+ Label = ((ICallable)this).Name,
+ IsMeasurement = true,
+ Targets = targets,
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs b/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs
new file mode 100644
index 00000000000..dcb7df85c86
--- /dev/null
+++ b/src/Simulation/Simulators.Tests/Circuits/RuntimeMetadataTest.qs
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits {
+
+ newtype FooUDT = (String, (Qubit, Double));
+
+ operation FooUDTOp (foo : FooUDT) : Unit is Ctl + Adj { }
+
+}
diff --git a/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs b/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs
new file mode 100644
index 00000000000..5e551565841
--- /dev/null
+++ b/src/Simulation/Simulators.Tests/RuntimeMetadataTests.cs
@@ -0,0 +1,641 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#nullable enable
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Quantum.Simulation.Core;
+using Xunit;
+
+namespace Microsoft.Quantum.Simulation.Simulators.Tests
+{
+ public class RuntimeMetadataEqualityTests
+ {
+ [Fact]
+ public void WrongType()
+ {
+ var a = new RuntimeMetadata { };
+ var i = 5;
+ Assert.False(a.Equals(i));
+ }
+
+ [Fact]
+ public void NullEquality()
+ {
+ var a = new RuntimeMetadata { };
+ RuntimeMetadata? b = null;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(b, a);
+ }
+
+ [Fact]
+ public void CheckEquality()
+ {
+ var a = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { },
+ };
+ var b = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { },
+ };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+
+ b.Label = "X";
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.Label = "H";
+
+ b.FormattedNonQubitArgs = "(1)";
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.FormattedNonQubitArgs = "";
+
+ b.IsAdjoint = true;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.IsAdjoint = false;
+
+ b.IsControlled = true;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.IsControlled = false;
+
+ b.IsMeasurement = true;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.IsMeasurement = false;
+
+ b.IsComposite = true;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ b.IsComposite = false;
+ }
+
+ [Fact]
+ public void ControlsEquality()
+ {
+ var a = new RuntimeMetadata()
+ {
+ Controls = new List() { },
+ };
+ var b = new RuntimeMetadata()
+ {
+ Controls = new List() { },
+ };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+
+ b.Controls = new List() { new FreeQubit(1) };
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+
+ a.Controls = new List() { new FreeQubit(1) };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public void TargetsEquality()
+ {
+ var a = new RuntimeMetadata()
+ {
+ Targets = new List() { },
+ };
+ var b = new RuntimeMetadata()
+ {
+ Targets = new List() { },
+ };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+
+ b.Targets = new List() { new FreeQubit(1) };
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+
+ a.Targets = new List() { new FreeQubit(1) };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+ }
+
+ [Fact]
+ public void ChildrenEquality()
+ {
+ var a = new RuntimeMetadata()
+ {
+ Children = new[]
+ {
+ new List(),
+ new List(),
+ },
+ };
+ var b = new RuntimeMetadata()
+ {
+ Children = new[]
+ {
+ new List(),
+ new List(),
+ },
+ };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+
+ var aChildren = a.Children.ToList();
+ aChildren[0] = new List() { new RuntimeMetadata() { Label = "H" } };
+ a.Children = aChildren;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+
+ var bChildren = b.Children.ToList();
+ bChildren[0] = new List() { new RuntimeMetadata() { Label = "X" } };
+ b.Children = bChildren;
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+
+ bChildren[0] = new List() { new RuntimeMetadata() { Label = "H" } };
+ Assert.Equal(a, b);
+ Assert.Equal(a.GetHashCode(), b.GetHashCode());
+
+ b.Children = b.Children.SkipLast(1);
+ Assert.NotEqual(a, b);
+ Assert.NotEqual(a.GetHashCode(), b.GetHashCode());
+ }
+ }
+
+ public class IntrinsicTests
+ {
+ [Fact]
+ public void CNOT()
+ {
+ var control = new FreeQubit(1);
+ var target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn((control, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { control },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void CCNOT()
+ {
+ var control1 = new FreeQubit(0);
+ var control2 = new FreeQubit(2);
+ var target = new FreeQubit(1);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn((control1, control2, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { control1, control2 },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void Ry()
+ {
+ var target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn((2.1, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "Ry",
+ FormattedNonQubitArgs = "(2.1)",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void M()
+ {
+ var measureQubit = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn(measureQubit);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "M",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = true,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { measureQubit },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+ }
+
+ public class MeasurementTests
+ {
+ [Fact]
+ public void MResetX()
+ {
+ var measureQubit = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn(measureQubit);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "MResetX",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = true,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { measureQubit },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void MResetY()
+ {
+ var measureQubit = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn(measureQubit);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "MResetY",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = true,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { measureQubit },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void MResetZ()
+ {
+ var measureQubit = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn(measureQubit);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "MResetZ",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = true,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { measureQubit },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+ }
+
+ public class UDTTests
+ {
+ [Fact]
+ public void FooUDTOp()
+ {
+ Qubit target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get();
+ var args = op.__dataIn(new Circuits.FooUDT(("bar", (target, 2.1))));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "FooUDTOp",
+ FormattedNonQubitArgs = "(\"bar\", (2.1))",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+ }
+
+ public class ControlledOpTests
+ {
+ [Fact]
+ public void ControlledH()
+ {
+ IQArray controls = new QArray(new[] { new FreeQubit(0) });
+ Qubit target = new FreeQubit(1);
+ var op = new QuantumSimulator().Get().Controlled;
+ var args = op.__dataIn((controls, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = controls,
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void ControlledX()
+ {
+ IQArray controls = new QArray(new[] { new FreeQubit(0) });
+ Qubit target = new FreeQubit(1);
+ var op = new QuantumSimulator().Get().Controlled;
+ var args = op.__dataIn((controls, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = controls,
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void ControlledCNOT()
+ {
+ IQArray controls = new QArray(new[] { new FreeQubit(0) });
+ Qubit control = new FreeQubit(1);
+ Qubit target = new FreeQubit(2);
+ var op = new QuantumSimulator().Get().Controlled;
+ var args = op.__dataIn((controls, (control, target)));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = controls.Append(control),
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void ControlledCCNOT()
+ {
+ Qubit control1 = new FreeQubit(0);
+ Qubit control2 = new FreeQubit(1);
+ Qubit control3 = new FreeQubit(2);
+ Qubit target = new FreeQubit(3);
+ IQArray controls = new QArray(new[] { control1 });
+ var op = new QuantumSimulator().Get().Controlled;
+ var args = op.__dataIn((controls, (control2, control3, target)));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { control1, control2, control3 },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+ }
+
+ public class AdjointTests
+ {
+ [Fact]
+ public void AdjointH()
+ {
+ Qubit target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get().Adjoint;
+ var args = op.__dataIn(target);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = true,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void AdjointX()
+ {
+ Qubit target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get().Adjoint;
+ var args = op.__dataIn(target);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "X",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = true,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void AdjointAdjointH()
+ {
+ Qubit target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get().Adjoint.Adjoint;
+ var args = op.__dataIn(target);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void ControlledAdjointH()
+ {
+ IQArray controls = new QArray(new[] { new FreeQubit(0) });
+ Qubit target = new FreeQubit(1);
+ var op1 = new QuantumSimulator().Get().Controlled.Adjoint;
+ var op2 = new QuantumSimulator().Get().Adjoint.Controlled;
+ var args = op1.__dataIn((controls, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = true,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = controls,
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op1.GetRuntimeMetadata(args), expected);
+ Assert.Equal(op2.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void ControlledAdjointAdjointH()
+ {
+ IQArray controls = new QArray(new[] { new FreeQubit(0) });
+ Qubit target = new FreeQubit(1);
+ var op1 = new QuantumSimulator().Get().Controlled.Adjoint.Adjoint;
+ var op2 = new QuantumSimulator().Get().Adjoint.Controlled.Adjoint;
+ var op3 = new QuantumSimulator().Get().Adjoint.Adjoint.Controlled;
+ var args = op1.__dataIn((controls, target));
+ var expected = new RuntimeMetadata()
+ {
+ Label = "H",
+ FormattedNonQubitArgs = "",
+ IsAdjoint = false,
+ IsControlled = true,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = controls,
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op1.GetRuntimeMetadata(args), expected);
+ Assert.Equal(op2.GetRuntimeMetadata(args), expected);
+ Assert.Equal(op3.GetRuntimeMetadata(args), expected);
+ }
+ }
+
+ public class PartialOpTests
+ {
+
+ [Fact]
+ public void PartialRy()
+ {
+ var target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get().Partial((double d) =>
+ new ValueTuple(d, target));
+ var args = op.__dataIn(2.1);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "Ry",
+ FormattedNonQubitArgs = "(2.1)",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { target },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+
+ [Fact]
+ public void PartialUDT()
+ {
+ var target = new FreeQubit(0);
+ var op = new QuantumSimulator().Get>(typeof(Circuits.FooUDT))
+ .Partial((double d) => (("bar", (target, d))));
+ var args = new QTuple(2.1);
+ var expected = new RuntimeMetadata()
+ {
+ Label = "FooUDT",
+ FormattedNonQubitArgs = "(\"bar\", (2.1))",
+ IsAdjoint = false,
+ IsControlled = false,
+ IsMeasurement = false,
+ IsComposite = false,
+ Children = null,
+ Controls = new List() { },
+ Targets = new List() { },
+ };
+
+ Assert.Equal(op.GetRuntimeMetadata(args), expected);
+ }
+ }
+}
diff --git a/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs b/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs
new file mode 100644
index 00000000000..8e025482316
--- /dev/null
+++ b/src/Simulation/Simulators.Tests/TypeExtensionsTest.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.Quantum.Simulation.Core;
+using Xunit;
+
+namespace Microsoft.Quantum.Simulation.Simulators.Tests
+{
+ public class ApplyData : IApplyData
+ {
+ public T Data;
+
+ public ApplyData(T data)
+ {
+ this.Data = data;
+ }
+
+ object IApplyData.Value => this.Data;
+
+ IEnumerable IApplyData.Qubits => QubitsExtractor.Get(typeof(T))?.Extract(Data);
+ }
+
+ public class GetNonQubitArgumentsAsStringTests
+ {
+ [Fact]
+ public void BasicTypes()
+ {
+ Assert.Equal("3", 3.GetNonQubitArgumentsAsString());
+ Assert.Equal("False", false.GetNonQubitArgumentsAsString());
+ Assert.Equal("\"Foo\"", "Foo".GetNonQubitArgumentsAsString());
+ Assert.Equal("\"\"", "".GetNonQubitArgumentsAsString());
+ }
+
+ [Fact]
+ public void TupleTypes()
+ {
+ Assert.Equal("(1, 2)", (1, 2).GetNonQubitArgumentsAsString());
+ Assert.Equal("(\"foo\", \"bar\")", ("foo", "bar").GetNonQubitArgumentsAsString());
+ Assert.Equal("(\"foo\", \"bar\", \"\")", ("foo", "bar", "").GetNonQubitArgumentsAsString());
+ Assert.Equal("(\"foo\", (\"bar\", \"car\"))", ("foo", ("bar", "car")).GetNonQubitArgumentsAsString());
+ Assert.Equal("((\"foo\"), (\"bar\", \"car\"))", (("foo", new FreeQubit(0)), ("bar", "car")).GetNonQubitArgumentsAsString());
+ }
+
+ [Fact]
+ public void ArrayTypes()
+ {
+ Assert.Equal("[1, 2, 3]", new[] { 1, 2, 3 }.GetNonQubitArgumentsAsString());
+ Assert.Equal("[\"foo\", \"bar\"]", new[] { "foo", "bar" }.GetNonQubitArgumentsAsString());
+
+ var arr = new[] {
+ (new FreeQubit(0), "foo"),
+ (new FreeQubit(1), "bar"),
+ };
+ Assert.Equal("[(\"foo\"), (\"bar\")]", arr.GetNonQubitArgumentsAsString());
+ }
+
+ [Fact]
+ public void IApplyDataTypes()
+ {
+ IApplyData data;
+ data = new ApplyData(3);
+ Assert.Equal("3", data.GetNonQubitArgumentsAsString());
+
+ data = new ApplyData(false);
+ Assert.Equal("False", data.GetNonQubitArgumentsAsString());
+
+ data = new ApplyData("Foo");
+ Assert.Equal("\"Foo\"", data.GetNonQubitArgumentsAsString());
+
+ data = new ApplyData>((1, "foo"));
+ Assert.Equal("(1, \"foo\")", data.GetNonQubitArgumentsAsString());
+
+ data = new ApplyData, ValueTuple>>((("foo", new FreeQubit(0)), ("bar", "car")));
+ Assert.Equal("((\"foo\"), (\"bar\", \"car\"))", data.GetNonQubitArgumentsAsString());
+
+ data = new ApplyData(new[] { 1, 2, 3 });
+ Assert.Equal("[1, 2, 3]", data.GetNonQubitArgumentsAsString());
+
+ var arr = new[] {
+ (new FreeQubit(0), "foo"),
+ (new FreeQubit(1), "bar"),
+ };
+ data = new ApplyData<(FreeQubit, string)[]>(arr);
+ Assert.Equal("[(\"foo\"), (\"bar\")]", data.GetNonQubitArgumentsAsString());
+ }
+ }
+}