diff --git a/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs b/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs
index dda46fc992a..e444e7bc203 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/CommonNativeSimulator.cs
@@ -35,6 +35,8 @@ private protected CommonNativeSimulator(
public uint Id { get; protected set; }
+ public abstract uint[] QubitIds { get; }
+
public override string Name
{
get
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs b/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs
new file mode 100644
index 00000000000..0cdf4fd272c
--- /dev/null
+++ b/src/Simulation/Simulators/CommonNativeSimulator/DisplayableState.cs
@@ -0,0 +1,242 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace Microsoft.Quantum.Simulation.Simulators
+{
+ public partial class CommonNativeSimulator
+ {
+ ///
+ /// The convention to be used in labeling computational basis states
+ /// given their representations as strings of classical bits.
+ ///
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum BasisStateLabelingConvention
+ {
+ ///
+ /// 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";
+
+ ///
+ /// 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; }
+
+ ///
+ /// These amplitudes represent the computational basis states
+ /// labeled in little-endian order, as per the behavior of
+ /// .
+ ///
+ [JsonProperty("amplitudes")]
+ public IDictionary? Amplitudes { get; set; }
+
+ ///
+ /// 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
+ .Where(item =>
+ System.Math.Pow(item.Value.Magnitude, 2.0) >= truncationThreshold
+ )
+ : Amplitudes
+ )
+ .Select(
+ item => (item.Value, BasisStateLabel(convention, item.Key))
+ )
+ .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
+ }
+ );
+
+ ///
+ /// 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.
+ ///
+ 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}.")
+ };
+
+ ///
+ /// Returns a string that represents the magnitude of the amplitude.
+ ///
+ public virtual string FormatMagnitude(double magnitude, double phase) =>
+ (new String('*', (int)System.Math.Ceiling(20.0 * magnitude))).PadRight(20) + $" [ {magnitude:F6} ]";
+
+ ///
+ /// Returns a string that represents the phase of the amplitude.
+ ///
+ public virtual string FormatAngle(double magnitude, double angle)
+ {
+ var PI = System.Math.PI;
+ var offset = PI / 16.0;
+ if (magnitude == 0.0)
+ {
+ return " ";
+ }
+
+ var chart = " ---";
+ if (angle > 0)
+ {
+ if (angle >= (0 * PI / 8) + offset && angle < ((1 * PI / 8) + offset)) { chart = " /-"; }
+ if (angle >= (1 * PI / 8) + offset && angle < ((2 * PI / 8) + offset)) { chart = " / "; }
+ if (angle >= (2 * PI / 8) + offset && angle < ((3 * PI / 8) + offset)) { chart = " +/ "; }
+ if (angle >= (3 * PI / 8) + offset && angle < ((4 * PI / 8) + offset)) { chart = " ↑ "; }
+ if (angle >= (4 * PI / 8) + offset && angle < ((5 * PI / 8) + offset)) { chart = " \\- "; }
+ if (angle >= (5 * PI / 8) + offset && angle < ((6 * PI / 8) + offset)) { chart = " \\ "; }
+ if (angle >= (6 * PI / 8) + offset && angle < ((7 * PI / 8) + offset)) { chart = "+\\ "; }
+ if (angle >= (7 * PI / 8) + offset) { chart = "--- "; }
+ }
+ else if (angle < 0)
+ {
+ var abs_angle = System.Math.Abs(angle);
+ if (abs_angle >= (0 * PI / 8) + offset && abs_angle < ((1 * PI / 8) + offset)) { chart = " \\+"; }
+ if (abs_angle >= (1 * PI / 8) + offset && abs_angle < ((2 * PI / 8) + offset)) { chart = " \\ "; }
+ if (abs_angle >= (2 * PI / 8) + offset && abs_angle < ((3 * PI / 8) + offset)) { chart = " -\\ "; }
+ if (abs_angle >= (3 * PI / 8) + offset && abs_angle < ((4 * PI / 8) + offset)) { chart = " ↓ "; }
+ if (abs_angle >= (4 * PI / 8) + offset && abs_angle < ((5 * PI / 8) + offset)) { chart = " /+ "; }
+ if (abs_angle >= (5 * PI / 8) + offset && abs_angle < ((6 * PI / 8) + offset)) { chart = " / "; }
+ if (abs_angle >= (6 * PI / 8) + offset && abs_angle < ((7 * PI / 8) + offset)) { chart = "-/ "; }
+ }
+
+ return $" {chart} [ {angle,8:F5} rad ]";
+ }
+
+ ///
+ /// Returns a string for the amplitude's polar representation (magnitude/angle).
+ ///
+ public virtual string FormatPolar(double magnitude, double angle) =>
+ $"{FormatMagnitude(magnitude, angle)}{FormatAngle(magnitude, angle)}";
+
+ ///
+ /// Returns a string for the amplitude's cartesian representation (real + imagnary).
+ ///
+ public virtual string FormatCartesian(double real, double img) =>
+ $"{real,9:F6} + {img,9:F6} i";
+
+ 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);
+
+ }
+
+ }
+}
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs b/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs
index 51fa1c153fa..ce3bcf38f63 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/Dump.cs
@@ -2,19 +2,18 @@
// Licensed under the MIT License.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Numerics;
using Microsoft.Quantum.Simulation.Core;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
namespace Microsoft.Quantum.Simulation.Simulators
{
public partial class CommonNativeSimulator
{
- protected virtual QVoid process(Action channel, IQArray? qubits)
- {
- return QVoid.Instance;
- }
-
///
/// Dumps the wave function for the given qubits into the given target.
/// If the target is QVoid or an empty string, it dumps it to the console
@@ -26,30 +25,27 @@ protected virtual QVoid process(Action channel, IQArray? qubits)
///
protected virtual QVoid Dump(T target, IQArray? qubits = null)
{
- var filename = (target is QVoid) ? "" : target.ToString();
- var logMessage = this.Get, Microsoft.Quantum.Intrinsic.Message>();
+ var filename = ((target == null) || (target is QVoid)) ? "" : target.ToString();
- // If no file provided, use `Message` to generate the message into the console;
+ // If no file provided, output to the console;
if (string.IsNullOrWhiteSpace(filename))
{
- var op = this.Get, Microsoft.Quantum.Intrinsic.Message>();
- return process((msg) => op.Apply(msg), qubits);
+ new DisplayableStateDumper(this).Dump(qubits);
}
else
{
try
{
- using (var file = new StreamWriter(filename))
- {
- return process(file.WriteLine, qubits);
- }
+ using var file = new StreamWriter(filename);
+ new DisplayableStateDumper(this, file.WriteLine).Dump(qubits);
}
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;
}
// `QsimDumpMachine` makes an impression that it is never used,
@@ -96,5 +92,135 @@ public QSimDumpRegister(CommonNativeSimulator m) : base(m)
return Simulator.Dump(location, qubits);
};
}
+
+ ///
+ /// This class allows you to dump the state (wave function)
+ /// of the native simulator into a callback function.
+ /// The callback function is triggered for every state basis
+ /// vector in the wavefunction.
+ ///
+ public abstract class StateDumper
+ {
+ ///
+ /// Basic constructor. Takes the simulator to probe.
+ ///
+ public StateDumper(CommonNativeSimulator qsim)
+ {
+ this.Simulator = qsim;
+ }
+
+ ///
+ /// The callback method that will be used to report the amplitude
+ /// of each basis vector of the wave function.
+ /// The method should return 'true' if the simulator should
+ /// continue reporting the state of the remaining basis vectors.
+ ///
+ /// The index of the basis state vector being reported.
+ /// The real portion of the amplitude of the given basis state vector.
+ /// The imaginary portion of the amplitude of the given basis state vector.
+ /// true if dumping should continue, false to stop dumping.
+ public abstract bool Callback(uint idx, double real, double img);
+
+ ///
+ /// The Simulator being reported.
+ ///
+ public CommonNativeSimulator Simulator { get; }
+
+ ///
+ /// Entry method to get the dump of the wave function.
+ ///
+ public virtual bool Dump(IQArray? qubits = null)
+ {
+ if (qubits == null)
+ {
+ this.Simulator.sim_Dump(Callback);
+ return true;
+ }
+ else
+ {
+ var ids = qubits.GetIds();
+ return this.Simulator.sim_DumpQubits((uint)ids.Length, ids, Callback);
+ }
+ }
+ }
+
+ ///
+ /// A state dumper that encodes dumped states into displayable
+ /// objects.
+ ///
+ public class DisplayableStateDumper : StateDumper
+ {
+ private long _count = -1;
+ private IDictionary? _data = null;
+
+ ///
+ /// 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(CommonNativeSimulator sim, Action? fileWriter = null) : base(sim)
+ {
+ this.FileWriter = fileWriter;
+ }
+
+ ///
+ /// Used by the simulator to provide states when dumping.
+ /// Not intended to be called directly.
+ ///
+ 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[(int)idx] = new Complex(real, img);
+ return true;
+ }
+
+ ///
+ /// Dumps the state of a register of qubits as a displayable object.
+ ///
+ 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 Dictionary(); // 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 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,
+ };
+
+ if (this.FileWriter != null)
+ {
+ this.FileWriter(state.ToString());
+ }
+ else
+ {
+ Simulator.MaybeDisplayDiagnostic(state);
+ }
+
+ // Clean up the state vector buffer.
+ _data = null;
+
+ return result;
+ }
+
+ }
}
}
diff --git a/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs b/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs
index 7e33cea1441..42bfca58c8d 100644
--- a/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs
+++ b/src/Simulation/Simulators/CommonNativeSimulator/NativeWrappers.cs
@@ -29,5 +29,9 @@ public partial class CommonNativeSimulator
protected abstract void MCY(uint count, uint[] ctrls, uint qubit);
protected abstract void Z(uint qubit);
protected abstract void MCZ(uint count, uint[] ctrls, uint qubit);
+
+ protected delegate bool DumpCallback(uint idx, double real, double img);
+ protected abstract void sim_Dump(DumpCallback callback);
+ protected abstract bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback);
}
}
diff --git a/src/Simulation/Simulators/QuantumSimulator/Dump.cs b/src/Simulation/Simulators/QuantumSimulator/Dump.cs
index 3e414204905..d89a153c50f 100644
--- a/src/Simulation/Simulators/QuantumSimulator/Dump.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/Dump.cs
@@ -14,7 +14,7 @@ public partial class QuantumSimulator
///
/// Returns the list of the qubits' ids currently allocated in the simulator.
///
- public uint[] QubitIds
+ public override uint[] QubitIds
{
get
{
@@ -26,19 +26,5 @@ public uint[] QubitIds
}
}
- protected override QVoid process(Action channel, IQArray? qubits)
- {
- 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;
- }
}
}
diff --git a/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs b/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs
index b185f287771..4ad08dc2a3d 100644
--- a/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs
+++ b/src/Simulation/Simulators/QuantumSimulator/NativeWrappers.cs
@@ -107,12 +107,12 @@ protected override void MCAdjS(uint count, uint[] ctrls, uint qubit)
MCAdjSNative(this.Id, count, ctrls, qubit);
}
- protected virtual void sim_Dump(DumpCallback callback)
+ protected override void sim_Dump(DumpCallback callback)
{
sim_DumpNative(this.Id, callback);
}
- protected virtual bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback)
+ protected override bool sim_DumpQubits(uint count, uint[] ids, DumpCallback callback)
{
return sim_DumpQubitsNative(this.Id, count, ids, callback);
}
diff --git a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs
deleted file mode 100644
index 22c42a05f6e..00000000000
--- a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using System;
-using System.Diagnostics;
-using Microsoft.Quantum.Simulation.Core;
-
-namespace Microsoft.Quantum.Simulation.Simulators
-{
- public partial class QuantumSimulator
- {
- protected delegate bool DumpCallback(uint idx, double real, double img);
-
- ///
- /// This class allows you to dump the state (wave function)
- /// of the QuantumSimulator into a callback function.
- /// The callback function is triggered for every state basis
- /// vector in the wavefunction.
- ///
- public abstract class StateDumper // Is used by "iqsharp\src\Jupyter\Visualization\StateDisplayOperations.cs".
- {
- ///
- /// Basic constructor. Takes the simulator to probe.
- ///
- public StateDumper(QuantumSimulator qsim)
- {
- this.Simulator = qsim;
- }
-
- ///
- /// The callback method that will be used to report the amplitude
- /// of each basis vector of the wave function.
- /// The method should return 'true' if the QuantumSimulator should
- /// continue reporting the state of the remaining basis vectors.
- ///
- /// The index of the basis state vector being reported.
- /// The real portion of the amplitude of the given basis state vector.
- /// The imaginary portion of the amplitude of the given basis state vector.
- /// true if dumping should continue, false to stop dumping.
- public abstract bool Callback(uint idx, double real, double img);
-
- ///
- /// The QuantumSimulator being reported.
- ///
- public QuantumSimulator Simulator { get; }
-
- ///
- /// Entry method to get the dump of the wave function.
- ///
- public virtual bool Dump(IQArray? qubits = null)
- {
- if (qubits == null)
- {
- this.Simulator.sim_Dump(Callback);
- return true;
- }
- else
- {
- var ids = qubits.GetIds();
- return this.Simulator.sim_DumpQubits((uint)ids.Length, ids, Callback);
- }
- }
- }
-
- ///
- /// A simple implementation of a . It outputs the
- /// a string representation of the state to the given channel.
- ///
- public class SimpleDumper : StateDumper
- {
- private int _maxCharsStateId;
-
- public SimpleDumper(QuantumSimulator qsim, Action channel) : base(qsim)
- {
- this.Channel = channel;
- }
-
- ///
- /// A method to call to output a string representation of the amplitude of each
- /// state basis vector.
- ///
- public virtual Action Channel { get; }
-
- ///
- /// Returns a string that represents the label for the given base state.
- ///
- public virtual string FormatBaseState(uint idx) =>
- $"∣{idx.ToString().PadLeft(_maxCharsStateId, ' ')}❭";
-
- ///
- /// Returns a string that represents the magnitude of the amplitude.
- ///
- public virtual string FormatMagnitude(double magnitude, double phase) =>
- (new String('*', (int)System.Math.Ceiling(20.0 * magnitude))).PadRight(20) + $" [ {magnitude:F6} ]";
-
- ///
- /// Returns a string that represents the phase of the amplitude.
- ///
- public virtual string FormatAngle(double magnitude, double angle)
- {
- var PI = System.Math.PI;
- var offset = PI / 16.0;
- if (magnitude == 0.0)
- {
- return " ";
- }
-
- var chart = " ---";
- if (angle > 0)
- {
- if (angle >= (0 * PI / 8) + offset && angle < ((1 * PI / 8) + offset)) { chart = " /-"; }
- if (angle >= (1 * PI / 8) + offset && angle < ((2 * PI / 8) + offset)) { chart = " / "; }
- if (angle >= (2 * PI / 8) + offset && angle < ((3 * PI / 8) + offset)) { chart = " +/ "; }
- if (angle >= (3 * PI / 8) + offset && angle < ((4 * PI / 8) + offset)) { chart = " ↑ "; }
- if (angle >= (4 * PI / 8) + offset && angle < ((5 * PI / 8) + offset)) { chart = " \\- "; }
- if (angle >= (5 * PI / 8) + offset && angle < ((6 * PI / 8) + offset)) { chart = " \\ "; }
- if (angle >= (6 * PI / 8) + offset && angle < ((7 * PI / 8) + offset)) { chart = "+\\ "; }
- if (angle >= (7 * PI / 8) + offset) { chart = "--- "; }
- }
- else if (angle < 0)
- {
- var abs_angle = System.Math.Abs(angle);
- if (abs_angle >= (0 * PI / 8) + offset && abs_angle < ((1 * PI / 8) + offset)) { chart = " \\+"; }
- if (abs_angle >= (1 * PI / 8) + offset && abs_angle < ((2 * PI / 8) + offset)) { chart = " \\ "; }
- if (abs_angle >= (2 * PI / 8) + offset && abs_angle < ((3 * PI / 8) + offset)) { chart = " -\\ "; }
- if (abs_angle >= (3 * PI / 8) + offset && abs_angle < ((4 * PI / 8) + offset)) { chart = " ↓ "; }
- if (abs_angle >= (4 * PI / 8) + offset && abs_angle < ((5 * PI / 8) + offset)) { chart = " /+ "; }
- if (abs_angle >= (5 * PI / 8) + offset && abs_angle < ((6 * PI / 8) + offset)) { chart = " / "; }
- if (abs_angle >= (6 * PI / 8) + offset && abs_angle < ((7 * PI / 8) + offset)) { chart = "-/ "; }
- }
-
- return $" {chart} [ {angle,8:F5} rad ]";
- }
-
- ///
- /// Returns a string for the amplitude's polar representation (magnitude/angle).
- ///
- public virtual string FormatPolar(double magnitude, double angle) =>
- $"{FormatMagnitude(magnitude, angle)}{FormatAngle(magnitude, angle)}";
-
- ///
- /// Returns a string for the amplitude's cartesian representation (real + imagnary).
- ///
- public virtual string FormatCartesian(double real, double img) =>
- $"{real,9:F6} + {img,9:F6} i";
-
- ///
- /// The method to use to format the amplitude into a string.
- ///
- public virtual string Format(uint idx, double real, double img)
- {
- var amplitude = (real * real) + (img * img);
- var angle = System.Math.Atan2(img, real);
-
- return $"{FormatBaseState(idx)}:\t" +
- $"{FormatCartesian(real, img)}\t == \t" +
- $"{FormatPolar(amplitude, angle)}";
-
- }
-
- ///
- /// 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)
- {
- Channel(Format(idx, real, img));
- return true;
- }
-
- public override bool Dump(IQArray? qubits = null)
- {
- Debug.Assert(this.Simulator.QubitManager != null);
-
- var count = qubits == null
- ? this.Simulator.QubitManager.AllocatedQubitsCount
- : qubits.Length;
- this._maxCharsStateId = ((1 << (int)count) - 1).ToString().Length;
-
- return base.Dump(qubits);
- }
- }
- }
-}