diff --git a/src/Simulation/Core/IOperationFactory.cs b/src/Simulation/Core/IOperationFactory.cs
index 70310776a17..eedca83664b 100644
--- a/src/Simulation/Core/IOperationFactory.cs
+++ b/src/Simulation/Core/IOperationFactory.cs
@@ -24,7 +24,7 @@ public interface IOperationFactory
///
/// Returns an instance of the requested operation.
///
- I Get(Type t);
+ I Get(Type T);
///
/// Returns an instance of the requested operation.
diff --git a/src/Simulation/Native/src/simulator/capi.hpp b/src/Simulation/Native/src/simulator/capi.hpp
index 260b8a43905..2c33478b56b 100644
--- a/src/Simulation/Native/src/simulator/capi.hpp
+++ b/src/Simulation/Native/src/simulator/capi.hpp
@@ -22,8 +22,6 @@ extern "C"
MICROSOFT_QUANTUM_DECL void destroy(_In_ unsigned sid); // NOLINT
MICROSOFT_QUANTUM_DECL void seed(_In_ unsigned sid, _In_ unsigned s); // NOLINT
MICROSOFT_QUANTUM_DECL void Dump(_In_ unsigned sid, _In_ bool (*callback)(size_t, double, double));
-
- // TODO(rokuzmin): What does it return?
MICROSOFT_QUANTUM_DECL bool DumpQubits(
_In_ unsigned sid,
_In_ unsigned n,
diff --git a/src/Simulation/Native/src/simulator/simulatorinterface.hpp b/src/Simulation/Native/src/simulator/simulatorinterface.hpp
index c23fd2df123..7a85d65aef6 100644
--- a/src/Simulation/Native/src/simulator/simulatorinterface.hpp
+++ b/src/Simulation/Native/src/simulator/simulatorinterface.hpp
@@ -99,7 +99,6 @@ class SimulatorInterface
{
assert(false);
}
- // TODO(rokuzmin): What does it return?
virtual bool dumpQubits(std::vector const& qs, bool (*callback)(size_t, double, double))
{
assert(false);
diff --git a/src/Simulation/Simulators/QuantumSimulator/Dump.cs b/src/Simulation/Simulators/QuantumSimulator/Dump.cs
index 90e91105734..d57d0b7dd4a 100644
--- a/src/Simulation/Simulators/QuantumSimulator/Dump.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/Dump.cs
@@ -23,29 +23,48 @@ protected virtual QVoid Dump(T target, IQArray? qubits = null)
{
var filename = (target is QVoid) ? "" : target.ToString();
- // If no file provided, output to the console;
+ QVoid process(Action channel)
+ {
+ var ids = qubits?.Select(q => (uint)q.Id).ToArray() ?? QubitIds;
+
+ var dumper = new SimpleDumper(this, channel);
+ channel($"# wave function for qubits with ids (least to most significant): {string.Join(";", ids)}");
+
+ if (!dumper.Dump(qubits))
+ {
+ channel("## Qubits were entangled with an external qubit. Cannot dump corresponding wave function. ##");
+ }
+
+ return QVoid.Instance;
+ }
+
+ var logMessage = this.Get, Microsoft.Quantum.Intrinsic.Message>();
+
+ // If no file provided, use `Message` to generate the message into the console;
if (string.IsNullOrWhiteSpace(filename))
{
- new DisplayableStateDumper(this).Dump(qubits);
+ var op = this.Get, Microsoft.Quantum.Intrinsic.Message>();
+ return process((msg) => op.Apply(msg));
}
else
{
try
{
- using var file = new StreamWriter(filename);
- new DisplayableStateDumper(this, file.WriteLine).Dump(qubits);
+ using (var file = new StreamWriter(filename))
+ {
+ return process(file.WriteLine);
+ }
}
catch (Exception e)
{
- var logMessage = this.Get, Microsoft.Quantum.Intrinsic.Message>();
logMessage.Apply($"[warning] Unable to write state to '{filename}' ({e.Message})");
+ return QVoid.Instance;
}
}
- return QVoid.Instance;
}
- public class QsimDumpMachine : Quantum.Diagnostics.DumpMachine // Is inherited (and replaced at runtime)
- { // by (iqsharp's) JupyterDumpMachine.
+ public class QsimDumpMachine : Quantum.Diagnostics.DumpMachine
+ {
private QuantumSimulator Simulator { get; }
public QsimDumpMachine(QuantumSimulator m) : base(m)
@@ -61,8 +80,8 @@ public QsimDumpMachine(QuantumSimulator m) : base(m)
};
}
- public class QSimDumpRegister : Quantum.Diagnostics.DumpRegister // Is inherited (and replaced at runtime)
- { // by (iqsharp's) JupyterDumpRegister.
+ public class QSimDumpRegister : Quantum.Diagnostics.DumpRegister
+ {
private QuantumSimulator Simulator { get; }
public QSimDumpRegister(QuantumSimulator m) : base(m)
diff --git a/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs b/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs
index 6ff07af9522..30b84a41e8d 100644
--- a/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/NativeImports.cs
@@ -86,7 +86,6 @@ public partial class QuantumSimulator
[DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "Dump")]
private static extern void sim_Dump(uint id, DumpCallback callback);
- // TODO(rokuzmin): What does it return?
[DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "DumpQubits")]
private static extern bool sim_DumpQubits(uint id, uint cout, uint[] ids, DumpCallback callback);
diff --git a/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs b/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs
index a5a0e4ef67e..8bb52e118e4 100644
--- a/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs
@@ -93,9 +93,9 @@ public SimulatorBase(IQubitManager? qubitManager = null, int? seed = null)
}
}
- public I Get(Type t)
+ public I Get(Type T)
{
- return (I)this.GetInstance(t);
+ return (I)this.GetInstance(T);
}
///
diff --git a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs
index 7795f0082db..a7c351fad69 100644
--- a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs
@@ -2,13 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Numerics;
using Microsoft.Quantum.Simulation.Core;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
-
namespace Microsoft.Quantum.Simulation.Simulators
{
@@ -20,7 +14,7 @@ public partial class QuantumSimulator
/// The callback function is triggered for every state basis
/// vector in the wavefunction.
///
- public abstract class StateDumper // Is inherited by (iqsharp's) JupyterDisplayDumper.
+ public abstract class StateDumper
{
///
/// Basic constructor. Takes the simulator to probe.
@@ -50,7 +44,6 @@ public StateDumper(QuantumSimulator qsim)
///
/// Entry method to get the dump of the wave function.
///
- // TODO(rokuzmin): What does it return?
public virtual bool Dump(IQArray? qubits = null)
{
if (qubits == null)
@@ -67,190 +60,29 @@ public virtual bool Dump(IQArray? qubits = null)
}
///
- /// The convention to be used in labeling computational basis states
- /// given their representations as strings of classical bits.
+ /// A simple implementation of a . It outputs the
+ /// a string representation of the state to the given channel.
///
- [JsonConverter(typeof(StringEnumConverter))]
- public enum BasisStateLabelingConvention
+ public class SimpleDumper : StateDumper
{
- ///
- /// Label computational states directly by their bit strings.
- ///
- ///
- /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled
- /// by |011⟩.
- ///
- Bitstring,
-
- ///
- /// Label computational states directly by interpreting their bit
- /// strings as little-endian encoded integers.
- ///
- ///
- /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled
- /// by |6⟩.
- ///
- LittleEndian,
-
- ///
- /// Label computational states directly by interpreting their bit
- /// strings as big-endian encoded integers.
- ///
- ///
- /// Following this convention, the state |0⟩ ⊗ |1⟩ ⊗ |1⟩ is labeled
- /// by |3⟩.
- ///
- BigEndian
- }
-
- ///
- /// Represents a quantum state vector and all metadata needed to display
- /// that state vector.
- ///
- public class DisplayableState
- {
- private static readonly IComparer ToIntComparer =
- Comparer.Create((label1, label2) =>
- Comparer.Default.Compare(
- Int32.Parse(label1), Int32.Parse(label2)
- )
- );
-
- ///
- /// Metadata to be used when serializing to JSON, allowing code
- /// in other languages to determine what representation is used
- /// for this state.
- ///
- [JsonProperty("diagnostic_kind")]
- private string DiagnosticKind => "state-vector";
-
- // TODO(rokuzmin): Get back to this after the IQ#-side PR:
- // ///
- // /// ID for an HTML element where the vertical measurement probability histogram
- // /// will be displayed.
- // ///
- // [JsonProperty("div_id")]
- // public string DivId { get; set; } = string.Empty;
-
- ///
- /// The indexes of each qubit on which this state is defined, or
- /// null if these indexes are not known.
- ///
- [JsonProperty("qubit_ids")]
- public IEnumerable? QubitIds { get; set; }
-
- ///
- /// The number of qubits on which this state is defined.
- ///
- [JsonProperty("n_qubits")]
- public int NQubits { get; set; }
+ private int _maxCharsStateId;
- ///
- /// These amplitudes represent the computational basis states
- /// labeled in little-endian order, as per the behavior of
- /// .
- ///
- [JsonProperty("amplitudes")]
- public Complex[]? Amplitudes { get; set; }
-
-
- // TODO(rokuzmin): Make this an extension method for `QuantumSimulator.DisplayableState` in IQSharp repo:
- // ///
- // /// An enumerable source of the significant amplitudes of this state
- // /// vector and their labels, where significance and labels are
- // /// defined by the values loaded from .
- // ///
- // public IEnumerable<(Complex, string)> SignificantAmplitudes(
- // IConfigurationSource configurationSource
- // ) => SignificantAmplitudes(
- // configurationSource.BasisStateLabelingConvention,
- // configurationSource.TruncateSmallAmplitudes,
- // configurationSource.TruncationThreshold
- // );
-
- ///
- /// An enumerable source of the significant amplitudes of this state
- /// vector and their labels.
- ///
- ///
- /// The convention to be used in labeling each computational basis state.
- ///
- ///
- /// Whether to truncate small amplitudes.
- ///
- ///
- /// If is true,
- /// then amplitudes whose absolute value squared are below this
- /// threshold are suppressed.
- ///
- public IEnumerable<(Complex, string)> SignificantAmplitudes(
- BasisStateLabelingConvention convention,
- bool truncateSmallAmplitudes, double truncationThreshold
- ) =>
- (
- truncateSmallAmplitudes
- ? Amplitudes
- .Select((amplitude, idx) => (amplitude, idx))
- .Where(item =>
- System.Math.Pow(item.amplitude.Magnitude, 2.0) >= truncationThreshold
- )
- : Amplitudes.Select((amplitude, idx) => (amplitude, idx))
- )
- .Select(
- item => (item.amplitude, BasisStateLabel(convention, item.idx))
- )
- .OrderBy(
- item => item.Item2,
- // If a basis state label is numeric, we want to compare
- // numerically rather than lexographically.
- convention switch {
- BasisStateLabelingConvention.BigEndian => ToIntComparer,
- BasisStateLabelingConvention.LittleEndian => ToIntComparer,
- _ => Comparer.Default
- }
- );
+ public SimpleDumper(QuantumSimulator qsim, Action channel) : base(qsim)
+ {
+ this.Channel = channel;
+ }
///
- /// Using the given labeling convention, returns the label for a
- /// computational basis state described by its bit string as encoded
- /// into an integer index in the little-endian encoding.
+ /// A method to call to output a string representation of the amplitude of each
+ /// state basis vector.
///
- public string BasisStateLabel(
- BasisStateLabelingConvention convention, int index
- ) => convention switch
- {
- BasisStateLabelingConvention.Bitstring =>
- String.Concat(
- System
- .Convert
- .ToString(index, 2)
- .PadLeft(NQubits, '0')
- .Reverse()
- ),
- BasisStateLabelingConvention.BigEndian =>
- System.Convert.ToInt64(
- String.Concat(
- System.Convert.ToString(index, 2).PadLeft(NQubits, '0').Reverse()
- ),
- fromBase: 2
- )
- .ToString(),
- BasisStateLabelingConvention.LittleEndian =>
- index.ToString(),
- _ => throw new ArgumentException($"Invalid basis state labeling convention {convention}.")
- };
-
+ public virtual Action Channel { get; }
///
/// Returns a string that represents the label for the given base state.
///
- public virtual string FormatBaseState(uint idx)
- {
- int qubitCount = Amplitudes?.Length ?? 0;
- int maxCharsStateId = ((1 << qubitCount) - 1).ToString().Length;
-
- return $"∣{idx.ToString().PadLeft(maxCharsStateId, ' ')}❭";
- }
+ public virtual string FormatBaseState(uint idx) =>
+ $"∣{idx.ToString().PadLeft(_maxCharsStateId, ' ')}❭";
///
/// Returns a string that represents the magnitude of the amplitude.
@@ -323,168 +155,25 @@ public virtual string Format(uint idx, double real, double img)
}
- public string ToString(BasisStateLabelingConvention convention, // Non-override. Parameterized.
- bool truncateSmallAmplitudes,
- double truncationThreshold)
- {
- return string.Join('\n',
- SignificantAmplitudes(convention, truncateSmallAmplitudes, truncationThreshold)
- .Select(
- item =>
- {
- var (cmplx, basisLabel) = item;
- var amplitude = (cmplx.Real * cmplx.Real) + (cmplx.Imaginary * cmplx.Imaginary);
- var angle = System.Math.Atan2(cmplx.Imaginary, cmplx.Real);
- return $"|{basisLabel}⟩\t{FormatCartesian(cmplx.Real, cmplx.Imaginary)}\t == \t" +
- $"{FormatPolar(amplitude, angle)}";
- }));
- }
-
- public override string ToString() => // An override of the `object.ToString()`.
- ToString(BasisStateLabelingConvention.LittleEndian, false, 0.0);
-
- } // public class DisplayableState
-
-
- ///
- /// A state dumper that encodes dumped states into displayable
- /// objects.
- ///
- public class DisplayableStateDumper : StateDumper
- {
- private long _count = -1;
- private Complex[]? _data = null;
-
- // TODO(rokuzmin): Remove the commented-out code below once everything works on IQSharp side.
- // ///
- // /// Whether small amplitudes should be truncated when dumping
- // /// states.
- // ///
- // public bool TruncateSmallAmplitudes { get; set; } = false;
-
- // ///
- // /// The threshold for truncating measurement probabilities when
- // /// dumping states. Computational basis states whose measurement
- // /// probabilities (i.e: squared magnitudes) are below this threshold
- // /// are subject to truncation when
- // ///
- // /// is true.
- // ///
- // public double TruncationThreshold { get; set; } = 1e-10;
-
- // ///
- // /// The labeling convention to be used when labeling computational
- // /// basis states.
- // ///
- // public BasisStateLabelingConvention BasisStateLabelingConvention { get; set; } = BasisStateLabelingConvention.Bitstring;
-
- // ///
- // /// Whether the measurement probabilities will be displayed as an
- // /// interactive histogram.
- // ///
- // private bool ShowMeasurementDisplayHistogram { get; set; } = false;
-
- // ///
- // /// Sets the properties of this display dumper from a given
- // /// configuration source.
- // ///
- // public JupyterDisplayDumper Configure(IConfigurationSource configurationSource)
- // {
- // configurationSource
- // .ApplyConfiguration("dump.measurementDisplayHistogram", value => ShowMeasurementDisplayHistogram = value)
- // .ApplyConfiguration("dump.truncateSmallAmplitudes", value => TruncateSmallAmplitudes = value)
- // .ApplyConfiguration("dump.truncationThreshold", value => TruncationThreshold = value)
- // .ApplyConfiguration(
- // "dump.basisStateLabelingConvention", value => BasisStateLabelingConvention = value
- // );
- // return this;
- // }
-
///
- /// A method to call to output a string representation.
- ///
- public virtual Action? FileWriter { get; }
-
- ///
- /// Constructs a new display dumper for a given simulator.
- ///
- public DisplayableStateDumper(QuantumSimulator sim, Action? fileWriter = null) : base(sim)
- {
- this.FileWriter = fileWriter;
- }
-
- ///
- /// Used by the simulator to provide states when dumping.
- /// Not intended to be called directly.
+ /// The callback method. Formats the given state and invokes the
///
+ /// True, so the entire wave function is dumped.
public override bool Callback(uint idx, double real, double img)
{
- if (_data == null) throw new Exception("Expected data buffer to be initialized before callback, but it was null.");
- _data[idx] = new Complex(real, img);
+ Channel(Format(idx, real, img));
return true;
}
- ///
- /// Dumps the state of a register of qubits as a displayable object.
- ///
- // TODO(rokuzmin): What does it return?
public override bool Dump(IQArray? qubits = null)
{
- System.Diagnostics.Debug.Assert(this.Simulator.QubitManager != null,
- "Internal logic error, QubitManager must be assigned");
-
- _count = qubits == null
- ? this.Simulator.QubitManager.AllocatedQubitsCount
- : qubits.Length;
- _data = new Complex[1 << ((int)_count)]; // If 0 qubits are allocated then the array has
- // a single element. The Hilbert space of the system is
- // ℂ¹ (that is, complex-valued scalars).
- var result = base.Dump(qubits);
-
- // At this point, _data should be filled with the full state
- // vector, so let's display it, counting on the right display
- // encoder to be there to pack it into a table.
-
- // var id = System.Guid.NewGuid();
- var state = new DisplayableState
- {
- // We cast here as we don't support a large enough number
- // of qubits to saturate an int.
- QubitIds = qubits?.Select(q => q.Id) ?? Simulator.QubitIds.Select(q => (int)q) ?? Enumerable.Empty(),
- NQubits = (int)_count,
- Amplitudes = _data,
- // DivId = $"dump-machine-div-{id}"
- };
-
- if (this.FileWriter != null)
- {
- this.FileWriter(state.ToString());
- }
- else
- {
- Simulator.MaybeDisplayDiagnostic(state);
- }
+ var count = qubits == null
+ ? this.Simulator.QubitManager.AllocatedQubitsCount
+ : qubits.Length;
+ this._maxCharsStateId = ((1 << (int)count) - 1).ToString().Length;
-
- // TODO(rokuzmin): Work on this thoroughly on the IQSharp side:
- // if (ShowMeasurementDisplayHistogram)
- // {
- // Debug.Assert(Channel.CommsRouter != null, "Display dumper requires comms router.");
- // Channel.CommsRouter.OpenSession(
- // "iqsharp_state_dump",
- // new MeasurementHistogramContent()
- // {
- // State = state
- // }
- // ).Wait();
- // }
-
- // Clean up the state vector buffer.
- _data = null;
-
- return result;
+ return base.Dump(qubits);
}
-
}
}
}