Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/Core/ExecutionPathTracer/ExecutionPathTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,17 @@ private ClassicalRegister GetClassicalRegister(Qubit controlQubit)
{
if (metadata == null) return null;

var displayArgs = (metadata.FormattedNonQubitArgs.Length > 0)
? metadata.FormattedNonQubitArgs
: null;

// Add surrounding parentheses around displayArgs if it doesn't already have it (i.e. not a tuple)
if (displayArgs != null && !displayArgs.StartsWith("(")) displayArgs = $"({displayArgs})";

var op = new Operation()
{
Gate = metadata.Label,
DisplayArgs = (metadata.FormattedNonQubitArgs.Length > 0) ? metadata.FormattedNonQubitArgs : null,
DisplayArgs = displayArgs,
Children = metadata.Children?.Select(child => child.Select(this.MetadataToOperation).WhereNotNull()),
Controlled = metadata.IsControlled,
Adjoint = metadata.IsAdjoint,
Expand Down
4 changes: 2 additions & 2 deletions src/Kernel/Magic/TraceMagic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public ExecutionPathVisualizerContent(JToken executionPath, string id)
public class TraceMagic : AbstractMagic
{
private const string ParameterNameOperationName = "__operationName__";
private const string ParameterNameDepth = "depth";
private const string ParameterNameDepth = "--depth";

/// <summary>
/// Constructs a new magic command given a resolver used to find
Expand All @@ -61,7 +61,7 @@ public TraceMagic(ISymbolResolver resolver, IConfigurationSource configurationSo
"trace",
new Documentation
{
Summary = "Outputs the HTML-based visualization of an execution path of the given operation.",
Summary = "Visualizes the execution path of the given operation.",
Description = $@"
This magic command renders an HTML-based visualization of a runtime execution path of the
given operation using the QuantumSimulator.
Expand Down
97 changes: 94 additions & 3 deletions src/Tests/ExecutionPathTracerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

namespace Tests.IQSharp
{
[TestClass]
public class IntrinsicTests
public class ExecutionPathTracerTests
{
public Workspace InitWorkspace()
{
Expand All @@ -33,7 +32,11 @@ public ExecutionPath GetExecutionPath(string name, int depth = 1)

return tracer.GetExecutionPath();
}
}

[TestClass]
public class IntrinsicTests : ExecutionPathTracerTests
{
[TestMethod]
public void HTest()
{
Expand Down Expand Up @@ -275,7 +278,11 @@ public void ControlledAdjointSTest()
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}
}

[TestClass]
public class Circuits : ExecutionPathTracerTests
{
[TestMethod]
public void FooTest()
{
Expand Down Expand Up @@ -429,7 +436,24 @@ public void EmptyTest()
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}


[TestMethod]
public void NoQubitArgsTest()
{
var path = GetExecutionPath("NoQubitArgsCirc");
var qubits = new QubitDeclaration[] {};
var operations = new Operation[]
{
new Operation()
{
Gate = "NoQubitCirc",
DisplayArgs = "(2)",
},
};
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}

[TestMethod]
public void NestedTest()
{
Expand Down Expand Up @@ -533,4 +557,71 @@ public void BigTest()
Assert.AreEqual(expected.ToJson(), path.ToJson());
}
}

[TestClass]
public class MeasurementTests : ExecutionPathTracerTests
{
[TestMethod]
public void MResetXTest()
{
var path = GetExecutionPath("MResetXCirc");
var qubits = new QubitDeclaration[]
{
new QubitDeclaration(0, 1),
};
var operations = new Operation[]
{
new Operation()
{
Gate = "measure",
Controls = new List<Register>() { new QubitRegister(0) },
Targets = new List<Register>() { new ClassicalRegister(0, 0) },
},
};
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}

[TestMethod]
public void MResetYTest()
{
var path = GetExecutionPath("MResetYCirc");
var qubits = new QubitDeclaration[]
{
new QubitDeclaration(0, 1),
};
var operations = new Operation[]
{
new Operation()
{
Gate = "measure",
Controls = new List<Register>() { new QubitRegister(0) },
Targets = new List<Register>() { new ClassicalRegister(0, 0) },
},
};
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}

[TestMethod]
public void MResetZTest()
{
var path = GetExecutionPath("MResetZCirc");
var qubits = new QubitDeclaration[]
{
new QubitDeclaration(0, 1),
};
var operations = new Operation[]
{
new Operation()
{
Gate = "measure",
Controls = new List<Register>() { new QubitRegister(0) },
Targets = new List<Register>() { new ClassicalRegister(0, 0) },
},
};
var expected = new ExecutionPath(qubits, operations);
Assert.AreEqual(expected.ToJson(), path.ToJson());
}
}
}
2 changes: 1 addition & 1 deletion src/Tests/IQsharpEngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ public async Task TestTraceMagic()
));

// Should see depth-2 operations
await AssertTrace("Depth2Circ depth=2", new ExecutionPath(
await AssertTrace("Depth2Circ --depth=2", new ExecutionPath(
new QubitDeclaration[] { new QubitDeclaration(0) },
new Operation[]
{
Expand Down
3 changes: 3 additions & 0 deletions src/Tests/Tests.IQsharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
<None Update="Workspace.ExecutionPathTracer\Measurement.qs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Workspace.ExecutionPathTracer\Circuits.qs">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
91 changes: 91 additions & 0 deletions src/Tests/Workspace.ExecutionPathTracer/Circuits.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Tests.ExecutionPathTracer {

open Microsoft.Quantum.Intrinsic;

// Custom operation
operation Foo(theta : Double, (qubit : Qubit, bar : String)) : Unit
is Adj + Ctl {
}

operation FooCirc() : Unit {
using (q = Qubit()) {
Foo(2.1, (q, "bar"));
}
}

operation ControlledFooCirc() : Unit {
using (qs = Qubit[2]) {
Controlled Foo([qs[0]], (2.1, (qs[1], "bar")));
}
}

operation UnusedQubitCirc() : Unit {
using (qs = Qubit[3]) {
CNOT(qs[2], qs[0]);
Reset(qs[0]);
Reset(qs[2]);
}
}

operation EmptyCirc() : Unit {
using (qs = Qubit[3]) {
}
}

operation NoQubitCirc(n : Int) : Unit {
}

operation NoQubitArgsCirc() : Unit {
NoQubitCirc(2);
}

operation NestedCirc() : Unit {
using (q = Qubit()) {
H(q);
HCirc();
Reset(q);
}
}

operation FooBar(q : Qubit) : Unit {
H(q);
X(q);
H(q);
}

operation Depth2Circ() : Unit {
using (q = Qubit()) {
FooBar(q);
}
}

operation PartialOpCirc() : Unit {
using (qs = Qubit[3]) {
(Controlled H(qs[0..1], _))(qs[2]);
((Ry(_, _))(2.5, _))(qs[0]);
ResetAll(qs);
}
}

operation Bar((alpha : Double, beta : Double), (q : Qubit, name : String)) : Unit
is Adj + Ctl {
}

operation BigCirc() : Unit {
using (qs = Qubit[3]) {
H(qs[0]);
Ry(2.5, qs[1]);
Bar((1.0, 2.1), (qs[0], "foo"));
X(qs[0]);
CCNOT(qs[0], qs[1], qs[2]);
Controlled CNOT([qs[0]], (qs[1], qs[2]));
Controlled Adjoint Bar([qs[2]], ((1.0, 2.1), (qs[0], "foo")));
let res = M(qs[0]);
ResetAll(qs);
}
}

}
79 changes: 0 additions & 79 deletions src/Tests/Workspace.ExecutionPathTracer/Intrinsic.qs
Original file line number Diff line number Diff line change
Expand Up @@ -65,83 +65,4 @@ namespace Tests.ExecutionPathTracer {
ResetAll(qs);
}
}

// Custom operation
operation Foo(theta : Double, (qubit : Qubit, bar : String)) : Unit
is Adj + Ctl {
}

operation FooCirc() : Unit {
using (q = Qubit()) {
Foo(2.1, (q, "bar"));
}
}

operation ControlledFooCirc() : Unit {
using (qs = Qubit[2]) {
Controlled Foo([qs[0]], (2.1, (qs[1], "bar")));
}
}

operation UnusedQubitCirc() : Unit {
using (qs = Qubit[3]) {
CNOT(qs[2], qs[0]);
Reset(qs[0]);
Reset(qs[2]);
}
}

operation EmptyCirc() : Unit {
using (qs = Qubit[3]) {
}
}

operation NestedCirc() : Unit {
using (q = Qubit()) {
H(q);
HCirc();
Reset(q);
}
}

operation FooBar(q : Qubit) : Unit {
H(q);
X(q);
H(q);
}

operation Depth2Circ() : Unit {
using (q = Qubit()) {
FooBar(q);
}
}

operation PartialOpCirc() : Unit {
using (qs = Qubit[3]) {
(Controlled H(qs[0..1], _))(qs[2]);
((Ry(_, _))(2.5, _))(qs[0]);
ResetAll(qs);
}
}

operation Bar((alpha : Double, beta : Double), (q : Qubit, name : String)) : Unit
is Adj + Ctl {
}

operation BigCirc() : Unit {
using (qs = Qubit[3]) {
H(qs[0]);
Ry(2.5, qs[1]);
Bar((1.0, 2.1), (qs[0], "foo"));
X(qs[0]);
CCNOT(qs[0], qs[1], qs[2]);
Controlled CNOT([qs[0]], (qs[1], qs[2]));
Controlled Adjoint Bar([qs[2]], ((1.0, 2.1), (qs[0], "foo")));
let res = M(qs[0]);
ResetAll(qs);
}
}

}