diff --git a/QuIDE/CodeHelpers/BlochSphereGenerator.cs b/QuIDE/CodeHelpers/BlochSphereGenerator.cs
new file mode 100644
index 0000000..6529bd5
--- /dev/null
+++ b/QuIDE/CodeHelpers/BlochSphereGenerator.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Resources;
+using Avalonia.Platform;
+using QuIDE.Properties;
+using ScottPlot;
+using ScottPlot.Plottables;
+using SkiaSharp;
+
+namespace QuIDE.CodeHelpers;
+
+public record struct Coord3D(double X, double Y, double Z);
+
+public class BlochSphereGenerator
+{
+ public int DefaultAzimuthDegrees => 135;
+ public int DefaultElevationDegrees => 245;
+
+ private int _azimuthDegrees;
+ private int _elevationDegrees;
+
+ public BlochSphereGenerator()
+ {
+ _azimuthDegrees = DefaultAzimuthDegrees;
+ _elevationDegrees = DefaultElevationDegrees;
+ }
+
+ ///
+ /// Set Camera position to look at the Bloch Sphere
+ ///
+ /// Horizontal angle to look from (azimuth)
+ /// Vertical angle to look from (elevation)
+ public void SetViewpoint(int horizontal, int vertical)
+ {
+ _azimuthDegrees = Mod360(horizontal);
+ _elevationDegrees = Mod360(vertical);
+ }
+
+ ///
+ /// Helper method, to normalize rotation degrees to 0 - 360
+ ///
+ public static int Mod360(int degree)
+ {
+ degree %= 360;
+ if (degree < 0)
+ degree += 360;
+
+ var result = (degree == 0) ? 360 : degree;
+ return result;
+ }
+
+ ///
+ /// Generate a square Bloch Sphere Image from a 2x2 density matrix.
+ /// This method calculates the Bloch vector from the density matrix and renders it.
+ ///
+ /// The 2x2 complex density matrix of the qubit.
+ /// Size of the image. Used for width and height.
+ /// A ScottPlot.Image representing the Bloch Sphere with the state vector.
+ public ScottPlot.Image GeneratePlot(Complex[,] densityMatrix, int imgSize)
+ {
+ // density Matrix is already normalized
+ Coord3D blochVector = ConvertToBlochVector(densityMatrix);
+ var color = GetVectorColor(blochVector);
+ return GetPlotFromComplexAmplitudes(imgSize, color, blochVector);
+ }
+
+ private Image GetPlotFromComplexAmplitudes(int imgSize, Color vectorColor, Coord3D blochVector)
+ {
+ const double plotLimit = 1.3;
+ Plot plot = new();
+ plot.Title("");
+ plot.Layout.Frameless();
+ plot.HideGrid();
+ plot.Axes.SetLimits(-plotLimit, plotLimit, -plotLimit, plotLimit);
+ plot.Axes.Rules.Clear();
+
+ DrawSphereWireframe(plot);
+ DrawAxesAndLabels(plot);
+ DrawStateVector(plot, vectorColor, blochVector);
+
+ return plot.GetImage(imgSize, imgSize);
+ }
+
+ // // "Mapping" from alpha/beta to "angles" theta/psi to find any point on the surface
+ // private Coord3D ConvertToBlochVector(Complex alpha, Complex beta)
+ // {
+ // Complex num = 2 * (Complex.Conjugate(alpha) * beta); // conjugate alpha = theta/2
+ // double real = num.Real;
+ // double imaginary = num.Imaginary; // y
+ // double z = Math.Pow(alpha.Magnitude, 2) - Math.Pow(beta.Magnitude, 2);
+ // return new Coord3D(real, imaginary, z);
+ // }
+
+ ///
+ /// Converts a 2x2 density matrix into a Bloch vector (x, y, z) coordinates.
+ ///
+ /// The 2x2 complex density matrix. Assumed to be trace-normalized.
+ /// A Coord3D representing the Bloch vector. Its magnitude will be less than or equal to 1.
+ private Coord3D ConvertToBlochVector(Complex[,] densityMatrix)
+ {
+ Complex num = 2 * densityMatrix[0, 1];
+ double x = num.Real;
+ double y = num.Imaginary;
+ double z = densityMatrix[0, 0].Real - densityMatrix[1, 1].Real;
+
+ // The resulting Bloch vector accurately represents pure states (on the surface) and mixed states (inside).
+ // No further normalization of the vector is needed here, as the density matrix is already normalized.
+ return new Coord3D(x, y, z);
+ }
+
+ private Color GetVectorColor(Coord3D blochVector)
+ {
+ // Pure states (length ≈ 1) are red.
+ // Mixed states (length < 1) are blue.
+ double length = Math.Round(Math.Sqrt(Math.Pow(blochVector.X, 2) + Math.Pow(blochVector.Y, 2) + Math.Pow(blochVector.Z, 2)), 3);
+ return (length < 1) ? Colors.Blue : Colors.Red;
+ }
+
+ private void DrawSphereWireframe(Plot plot)
+ {
+ const double negativeHalfPi = -Math.PI / 2;
+ const double halfPi = -(negativeHalfPi);
+ const double eightStep = Math.PI / 8;
+ const double doublePi = 2 * Math.PI;
+
+ // Latitude lines
+ for (double lat = negativeHalfPi; lat <= halfPi; lat += eightStep)
+ {
+ List points = new();
+ for (double lon = 0; lon <= doublePi; lon += 0.1)
+ {
+ points.Add(new Coord3D(
+ Math.Cos(lat) * Math.Cos(lon),
+ Math.Cos(lat) * Math.Sin(lon),
+ Math.Sin(lat)
+ ));
+ }
+
+ Draw3DLine(plot, points, Colors.LightGray, 1, LinePattern.Solid);
+ }
+
+ // Longitude
+ for (double lon = 0; lon < doublePi; lon += eightStep)
+ {
+ List points = new();
+ for (double lat = negativeHalfPi; lat <= halfPi; lat += 0.1)
+ {
+ points.Add(new Coord3D(
+ Math.Cos(lat) * Math.Cos(lon),
+ Math.Cos(lat) * Math.Sin(lon),
+ Math.Sin(lat)
+ ));
+ }
+
+ Draw3DLine(plot, points, Colors.LightGray, 1, LinePattern.Solid);
+ }
+ }
+
+ private void DrawAxesAndLabels(Plot plot)
+ {
+ // Axes
+ List X_Axis = new() { new(-1, 0, 0), new(1, 0, 0) };
+ List Y_Axis = new() { new(0, -1, 0), new(0, 1, 0) };
+ List Z_Axis = new() { new(0, 0, -1), new(0, 0, 1) };
+
+ Draw3DLine(plot, X_Axis, Colors.Gray, 1, LinePattern.DenselyDashed);
+ Draw3DLine(plot, Y_Axis, Colors.Gray, 1, LinePattern.DenselyDashed);
+ Draw3DLine(plot, Z_Axis, Colors.Gray, 1, LinePattern.DenselyDashed);
+
+ // Labels
+ AddText(plot, Resources.KetZero, new Coord3D(0, 0, 1.1));
+ AddText(plot, Resources.KetOne, new Coord3D(0, 0, -1.1));
+ AddText(plot, Resources.KetPlus, new Coord3D(1.1, 0, 0));
+ AddText(plot, Resources.KetMinus, new Coord3D(-1.1, 0, 0));
+ AddText(plot, Resources.KetNegative_I, new Coord3D(0, 1.1, 0));
+ AddText(plot, Resources.KetPositive_I, new Coord3D(0, -1.1, 0));
+ }
+
+ private void DrawStateVector(Plot plot, Color vectorColor, Coord3D vector)
+ {
+ List coordinates = new() { new(0, 0, 0), vector };
+ Draw3DLine(plot, coordinates, vectorColor, 3, LinePattern.Solid, true);
+
+ var (_, projectedEnd) = Project(vector);
+ Marker arrowHead = plot.Add.Marker(projectedEnd);
+ arrowHead.MarkerStyle.FillStyle.Color = vectorColor;
+ arrowHead.MarkerStyle.Shape = MarkerShape.FilledTriangleUp;
+ arrowHead.MarkerStyle.Size = 7f;
+ }
+
+ private Scatter Draw3DLine(Plot plot, List points3d, Color color, float lineWidth, LinePattern pattern, bool ignoreDepth = false)
+ {
+ // Project 3D to 2D -> create illusion of 3D on a 2D plane
+ var projectedPoints = points3d.Select(s => Project(s).projected).ToList();
+ var avgDepth = points3d.Average(a => Project(a).rotated.Z);
+
+ var scatter = plot.Add.Scatter(projectedPoints);
+ scatter.Color = color;
+ scatter.LineWidth = lineWidth;
+
+ if (ignoreDepth)
+ scatter.LinePattern = pattern;
+ else
+ scatter.LinePattern = (avgDepth < -0.1) ? LinePattern.Dotted : pattern;
+
+ scatter.MarkerSize = 0;
+ return scatter;
+ }
+
+ private void AddText(Plot plt, string text, Coord3D position)
+ {
+ var (_, projectedPos) = Project(position);
+ var label = plt.Add.Text(text, projectedPos);
+ label.LabelStyle.FontSize = 18;
+ label.LabelStyle.Bold = true;
+ label.LabelStyle.Alignment = Alignment.MiddleCenter;
+ }
+
+ ///
+ /// Project 3D coordinate into a 2D coordinate
+ ///
+ private (Coord3D rotated, Coordinates projected) Project(Coord3D coord)
+ {
+ // convert view angles to radiants
+ double azimuth = _azimuthDegrees * Math.PI / 180.0;
+ double elevation = _elevationDegrees * Math.PI / 180.0;
+
+ // apply rotation matrix
+ // > around Z-axis (azimuth - horizontal)
+ double x_1 = coord.X * Math.Cos(azimuth) - coord.Y * Math.Sin(azimuth);
+ double y_1 = coord.X * Math.Sin(azimuth) + coord.Y * Math.Cos(azimuth);
+ double z_1 = coord.Z;
+
+ // > around X-axis (elevation - vertical)
+ double x_2 = x_1;
+ double y_2 = y_1 * Math.Cos(elevation) - z_1 * Math.Sin(elevation);
+ double z_2 = y_1 * Math.Sin(elevation) + z_1 * Math.Cos(elevation); // depth
+
+ Coord3D result3D = new(x_2, y_2, z_2);
+ Coordinates result2D = new(x_2, y_2);
+ return (result3D, result2D);
+ }
+
+ public static ScottPlot.Image GeneratePlaceholder(int imgSize, string text)
+ {
+ var plot = new Plot();
+
+ // uniform gray background
+ var bg = new ScottPlot.Color(211, 211, 211, 100);
+ plot.FigureBackground.Color = bg; // outside the data area
+ plot.DataBackground.Color = bg; // inside the data area
+
+ // hide axes/ticks/frame
+ plot.Axes.Frameless();
+ plot.Axes.SetLimits(0, 1, 0, 1);
+ plot.HideGrid();
+
+ // centered text
+ var label = plot.Add.Text(text, 0.5, 0.5);
+ label.Alignment = Alignment.MiddleCenter;
+ label.LabelFontColor = new ScottPlot.Color(60, 60, 60);
+ label.LabelFontSize = 18;
+
+ return plot.GetImage(imgSize, imgSize);
+ }
+}
\ No newline at end of file
diff --git a/QuIDE/Properties/Resources.Designer.cs b/QuIDE/Properties/Resources.Designer.cs
index fcf8ce7..f40403a 100644
--- a/QuIDE/Properties/Resources.Designer.cs
+++ b/QuIDE/Properties/Resources.Designer.cs
@@ -1,59 +1,42 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-using System.Reflection;
-
namespace QuIDE.Properties {
using System;
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
- private static global::System.Resources.ResourceManager resourceMan;
+ private static System.Resources.ResourceManager resourceMan;
- private static global::System.Globalization.CultureInfo resourceCulture;
+ private static System.Globalization.CultureInfo resourceCulture;
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources() {
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public Resources() {
}
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- public static global::System.Resources.ResourceManager ResourceManager {
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static System.Resources.ResourceManager ResourceManager {
get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("QuIDE.Properties.Resources", typeof(Resources).Assembly);
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("QuIDE.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- public static global::System.Globalization.CultureInfo Culture {
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ public static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@@ -62,1061 +45,759 @@ internal Resources() {
}
}
- ///
- /// Looks up a localized string similar to About.
- ///
- public static string About {
- get {
- return ResourceManager.GetString("About", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to QuIDE - Quantum Integrated Development Environment
- ///
- public static string Name {
- get {
- return ResourceManager.GetString("Name", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to QuIDE - Quantum Integrated Development Environment
- ///
- public static string Copyright {
- get {
- return ResourceManager.GetString("Copyright", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Absolute.
- ///
public static string Absolute {
get {
return ResourceManager.GetString("Absolute", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Add Control Bit.
- ///
public static string AddControl {
get {
return ResourceManager.GetString("AddControl", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Add Parameter.
- ///
- public static string AddParam {
- get {
- return ResourceManager.GetString("AddParam", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Add Qubit to Register.
- ///
public static string AddQubit {
get {
return ResourceManager.GetString("AddQubit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Add New Register.
- ///
public static string AddRegister {
get {
return ResourceManager.GetString("AddRegister", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Add Step.
- ///
public static string AddStep {
get {
return ResourceManager.GetString("AddStep", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Amplitude.
- ///
public static string Amplitude {
get {
return ResourceManager.GetString("Amplitude", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to If amplitudes are not normalized (probabilities of possible states do not sum up to 1), they will be automatically normalized before register creation..
- ///
- public static string AmplitudesNormalizationCaution {
- get {
- return ResourceManager.GetString("AmplitudesNormalizationCaution", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Angle Value :.
- ///
public static string AngleValue {
get {
return ResourceManager.GetString("AngleValue", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Apply.
- ///
public static string Apply {
get {
return ResourceManager.GetString("Apply", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Authors:
- ///Joanna Patrzyk (jpatrzyk@QuIDE.eu)
- ///Bartłomiej Patrzyk (bpatrzyk@QuIDE.eu).
- ///
- public static string Authors {
- get {
- return ResourceManager.GetString("Authors", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Calculator.
- ///
- public static string Calculator {
- get {
- return ResourceManager.GetString("Calculator", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Cancel.
- ///
public static string Cancel {
get {
return ResourceManager.GetString("Cancel", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Circuit Designer.
- ///
public static string CircuitDesigner {
get {
return ResourceManager.GetString("CircuitDesigner", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Clear.
- ///
- public static string ClearAll {
- get {
- return ResourceManager.GetString("ClearAll", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Clear Circuit.
- ///
public static string ClearCircuit {
get {
return ResourceManager.GetString("ClearCircuit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Clear Selection [Delete].
- ///
- public static string ClearSelection {
- get {
- return ResourceManager.GetString("ClearSelection", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Composite Gate.
- ///
public static string Composite {
get {
return ResourceManager.GetString("Composite", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Console Output.
- ///
public static string ConsoleOutput {
get {
return ResourceManager.GetString("ConsoleOutput", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Copy [Ctrl+C].
- ///
public static string Copy {
get {
return ResourceManager.GetString("Copy", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Copy Result.
- ///
- public static string CopyResult {
- get {
- return ResourceManager.GetString("CopyResult", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Conditional Phase Kick (Phase Shift) Gate For QFT.
- ///
public static string CPhaseShift {
get {
return ResourceManager.GetString("CPhaseShift", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Cut [Ctrl+X].
- ///
public static string Cut {
get {
return ResourceManager.GetString("Cut", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Delete Column.
- ///
public static string DeleteColumn {
get {
return ResourceManager.GetString("DeleteColumn", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Delete Qubit.
- ///
public static string DeleteQubit {
get {
return ResourceManager.GetString("DeleteQubit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Delete Register.
- ///
public static string DeleteRegister {
get {
return ResourceManager.GetString("DeleteRegister", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Delete Row.
- ///
public static string DeleteRow {
get {
return ResourceManager.GetString("DeleteRow", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Phase Distance Value (k) :.
- ///
public static string DistValue {
get {
return ResourceManager.GetString("DistValue", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Drag and Drop selected gates.
- ///
public static string DragGates {
get {
return ResourceManager.GetString("DragGates", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Edit....
- ///
- public static string Edit {
- get {
- return ResourceManager.GetString("Edit", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Enter Name for the new Composite Gate :.
- ///
- public static string EnterName {
- get {
- return ResourceManager.GetString("EnterName", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Erase Gate.
- ///
public static string EraseGate {
get {
return ResourceManager.GetString("EraseGate", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Flip Bit.
- ///
public static string FlipBit {
get {
return ResourceManager.GetString("FlipBit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Generate Code From Circuit.
- ///
public static string GenerateCode {
get {
return ResourceManager.GetString("GenerateCode", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Generate Circuit From Code.
- ///
public static string GenerateFromCode {
get {
return ResourceManager.GetString("GenerateFromCode", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to GNU GENERAL PUBLIC LICENSE
- /// Version 3, 29 June 2007
- ///
- /// Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- /// Everyone is permitted to copy and distribute verbatim copies
- /// of this license document, but changing it is not allowed.
- ///
- /// Preamble
- ///
- /// The GNU General Public License is a free, copyleft license for
- ///software and other kinds of works.
- ///
- /// The licenses for most software and other practical works are designed
- ///to take away your free [rest of string was truncated]";.
- ///
- public static string GPLText {
- get {
- return ResourceManager.GetString("GPLText", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Group.
- ///
- public static string Group {
- get {
- return ResourceManager.GetString("Group", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Create Composite Gate from selected gates.
- ///
- public static string GroupTip {
- get {
- return ResourceManager.GetString("GroupTip", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Hadamard Gate.
- ///
public static string Hadamard {
get {
return ResourceManager.GetString("Hadamard", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Run In Console.
- ///
- public static string InConsole {
- get {
- return ResourceManager.GetString("InConsole", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Initial register state:.
- ///
- public static string InitState {
- get {
- return ResourceManager.GetString("InitState", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Initial register value.
- ///
- public static string InitValue {
- get {
- return ResourceManager.GetString("InitValue", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Insert Column on the Left.
- ///
public static string InsertColumnLeft {
get {
return ResourceManager.GetString("InsertColumnLeft", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Column on the Right.
- ///
public static string InsertColumnRight {
get {
return ResourceManager.GetString("InsertColumnRight", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Qubit Above.
- ///
public static string InsertQubitAbove {
get {
return ResourceManager.GetString("InsertQubitAbove", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Qubit Below.
- ///
public static string InsertQubitBelow {
get {
return ResourceManager.GetString("InsertQubitBelow", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Register Above.
- ///
public static string InsertRegisterAbove {
get {
return ResourceManager.GetString("InsertRegisterAbove", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Register Below.
- ///
public static string InsertRegisterBelow {
get {
return ResourceManager.GetString("InsertRegisterBelow", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Row Above.
- ///
public static string InsertRowAbove {
get {
return ResourceManager.GetString("InsertRowAbove", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Insert Row Below.
- ///
public static string InsertRowBelow {
get {
return ResourceManager.GetString("InsertRowBelow", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Inversed Conditional Phase Kick (Phase Shift) Gate For QFT.
- ///
public static string InvCPhaseShift {
get {
return ResourceManager.GetString("InvCPhaseShift", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to QuIDE is available under the GNU General Public License:.
- ///
- public static string License {
- get {
- return ResourceManager.GetString("License", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to The matrix is not unitary..
- ///
public static string MatrixNotUnitary {
get {
return ResourceManager.GetString("MatrixNotUnitary", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Measurement.
- ///
public static string Measure {
get {
return ResourceManager.GetString("Measure", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to New [Ctrl+N].
- ///
public static string New {
get {
return ResourceManager.GetString("New", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Step Forward [F7].
- ///
public static string NextStep {
get {
return ResourceManager.GetString("NextStep", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Open [Ctrl+O].
- ///
public static string Open {
get {
return ResourceManager.GetString("Open", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Operation Matrix :.
- ///
public static string OperationMatrix {
get {
return ResourceManager.GetString("OperationMatrix", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Output.
- ///
public static string Output {
get {
return ResourceManager.GetString("Output", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Paste [Ctrl+V].
- ///
public static string Paste {
get {
return ResourceManager.GetString("Paste", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Phase Kick (Phase Shift) Gate.
- ///
public static string PhaseKick {
get {
return ResourceManager.GetString("PhaseKick", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Phase Scale Gate.
- ///
public static string PhaseScale {
get {
return ResourceManager.GetString("PhaseScale", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π.
- ///
public static string Pi {
get {
return ResourceManager.GetString("Pi", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π / 2.
- ///
public static string Pi_2 {
get {
return ResourceManager.GetString("Pi_2", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π / 3.
- ///
public static string Pi_3 {
get {
return ResourceManager.GetString("Pi_3", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π / 4.
- ///
public static string Pi_4 {
get {
return ResourceManager.GetString("Pi_4", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π / 6.
- ///
public static string Pi_6 {
get {
return ResourceManager.GetString("Pi_6", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to π / 8.
- ///
public static string Pi_8 {
get {
return ResourceManager.GetString("Pi_8", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Pointer.
- ///
public static string Pointer {
get {
return ResourceManager.GetString("Pointer", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Step Back [F6].
- ///
public static string PrevStep {
get {
return ResourceManager.GetString("PrevStep", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Print.
- ///
public static string Print {
get {
return ResourceManager.GetString("Print", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Probability.
- ///
public static string Probability {
get {
return ResourceManager.GetString("Probability", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Probability Scale.
- ///
public static string ProbabilityScale {
get {
return ResourceManager.GetString("ProbabilityScale", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Properties.
- ///
public static string Properties {
get {
return ResourceManager.GetString("Properties", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Quantum Fourier Transform.
- ///
public static string QFT {
get {
return ResourceManager.GetString("QFT", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Qubits.
- ///
public static string Qubits {
get {
return ResourceManager.GetString("Qubits", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Number of new qubits.
- ///
- public static string QubitsNumber {
- get {
- return ResourceManager.GetString("QubitsNumber", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Redo [Ctrl+Shift+Z].
- ///
- public static string Redo {
- get {
- return ResourceManager.GetString("Redo", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Relative.
- ///
public static string Relative {
get {
return ResourceManager.GetString("Relative", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Remove Qubit from Register.
- ///
public static string RemoveQubit {
get {
return ResourceManager.GetString("RemoveQubit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Restart [F5].
- ///
public static string Restart {
get {
return ResourceManager.GetString("Restart", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Rotate X Gate.
- ///
public static string RotateX {
get {
return ResourceManager.GetString("RotateX", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Rotate Y Gate.
- ///
public static string RotateY {
get {
return ResourceManager.GetString("RotateY", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Rotate Z Gate.
- ///
public static string RotateZ {
get {
return ResourceManager.GetString("RotateZ", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Run To End [F8].
- ///
public static string Run {
get {
return ResourceManager.GetString("Run", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Run In Console.
- ///
public static string RunInConsole {
get {
return ResourceManager.GetString("RunInConsole", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Save [Ctrl+S].
- ///
public static string Save {
get {
return ResourceManager.GetString("Save", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Save As... [Ctrl+Alt+S].
- ///
public static string SaveAs {
get {
return ResourceManager.GetString("SaveAs", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Select Composite Gate....
- ///
public static string SelectCompositeGate {
get {
return ResourceManager.GetString("SelectCompositeGate", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Selected Composite Gate :.
- ///
- public static string SelectedCompositeGate {
- get {
- return ResourceManager.GetString("SelectedCompositeGate", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Selection [Shift] (to move selected, press Shift+Ctrl).
- ///
- public static string Selection {
- get {
- return ResourceManager.GetString("Selection", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Selected Method :.
- ///
public static string SelectMethod {
get {
return ResourceManager.GetString("SelectMethod", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to About QuIDE....
- ///
- public static string ShowAbout {
- get {
- return ResourceManager.GetString("ShowAbout", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Show All.
- ///
public static string ShowAll {
get {
return ResourceManager.GetString("ShowAll", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Show Calculator [Ctrl+K].
- ///
- public static string ShowCalculator {
- get {
- return ResourceManager.GetString("ShowCalculator", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Show Only Non-Zero.
- ///
public static string ShowOnlyNonZero {
get {
return ResourceManager.GetString("ShowOnlyNonZero", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Sigma X Gate (Not).
- ///
public static string SigmaX {
get {
return ResourceManager.GetString("SigmaX", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Sigma Y Gate.
- ///
public static string SigmaY {
get {
return ResourceManager.GetString("SigmaY", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Sigma Z Gate.
- ///
public static string SigmaZ {
get {
return ResourceManager.GetString("SigmaZ", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Square Root of Not Gate.
- ///
public static string SqrtX {
get {
return ResourceManager.GetString("SqrtX", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Amplitude of the state. It is a complex number, which squared magnitude gives the probability of the state..
- ///
public static string StateAmplitude {
get {
return ResourceManager.GetString("StateAmplitude", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Probability of the state. The bar's length represents probability value. Color represents the phase of state's amplitude (which is complex number)..
- ///
public static string StateProbability {
get {
return ResourceManager.GetString("StateProbability", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to State binary representation.
- ///
public static string StateQubits {
get {
return ResourceManager.GetString("StateQubits", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to States Visibility.
- ///
public static string StatesVisibility {
get {
return ResourceManager.GetString("StatesVisibility", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Decimal value of the state.
- ///
public static string StateValue {
get {
return ResourceManager.GetString("StateValue", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Build Circuit.
- ///
+ public static string Ungroup {
+ get {
+ return ResourceManager.GetString("Ungroup", resourceCulture);
+ }
+ }
+
+ public static string Unitary {
+ get {
+ return ResourceManager.GetString("Unitary", resourceCulture);
+ }
+ }
+
+ public static string Value {
+ get {
+ return ResourceManager.GetString("Value", resourceCulture);
+ }
+ }
+
+ public static string SelectedCompositeGate {
+ get {
+ return ResourceManager.GetString("SelectedCompositeGate", resourceCulture);
+ }
+ }
+
+ public static string AddParam {
+ get {
+ return ResourceManager.GetString("AddParam", resourceCulture);
+ }
+ }
+
+ public static string Group {
+ get {
+ return ResourceManager.GetString("Group", resourceCulture);
+ }
+ }
+
+ public static string GroupTip {
+ get {
+ return ResourceManager.GetString("GroupTip", resourceCulture);
+ }
+ }
+
+ public static string UngroupTip {
+ get {
+ return ResourceManager.GetString("UngroupTip", resourceCulture);
+ }
+ }
+
+ public static string EnterName {
+ get {
+ return ResourceManager.GetString("EnterName", resourceCulture);
+ }
+ }
+
+ public static string InitValue {
+ get {
+ return ResourceManager.GetString("InitValue", resourceCulture);
+ }
+ }
+
+ public static string QubitsNumber {
+ get {
+ return ResourceManager.GetString("QubitsNumber", resourceCulture);
+ }
+ }
+
+ public static string InitState {
+ get {
+ return ResourceManager.GetString("InitState", resourceCulture);
+ }
+ }
+
+ public static string AmplitudesNormalizationCaution {
+ get {
+ return ResourceManager.GetString("AmplitudesNormalizationCaution", resourceCulture);
+ }
+ }
+
+ public static string Calculator {
+ get {
+ return ResourceManager.GetString("Calculator", resourceCulture);
+ }
+ }
+
+ public static string CopyResult {
+ get {
+ return ResourceManager.GetString("CopyResult", resourceCulture);
+ }
+ }
+
+ public static string ShowCalculator {
+ get {
+ return ResourceManager.GetString("ShowCalculator", resourceCulture);
+ }
+ }
+
+ public static string ClearAll {
+ get {
+ return ResourceManager.GetString("ClearAll", resourceCulture);
+ }
+ }
+
+ public static string ClearSelection {
+ get {
+ return ResourceManager.GetString("ClearSelection", resourceCulture);
+ }
+ }
+
+ public static string InConsole {
+ get {
+ return ResourceManager.GetString("InConsole", resourceCulture);
+ }
+ }
+
+ public static string Selection {
+ get {
+ return ResourceManager.GetString("Selection", resourceCulture);
+ }
+ }
+
public static string ToCircuit {
get {
return ResourceManager.GetString("ToCircuit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to To Code.
- ///
public static string ToCode {
get {
return ResourceManager.GetString("ToCode", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Undo [Ctrl+Z].
- ///
+ public static string Edit {
+ get {
+ return ResourceManager.GetString("Edit", resourceCulture);
+ }
+ }
+
+ public static string About {
+ get {
+ return ResourceManager.GetString("About", resourceCulture);
+ }
+ }
+
+ public static string ShowAbout {
+ get {
+ return ResourceManager.GetString("ShowAbout", resourceCulture);
+ }
+ }
+
+ public static string Name {
+ get {
+ return ResourceManager.GetString("Name", resourceCulture);
+ }
+ }
+
+ public static string Copyright {
+ get {
+ return ResourceManager.GetString("Copyright", resourceCulture);
+ }
+ }
+
+ public static string Authors {
+ get {
+ return ResourceManager.GetString("Authors", resourceCulture);
+ }
+ }
+
+ public static string GPLText {
+ get {
+ return ResourceManager.GetString("GPLText", resourceCulture);
+ }
+ }
+
+ public static string Redo {
+ get {
+ return ResourceManager.GetString("Redo", resourceCulture);
+ }
+ }
+
public static string Undo {
get {
return ResourceManager.GetString("Undo", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Ungroup.
- ///
- public static string Ungroup {
+ public static string NoImg {
get {
- return ResourceManager.GetString("Ungroup", resourceCulture);
+ return ResourceManager.GetString("NoImg", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Ungroup Composite Gate.
- ///
- public static string UngroupTip {
+ public static string NoQubit {
get {
- return ResourceManager.GetString("UngroupTip", resourceCulture);
+ return ResourceManager.GetString("NoQubit", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Custom Unitary Gate.
- ///
- public static string Unitary {
+ public static string AreaTooSmall {
get {
- return ResourceManager.GetString("Unitary", resourceCulture);
+ return ResourceManager.GetString("AreaTooSmall", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Value.
- ///
- public static string Value {
+ public static string QubitEntanlged {
get {
- return ResourceManager.GetString("Value", resourceCulture);
+ return ResourceManager.GetString("QubitEntanlged", resourceCulture);
}
}
-
- public static string Version
- {
- get
- {
- return "Version: " + Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion;
+
+ public static string KetZero {
+ get {
+ return ResourceManager.GetString("KetZero", resourceCulture);
+ }
+ }
+
+ public static string KetOne {
+ get {
+ return ResourceManager.GetString("KetOne", resourceCulture);
+ }
+ }
+
+ public static string KetPlus {
+ get {
+ return ResourceManager.GetString("KetPlus", resourceCulture);
+ }
+ }
+
+ public static string KetMinus {
+ get {
+ return ResourceManager.GetString("KetMinus", resourceCulture);
+ }
+ }
+
+ public static string KetPositive_I {
+ get {
+ return ResourceManager.GetString("KetPositive_I", resourceCulture);
+ }
+ }
+
+ public static string KetNegative_I {
+ get {
+ return ResourceManager.GetString("KetNegative_I", resourceCulture);
+ }
+ }
+
+ public static string Version {
+ get {
+ return ResourceManager.GetString("Version", resourceCulture);
+ }
+ }
+
+ public static string NoRegisterForQubitFound {
+ get {
+ return ResourceManager.GetString("NoRegisterForQubitFound", resourceCulture);
}
}
}
diff --git a/QuIDE/Properties/Resources.resx b/QuIDE/Properties/Resources.resx
index 560f90a..db7c2dd 100644
--- a/QuIDE/Properties/Resources.resx
+++ b/QuIDE/Properties/Resources.resx
@@ -450,11 +450,12 @@
QuIDE - Quantum Integrated Development Environment
-
- © 2014 Joanna Patrzyk, Bartłomiej Patrzyk
+
+ © 2014 Joanna Patrzyk, Bartłomiej Patrzyk
© 2023 Marc Fichtner
-© 2023-2024 MNM-Team
-
+© 2023-2024 MNM-Team
+© 2025 Albert Pankratz
+
Authors:
Joanna Patrzyk (jpatrzyk@quide.eu)
@@ -470,4 +471,40 @@ MNM-Team (mnm-team.org)
Undo [Ctrl+Z]
+
+ No Image to render
+
+
+ No Qubit selected
+
+
+ Area too small
+
+
+ Selected qubit is entangled
+
+
+ |0>
+
+
+ |1>
+
+
+ |+>
+
+
+ |->
+
+
+ |i>
+
+
+ |-i>
+
+
+ 2.4.1
+
+
+ Could not find quantum register for selected qubit.
+
\ No newline at end of file
diff --git a/QuIDE/QuIDE.csproj b/QuIDE/QuIDE.csproj
index ed7a552..4d9dbf2 100644
--- a/QuIDE/QuIDE.csproj
+++ b/QuIDE/QuIDE.csproj
@@ -10,6 +10,7 @@
true
true
+ 2.4.2
@@ -48,11 +49,13 @@
+
Designer
+ ResXFileCodeGenerator
diff --git a/QuIDE/ViewModels/Controls/BlochSphereViewModel.cs b/QuIDE/ViewModels/Controls/BlochSphereViewModel.cs
new file mode 100644
index 0000000..59e95c7
--- /dev/null
+++ b/QuIDE/ViewModels/Controls/BlochSphereViewModel.cs
@@ -0,0 +1,116 @@
+using System;
+using System.IO;
+using System.Windows.Input;
+using Avalonia.Media.Imaging;
+using QuIDE.CodeHelpers;
+using QuIDE.Properties;
+
+namespace QuIDE.ViewModels.Controls;
+
+public class BlochSphereViewModel : ViewModelBase
+{
+ private Bitmap _blochImage;
+ private int _horizontalDegree;
+ private int _verticalDegree;
+ private string _stateVector;
+ private int _renderSize = 400;
+ private readonly int _defaultAzimuthDegrees;
+ private readonly int _defaultElevationDegrees;
+
+ public string StateVector
+ {
+ get => _stateVector;
+ set
+ {
+ _stateVector = value;
+ this.OnPropertyChanged(nameof(StateVector));
+ }
+ }
+
+ public int VerticalDegree
+ {
+ get => _verticalDegree;
+ set
+ {
+ _verticalDegree = value;
+ this.OnPropertyChanged(nameof(VerticalDegree));
+ }
+ }
+
+ public int HorizontalDegree
+ {
+ get => _horizontalDegree;
+ set
+ {
+ _horizontalDegree = value;
+ this.OnPropertyChanged(nameof(HorizontalDegree));
+ }
+ }
+
+ public Bitmap BlochImage
+ {
+ get => _blochImage;
+ set
+ {
+ _blochImage = value;
+ this.OnPropertyChanged(nameof(BlochImage));
+ }
+ }
+
+ public int RenderSize
+ {
+ get => _renderSize;
+ set
+ {
+ // Only update if the change is significant to avoid rapid-fire updates
+ if (Math.Abs(_renderSize - value) < 5)
+ return;
+
+ _renderSize = value;
+ OnPropertyChanged(nameof(RenderSize));
+ }
+ }
+
+ public ICommand ResetViewCmd { get; }
+
+ public BlochSphereViewModel()
+ {
+ // needed for avalonia binding
+ }
+
+ public BlochSphereViewModel(int defaultAzimuthDegrees, int defaultElevationDegrees)
+ {
+ ResetViewCmd = new DelegateCommand(ResetView, _ => true);
+ _defaultAzimuthDegrees = defaultAzimuthDegrees;
+ _defaultElevationDegrees = defaultElevationDegrees;
+ ResetView(null);
+ }
+
+ public void ResetView(object obj)
+ {
+ HorizontalDegree = _defaultAzimuthDegrees;
+ VerticalDegree = _defaultElevationDegrees;
+ }
+
+ ///
+ /// Converts the ScottPlot plot image to an Avalonia Bitmap.
+ ///
+ /// A plot image, created through ScottPlot.GetImage(width, height)
+ /// Avlonia Bitmap, which can be used for UI Bindings
+ public Avalonia.Media.Imaging.Bitmap ToBitmap(ScottPlot.Image plot)
+ {
+ if (plot == null)
+ ClearImage(Resources.NoImg);
+
+ using (MemoryStream ms = new MemoryStream(plot.GetImageBytes()))
+ {
+ return new Bitmap(ms);
+ }
+ }
+
+ public void ClearImage(string message)
+ {
+ BlochImage = ToBitmap(BlochSphereGenerator.GeneratePlaceholder(RenderSize, message));
+ StateVector = message;
+ }
+}
\ No newline at end of file
diff --git a/QuIDE/ViewModels/Controls/CircuitGridViewModel.cs b/QuIDE/ViewModels/Controls/CircuitGridViewModel.cs
index 2873c25..4bb9979 100644
--- a/QuIDE/ViewModels/Controls/CircuitGridViewModel.cs
+++ b/QuIDE/ViewModels/Controls/CircuitGridViewModel.cs
@@ -52,11 +52,11 @@ private void OnQubitsChanged()
private readonly ComputerModel _model;
+ private QubitViewModel _selectedQubit;
private ObservableCollection _registers;
private ObservableCollection _steps;
private int _currentStep;
-
private double _scaleFactor = 0.75;
private readonly double _scaleFactorMax = 4.0;
private readonly double _scaleFactorMin = 0.1;
@@ -96,6 +96,28 @@ public CircuitGridViewModel(ComputerModel model, DialogManager dialogManager)
#region Model Properties
+ public QubitViewModel SelectedQubit
+ {
+ get => _selectedQubit;
+ set
+ {
+ // If the same item is set again, do nothing.
+ if (_selectedQubit == value)
+ return;
+
+ // Deselect the old qubit if it exists.
+ if (_selectedQubit != null)
+ _selectedQubit.IsSelected = false;
+
+ _selectedQubit = value;
+
+ // Select the new qubit if it's not null.
+ if (_selectedQubit != null)
+ _selectedQubit.IsSelected = true;
+ OnPropertyChanged(nameof(SelectedQubit));
+ }
+ }
+
public ObservableCollection Registers
{
get
@@ -207,7 +229,7 @@ private ObservableCollection CreateRegistersFromModel()
var registers = new ObservableCollection();
for (var i = 0; i < _model.Registers.Count; i++)
{
- var reg = new RegisterViewModel(_model, i, _dialogManager);
+ var reg = new RegisterViewModel(_model, i, _dialogManager, this);
reg.QubitsChanged += registers_QubitsChanged;
registers.Add(reg);
}
@@ -279,7 +301,7 @@ private void Registers_CollectionChanged(object sender, NotifyCollectionChangedE
var newRow = e.NewStartingIndex;
if (item is RegisterModel)
{
- var reg = new RegisterViewModel(_model, newRow, _dialogManager);
+ var reg = new RegisterViewModel(_model, newRow, _dialogManager, this);
reg.QubitsChanged += registers_QubitsChanged;
Registers.Insert(newRow, reg);
for (var i = newRow + 1; i < _registers.Count; i++) _registers[i].IncrementIndex();
diff --git a/QuIDE/ViewModels/Controls/OutputGridViewModel.cs b/QuIDE/ViewModels/Controls/OutputGridViewModel.cs
index f66fda6..8bd37c9 100644
--- a/QuIDE/ViewModels/Controls/OutputGridViewModel.cs
+++ b/QuIDE/ViewModels/Controls/OutputGridViewModel.cs
@@ -30,6 +30,11 @@ public OutputGridViewModel()
_selectedRegister = new ParameterViewModel("register", typeof(Register), "root");
}
+ public void SetMainViewModel(MainWindowViewModel mainVm)
+ {
+ this._mainVM = mainVm;
+ }
+
#endregion // Constructor
#region Events
@@ -44,7 +49,8 @@ private void OnSelectionChanged()
#endregion // Events
#region Fields
-
+ private MainWindowViewModel _mainVM;
+
private ComputerModel _model;
private OutputViewModel _outputModel;
@@ -80,7 +86,6 @@ public OutputState SelectedObject
get
{
if (_selectedIndex >= 0 && _selectedIndex < States.Length) return States[_selectedIndex].Model;
-
return null;
}
}
@@ -93,6 +98,7 @@ public int SelectedIndex
_selectedIndex = value;
OnPropertyChanged(nameof(SelectedIndex));
OnSelectionChanged();
+ this._mainVM.UpdateBlochSphere();
}
}
diff --git a/QuIDE/ViewModels/Helpers/QubitViewModel.cs b/QuIDE/ViewModels/Helpers/QubitViewModel.cs
index 933bdae..bdf7b41 100644
--- a/QuIDE/ViewModels/Helpers/QubitViewModel.cs
+++ b/QuIDE/ViewModels/Helpers/QubitViewModel.cs
@@ -7,6 +7,7 @@
using Avalonia.Media;
using QuIDE.CodeHelpers;
using QuIDE.QuantumModel;
+using QuIDE.ViewModels.Controls;
using QuIDE.ViewModels.Dialog;
using QuIDE.Views.Dialog;
@@ -16,7 +17,28 @@ namespace QuIDE.ViewModels.Helpers;
public class QubitViewModel : ViewModelBase
{
- public QubitViewModel(ComputerModel model, int registerIndex, int rowIndex, DialogManager dialogManager)
+ private bool _isSelected;
+ private CircuitGridViewModel _topParentVM;
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set
+ {
+ if (_isSelected == value)
+ return;
+
+ _isSelected = value;
+ OnPropertyChanged(nameof(IsSelected));
+
+ if (_isSelected)
+ _topParentVM.SelectedQubit = this;
+ else if (_topParentVM.SelectedQubit == this)
+ _topParentVM.SelectedQubit = null;
+
+ }
+ }
+
+ public QubitViewModel(ComputerModel model, int registerIndex, int rowIndex, DialogManager dialogManager, CircuitGridViewModel topParentVM)
{
_model = model;
_registerIndex = registerIndex;
@@ -25,6 +47,7 @@ public QubitViewModel(ComputerModel model, int registerIndex, int rowIndex, Dial
_deleteRegister = new DelegateCommand(DeleteRegister, x => model.Registers.Count > 1);
_dialogManager = dialogManager;
+ _topParentVM = topParentVM;
}
diff --git a/QuIDE/ViewModels/Helpers/RegisterViewModel.cs b/QuIDE/ViewModels/Helpers/RegisterViewModel.cs
index 8959dff..51e1d8c 100644
--- a/QuIDE/ViewModels/Helpers/RegisterViewModel.cs
+++ b/QuIDE/ViewModels/Helpers/RegisterViewModel.cs
@@ -31,9 +31,9 @@ private void OnQubitsChanged()
private readonly ComputerModel _model;
private int _registerIndex;
-
+
private ObservableCollection _qubits;
-
+ private readonly CircuitGridViewModel _parentCircuitVM;
private readonly DialogManager _dialogManager;
#endregion // Fields
@@ -41,12 +41,13 @@ private void OnQubitsChanged()
#region Constructor
- public RegisterViewModel(ComputerModel model, int registerIndex, DialogManager dialogManager)
+ public RegisterViewModel(ComputerModel model, int registerIndex, DialogManager dialogManager, CircuitGridViewModel parentCircuitVm)
{
_model = model;
_registerIndex = registerIndex;
_dialogManager = dialogManager;
+ _parentCircuitVM = parentCircuitVm;
_model.Registers[_registerIndex].Qubits.CollectionChanged += Qubits_CollectionChanged;
_model.StepChanged += _model_StepChanged;
@@ -57,6 +58,7 @@ public RegisterViewModel(ComputerModel model, int registerIndex, DialogManager d
#region Presentation Properties
+
public ObservableCollection Qubits
{
get
@@ -104,7 +106,7 @@ private ObservableCollection CreateQubitsFromModel()
ObservableCollection qubits = new ObservableCollection();
for (int i = 0; i < _model.Registers[_registerIndex].Qubits.Count; i++)
{
- qubits.Add(new QubitViewModel(_model, _registerIndex, i, _dialogManager));
+ qubits.Add(new QubitViewModel(_model, _registerIndex, i, _dialogManager, _parentCircuitVM));
}
return qubits;
@@ -120,7 +122,7 @@ private void Qubits_CollectionChanged(object sender, NotifyCollectionChangedEven
int newRow = e.NewStartingIndex;
if (item is not QubitModel) continue;
- _qubits.Insert(newRow, new QubitViewModel(_model, _registerIndex, newRow, _dialogManager));
+ _qubits.Insert(newRow, new QubitViewModel(_model, _registerIndex, newRow, _dialogManager, _parentCircuitVM));
for (int i = newRow + 1; i < _qubits.Count; i++)
{
_qubits[i].IncrementRow();
diff --git a/QuIDE/ViewModels/MainWindowViewModel.cs b/QuIDE/ViewModels/MainWindowViewModel.cs
index 2cb4cc3..c83217e 100644
--- a/QuIDE/ViewModels/MainWindowViewModel.cs
+++ b/QuIDE/ViewModels/MainWindowViewModel.cs
@@ -1,6 +1,11 @@
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.ComponentModel;
using System.Linq;
+using System.Numerics;
+using System.Resources;
+using System.Text;
using System.Windows.Input;
using Avalonia.Controls;
using QuIDE.CodeHelpers;
@@ -9,9 +14,13 @@
using QuIDE.Views;
using QuIDE.Views.Dialog;
using CommunityToolkit.Mvvm.Input;
+using QuIDE.Properties;
using QuIDE.QuantumModel;
using QuIDE.QuantumParser;
+using QuIDE.ViewModels.Helpers;
+using Image = ScottPlot.Image;
using Parser = QuIDE.QuantumParser.Parser;
+using Register = Quantum.Register;
namespace QuIDE.ViewModels;
@@ -47,13 +56,16 @@ public CircuitGridViewModel CircuitGrid
{
get
{
- if (_circuitGridVM != null) return _circuitGridVM;
+ if (_circuitGridVM != null)
+ return _circuitGridVM;
_circuitGridVM = new CircuitGridViewModel(_model, _dialogManager);
- if (_propertiesVM != null) _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
+ if (_propertiesVM != null)
+ _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
- if (_outputGridVM != null) _outputGridVM.AddQubitsTracing(_circuitGridVM);
+ if (_outputGridVM != null)
+ _outputGridVM.AddQubitsTracing(_circuitGridVM);
return _circuitGridVM;
}
@@ -64,9 +76,11 @@ private set
_circuitGridVM = value;
- if (_propertiesVM != null) _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
+ if (_propertiesVM != null)
+ _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
- if (_outputGridVM != null) _outputGridVM.AddQubitsTracing(_circuitGridVM);
+ if (_outputGridVM != null)
+ _outputGridVM.AddQubitsTracing(_circuitGridVM);
OnPropertyChanged(nameof(CircuitGrid));
}
@@ -80,9 +94,12 @@ public OutputGridViewModel OutputGrid
{
_outputGridVM = new OutputGridViewModel();
_outputGridVM.LoadModel(_model, _outputModel);
- if (_circuitGridVM != null) _outputGridVM.AddQubitsTracing(_circuitGridVM);
+ _outputGridVM.SetMainViewModel(this);
+ if (_circuitGridVM != null)
+ _outputGridVM.AddQubitsTracing(_circuitGridVM);
- if (_propertiesVM != null) _propertiesVM.AddSelectionTracing(_outputGridVM);
+ if (_propertiesVM != null)
+ _propertiesVM.AddSelectionTracing(_outputGridVM);
}
return _outputGridVM;
@@ -94,9 +111,11 @@ private set
_outputGridVM = value;
- if (_circuitGridVM != null) _outputGridVM.AddQubitsTracing(_circuitGridVM);
+ if (_circuitGridVM != null)
+ _outputGridVM.AddQubitsTracing(_circuitGridVM);
- if (_propertiesVM != null) _propertiesVM.AddSelectionTracing(_outputGridVM);
+ if (_propertiesVM != null)
+ _propertiesVM.AddSelectionTracing(_outputGridVM);
OnPropertyChanged(nameof(OutputGrid));
}
@@ -106,12 +125,15 @@ public PropertiesViewModel PropertiesPane
{
get
{
- if (_propertiesVM != null) return _propertiesVM;
+ if (_propertiesVM != null)
+ return _propertiesVM;
_propertiesVM = new PropertiesViewModel(CircuitGrid, OutputGrid);
- if (_outputGridVM != null) _propertiesVM.AddSelectionTracing(_outputGridVM);
+ if (_outputGridVM != null)
+ _propertiesVM.AddSelectionTracing(_outputGridVM);
- if (_circuitGridVM != null) _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
+ if (_circuitGridVM != null)
+ _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
return _propertiesVM;
}
@@ -122,9 +144,11 @@ private set
_propertiesVM = value;
- if (_outputGridVM != null) _propertiesVM.AddSelectionTracing(_outputGridVM);
+ if (_outputGridVM != null)
+ _propertiesVM.AddSelectionTracing(_outputGridVM);
- if (_circuitGridVM != null) _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
+ if (_circuitGridVM != null)
+ _propertiesVM.AddSelectionAndQubitsTracing(_circuitGridVM);
OnPropertyChanged(nameof(PropertiesPane));
}
@@ -147,7 +171,8 @@ public ObservableCollection CompositeTools
{
get
{
- if (_toolsVM != null) return _toolsVM;
+ if (_toolsVM != null)
+ return _toolsVM;
var eval = CircuitEvaluator.GetInstance();
var dict = eval.GetExtensionGates();
@@ -161,6 +186,8 @@ private set
}
}
+ public BlochSphereViewModel BlochSphere { get; private set; }
+
public static ActionName SelectedAction { get; private set; }
public string SelectedComposite
@@ -188,6 +215,7 @@ public void InitializeWindow(MainWindow window)
// they need dialogManager
InitFromModel(ComputerModel.CreateModelForGUI());
+ InitBlochSphereView();
// inject dialogManager and notify handler
EditorPane = new EditorViewModel(_dialogManager, NotifyEditorDependentCommands);
@@ -197,12 +225,40 @@ public void InitializeWindow(MainWindow window)
_consoleWriter.TextChanged += _consoleWriter_TextChanged;
}
+ private void InitBlochSphereView()
+ {
+ _blochSphereGenerator = new BlochSphereGenerator();
+ BlochSphere = new BlochSphereViewModel(_blochSphereGenerator.DefaultAzimuthDegrees, _blochSphereGenerator.DefaultElevationDegrees);
+
+ // when Bloch Sphere sliders are changed or another qubit is selected:
+ // regenerate Bloch Image with new arguments
+ BlochSphere.PropertyChanged += BlochSphereOnPropertyChanged;
+ CircuitGrid.PropertyChanged += CircuitGridOnPropertyChanged;
+ }
+
+ private void CircuitGridOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(CircuitGridViewModel.SelectedQubit))
+ UpdateBlochSphere();
+ }
+
+ private void BlochSphereOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(BlochSphere.VerticalDegree)
+ || e.PropertyName == nameof(BlochSphere.HorizontalDegree)
+ || e.PropertyName == nameof(BlochSphere.RenderSize))
+ {
+ UpdateBlochSphere();
+ }
+ }
+
private async void WindowClosing(object sender, WindowClosingEventArgs args)
{
args.Cancel = true;
var canClose = await EditorPane.EditorCanClose();
- if (!canClose) return;
+ if (!canClose)
+ return;
// Detach self and close with default handler
_window.Closing -= WindowClosing;
@@ -229,6 +285,7 @@ private async void WindowClosing(object sender, WindowClosingEventArgs args)
private ObservableCollection _toolsVM;
private string _selectedComposite;
+ private BlochSphereGenerator _blochSphereGenerator;
private ConsoleWriter _consoleWriter;
@@ -260,7 +317,8 @@ public ICommand CalculatorCommand
{
get
{
- if (_calculatorCommand == null) _calculatorCommand = new DelegateCommand(null, _ => false);
+ if (_calculatorCommand == null)
+ _calculatorCommand = new DelegateCommand(null, _ => false);
return _calculatorCommand;
}
@@ -270,7 +328,8 @@ public ICommand AboutCommand
{
get
{
- if (_aboutCommand == null) _aboutCommand = new DelegateCommand(ShowAbout, _ => true);
+ if (_aboutCommand == null)
+ _aboutCommand = new DelegateCommand(ShowAbout, _ => true);
return _aboutCommand;
}
@@ -280,7 +339,8 @@ public ICommand SelectActionCommand
{
get
{
- if (_selectAction == null) _selectAction = new DelegateCommand(SelectAction, x => true);
+ if (_selectAction == null)
+ _selectAction = new DelegateCommand(SelectAction, x => true);
return _selectAction;
}
@@ -290,7 +350,8 @@ public ICommand GroupCommand
{
get
{
- if (_group == null) _group = new DelegateCommand(MakeComposite, x => true);
+ if (_group == null)
+ _group = new DelegateCommand(MakeComposite, x => true);
return _group;
}
@@ -300,7 +361,8 @@ public ICommand ClearCircuitCommand
{
get
{
- if (_clearCircuit == null) _clearCircuit = new DelegateCommand(ClearCircuit, x => true);
+ if (_clearCircuit == null)
+ _clearCircuit = new DelegateCommand(ClearCircuit, x => true);
return _clearCircuit;
}
@@ -310,7 +372,8 @@ public ICommand CutGatesCommand
{
get
{
- if (_cutGates == null) _cutGates = new DelegateCommand(CutGates, x => true);
+ if (_cutGates == null)
+ _cutGates = new DelegateCommand(CutGates, x => true);
return _cutGates;
}
@@ -320,7 +383,8 @@ public ICommand CopyGatesCommand
{
get
{
- if (_copyGates == null) _copyGates = new DelegateCommand(CopyGates, x => true);
+ if (_copyGates == null)
+ _copyGates = new DelegateCommand(CopyGates, x => true);
return _copyGates;
}
@@ -330,7 +394,8 @@ public ICommand PasteGatesCommand
{
get
{
- if (_pasteGates == null) _pasteGates = new DelegateCommand(PasteGates, x => true);
+ if (_pasteGates == null)
+ _pasteGates = new DelegateCommand(PasteGates, x => true);
return _pasteGates;
}
@@ -340,7 +405,8 @@ public ICommand DeleteGatesCommand
{
get
{
- if (_pasteGates == null) _pasteGates = new DelegateCommand(DeleteGates, x => true);
+ if (_pasteGates == null)
+ _pasteGates = new DelegateCommand(DeleteGates, x => true);
return _pasteGates;
}
@@ -350,7 +416,8 @@ public ICommand RestartCommand
{
get
{
- if (_restart == null) _restart = new DelegateCommand(Restart, x => true);
+ if (_restart == null)
+ _restart = new DelegateCommand(Restart, x => true);
return _restart;
}
@@ -360,7 +427,8 @@ public ICommand PrevStepCommand
{
get
{
- if (_prevStep == null) _prevStep = new DelegateCommand(PrevStep, x => true);
+ if (_prevStep == null)
+ _prevStep = new DelegateCommand(PrevStep, x => true);
return _prevStep;
}
@@ -370,7 +438,8 @@ public ICommand NextStepCommand
{
get
{
- if (_nextStep == null) _nextStep = new DelegateCommand(NextStep, x => true);
+ if (_nextStep == null)
+ _nextStep = new DelegateCommand(NextStep, x => true);
return _nextStep;
}
@@ -380,7 +449,8 @@ public ICommand RunCommand
{
get
{
- if (_run == null) _run = new DelegateCommand(RunToEnd, x => true);
+ if (_run == null)
+ _run = new DelegateCommand(RunToEnd, x => true);
return _run;
}
@@ -437,7 +507,8 @@ await _dialogManager.ShowDialogAsync(new CompositeInput(compositeVM), () =>
_model.MakeComposite(name, toGroup);
- if (_toolsVM.Contains(name)) return;
+ if (_toolsVM.Contains(name))
+ return;
var newTools = _toolsVM;
newTools.Add(name);
@@ -486,7 +557,8 @@ private void GenerateFromCode()
try
{
var code = EditorPane.SelectedDocument?.Editor.Document.Text;
- if (string.IsNullOrWhiteSpace(code)) throw new NullReferenceException("Code is empty or not existing");
+ if (string.IsNullOrWhiteSpace(code))
+ throw new NullReferenceException("Code is empty or not existing");
var asmToBuild = parser.CompileForBuild(code);
var eval = CircuitEvaluator.GetInstance();
@@ -523,7 +595,8 @@ private void RunInConsole()
try
{
var code = EditorPane.SelectedDocument?.Editor.Document.Text;
- if (string.IsNullOrWhiteSpace(code)) throw new NullReferenceException("Code is empty or not existing");
+ if (string.IsNullOrWhiteSpace(code))
+ throw new NullReferenceException("Code is empty or not existing");
var asm = parser.CompileForRun(code);
Parser.Execute(asm, _consoleWriter);
@@ -556,6 +629,7 @@ private void Restart(object parameter)
_outputModel = eval.InitFromModel(_model);
OutputGrid.LoadModel(_model, _outputModel);
+ UpdateBlochSphere();
}
catch (Exception e)
{
@@ -574,13 +648,16 @@ private void PrevStep(object parameter)
}
else
{
- if (!_model.CanStepBack(currentStep - 1)) return;
+ if (!_model.CanStepBack(currentStep - 1))
+ return;
var eval = CircuitEvaluator.GetInstance();
var se = eval.GetStepEvaluator();
var outputChanged = se.RunStep(_model.Steps[currentStep - 1].Gates, true);
_model.CurrentStep = currentStep - 1;
- if (outputChanged) _outputModel.Update(eval.RootRegister);
+ if (outputChanged)
+ _outputModel.Update(eval.RootRegister);
+ UpdateBlochSphere();
}
}
catch (Exception e)
@@ -596,14 +673,18 @@ private void NextStep(object parameter)
var eval = CircuitEvaluator.GetInstance();
var currentStep = _model.CurrentStep;
- if (currentStep == 0) eval.InitFromModel(_model);
+ if (currentStep == 0)
+ eval.InitFromModel(_model);
- if (currentStep >= _model.Steps.Count) return;
+ if (currentStep >= _model.Steps.Count)
+ return;
var se = eval.GetStepEvaluator();
var outputChanged = se.RunStep(_model.Steps[currentStep].Gates);
_model.CurrentStep = currentStep + 1;
- if (outputChanged) _outputModel.Update(eval.RootRegister);
+ if (outputChanged)
+ _outputModel.Update(eval.RootRegister);
+ UpdateBlochSphere();
}
catch (Exception e)
{
@@ -618,12 +699,15 @@ private void RunToEnd(object parameter)
var eval = CircuitEvaluator.GetInstance();
var currentStep = _model.CurrentStep;
- if (currentStep == 0) eval.InitFromModel(_model);
+ if (currentStep == 0)
+ eval.InitFromModel(_model);
var se = eval.GetStepEvaluator();
var outputChanged = se.RunToEnd(_model.Steps, currentStep);
_model.CurrentStep = _model.Steps.Count;
- if (outputChanged) _outputModel.Update(eval.RootRegister);
+ if (outputChanged)
+ _outputModel.Update(eval.RootRegister);
+ UpdateBlochSphere();
}
catch (Exception e)
{
@@ -650,7 +734,6 @@ private async void ShowAbout(object o)
await new AboutWindow().ShowDialog(_window);
}
-
#region Private Helpers
private void InitFromModel(ComputerModel model)
@@ -663,7 +746,7 @@ private void InitFromModel(ComputerModel model)
foreach (var pair in oldComposites.Where(pair => !newComposites.ContainsKey(pair.Key)))
newComposites[pair.Key] = pair.Value;
}
-
+
try
{
_model = model;
@@ -675,10 +758,9 @@ private void InitFromModel(ComputerModel model)
}
catch (NullReferenceException)
{
- SimpleDialogHandler.ShowSimpleMessage("No circuit to build.","Warning");
+ SimpleDialogHandler.ShowSimpleMessage("No circuit to build.", "Warning");
ClearCircuit(true);
}
-
}
private void _consoleWriter_TextChanged(object sender, EventArgs eventArgs)
@@ -689,11 +771,153 @@ private void _consoleWriter_TextChanged(object sender, EventArgs eventArgs)
private static void PrintException(Exception e)
{
var message = e.Message;
- if (e.InnerException != null) message = message + ":\n" + e.InnerException.Message;
+ if (e.InnerException != null)
+ message = message + ":\n" + e.InnerException.Message;
message = message + "\n" + e.StackTrace;
SimpleDialogHandler.ShowSimpleMessage(message);
}
#endregion // Private Helpers
+
+ public void UpdateBlochSphere()
+ {
+ (Register qubitSubRegister, bool success, string errorMessage) = GetSelectedQubitRegister();
+
+ if (success == false)
+ {
+ BlochSphere.ClearImage(errorMessage);
+ return;
+ }
+
+ RenderBlochSphereImageAndText(qubitSubRegister);
+ }
+
+ #region BlochSphereHelpers
+
+ ///
+ /// Retrieves the quantum sub-register for the currently selected qubit.
+ /// Handles initial null checks for UI elements and parser components.
+ ///
+ ///
+ /// A tuple containing:
+ /// - The `Quantum.Register` instance for the selected single qubit.
+ /// - A boolean indicating success.
+ /// - An error message string if unsuccessful, otherwise null.
+ ///
+ private (Register qubitSubRegister, bool success, string errorMessage) GetSelectedQubitRegister()
+ {
+ // Get the currently selected qubit from the circuit grid.
+ QubitViewModel selectedQubit = CircuitGrid?.SelectedQubit;
+ if (selectedQubit == null)
+ return (null, false, Resources.NoQubit); // No qubit selected.
+
+ QuantumComputer qc = QuantumComputer.GetInstance();
+ QuantumParser.Register parserRegister = qc.FindRegister(selectedQubit.RegisterName);
+ if (parserRegister == null)
+ return (null, false, Resources.NoRegisterForQubitFound);
+
+ Register quantumRegister = parserRegister.SourceRegister;
+ Register qubitSubRegister = quantumRegister[selectedQubit.Index, 1];
+ return (qubitSubRegister, true, null);
+ }
+
+ ///
+ /// Renders the Bloch sphere image and updates the state vector text based on the qubit's state.
+ /// This method distinguishes between pure and mixed states, calling the appropriate BlochSphereGenerator method.
+ ///
+ /// The single-qubit quantum register model.
+ private void RenderBlochSphereImageAndText(Register qubitSubRegister)
+ {
+ try
+ {
+ int imgSize = BlochSphere.RenderSize;
+ // Check if the render area is too small
+ if (imgSize < 20)
+ {
+ BlochSphere.ClearImage(Resources.AreaTooSmall);
+ return;
+ }
+
+ Complex[,] densityMatrix = qubitSubRegister.GetReducedDensityMatrix();
+ if (densityMatrix == null)
+ {
+ BlochSphere.ClearImage("Could not calculate state");
+ return;
+ }
+
+ _blochSphereGenerator.SetViewpoint(BlochSphere.HorizontalDegree, BlochSphere.VerticalDegree);
+ ScottPlot.Image plotImg = _blochSphereGenerator.GeneratePlot(densityMatrix, imgSize);
+
+ BlochSphere.BlochImage = BlochSphere.ToBitmap(plotImg);
+ BlochSphere.StateVector = GetStateVectorTextFromDensityMatrix(densityMatrix);
+ ;
+ }
+ catch (ArgumentException ex)
+ {
+ BlochSphere.ClearImage($"Error calculating density matrix: {ex.Message}");
+ }
+ catch (Exception ex)
+ {
+ BlochSphere.ClearImage($"Error generating Bloch sphere: {ex.Message}");
+ }
+ }
+
+ private static string GetStateVectorTextFromDensityMatrix(Complex[,] densityMatrix)
+ {
+ // First, calculate the Bloch vector components from the density matrix.
+ // This is the universal representation for any state.
+ double x = 2 * densityMatrix[0, 1].Real;
+ double y = 2 * densityMatrix[0, 1].Imaginary;
+ double z = densityMatrix[0, 0].Real - densityMatrix[1, 1].Real;
+
+ // The squared length of the Bloch vector tells us if the state is pure.
+ double lengthSquared = Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2);
+
+ // Use a small tolerance for floating-point comparisons.
+ const double epsilon = 1e-6;
+
+ StringBuilder stateVectorBuilder;
+
+ if (Math.Abs(lengthSquared - 1.0) < epsilon)
+ {
+ // Pure state: We can reconstruct alpha and beta.
+ Complex alpha, beta;
+ alpha = new Complex(Math.Sqrt(densityMatrix[0, 0].Real), 0);
+
+ // Handle the edge case where the state is |1>, so alpha is 0.
+ if (alpha.Magnitude < epsilon)
+ {
+ // If alpha is zero, the state is |1⟩. We can choose beta's phase to be 0 as well.
+ beta = new Complex(1, 0);
+ }
+ else
+ {
+ // We use ρ₁₀ = β * α* to solve for β. Since α is real, α* = α.
+ // β = ρ₁₀ / α
+ beta = densityMatrix[1, 0] / alpha;
+ }
+
+ stateVectorBuilder = new StringBuilder();
+ stateVectorBuilder.AppendLine("State: Pure");
+ stateVectorBuilder.AppendLine($"α ≈ {alpha.Real:F3} + {alpha.Imaginary:F3}i");
+ stateVectorBuilder.AppendLine($"β ≈ {beta.Real:F3} + {beta.Imaginary:F3}i");
+ }
+ else
+ {
+ // Mixed state: There is no single alpha/beta. We display the density matrix elements.
+ stateVectorBuilder = new StringBuilder();
+ stateVectorBuilder.AppendLine("State: Mixed");
+ stateVectorBuilder.Append($@"ρ₀₀ = {densityMatrix[0, 0].Real:F3} ");
+ stateVectorBuilder.AppendLine($@"ρ₀₁ = {densityMatrix[0, 1].Real:F3} + {densityMatrix[0, 1].Imaginary:F3}i");
+ stateVectorBuilder.Append($@"ρ₁₀ = {densityMatrix[1, 0].Real:F3} + {densityMatrix[1, 0].Imaginary:F3}i ");
+ stateVectorBuilder.AppendLine($@"ρ₁₁ = {densityMatrix[1, 1].Real:F3}");
+ }
+
+ // Bloch vector.
+ stateVectorBuilder.AppendLine($"Bloch Vector: (x={x:F3}, y={y:F3}, z={z:F3})");
+ return stateVectorBuilder.ToString();
+ }
+
+ #endregion BlochSphereHelpers
}
\ No newline at end of file
diff --git a/QuIDE/Views/Controls/BlochSphere.axaml b/QuIDE/Views/Controls/BlochSphere.axaml
new file mode 100644
index 0000000..f90dca2
--- /dev/null
+++ b/QuIDE/Views/Controls/BlochSphere.axaml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/QuIDE/Views/Controls/BlochSphere.axaml.cs b/QuIDE/Views/Controls/BlochSphere.axaml.cs
new file mode 100644
index 0000000..1de9a06
--- /dev/null
+++ b/QuIDE/Views/Controls/BlochSphere.axaml.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Linq;
+using System.Threading;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Markup.Xaml;
+using Avalonia.Threading;
+using QuIDE.CodeHelpers;
+using QuIDE.ViewModels.Controls;
+
+namespace QuIDE.Views.Controls;
+
+public partial class BlochSphere : UserControl
+{
+ private bool _isDragging;
+ private Point _pressPoint;
+ private int _startAzimuth;
+ private int _startElevation;
+ private const double DegreesPerPixel = 0.5;
+
+ public BlochSphere()
+ {
+ InitializeComponent();
+ this.SizeChanged += OnBlochSphereSizeChanged;
+ }
+
+ private void OnBlochSphereSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (DataContext is not BlochSphereViewModel vm)
+ return;
+
+ // Use the smaller of the width or height to maintain a square aspect ratio
+ int newSize = (int)Math.Min(e.NewSize.Width, e.NewSize.Height);
+ vm.RenderSize = newSize;
+ }
+
+ private void BlochSphereImage_OnPointerPressed(object sender, PointerPressedEventArgs e)
+ {
+
+
+ if (DataContext is not BlochSphereViewModel vm)
+ return;
+
+ if (e.ClickCount == 2)
+ {
+ vm.ResetView(null);
+ return;
+ }
+ var pt = e.GetCurrentPoint(BlochSphereImage);
+ if (!pt.Properties.IsLeftButtonPressed)
+ return;
+
+ _isDragging = true;
+ _pressPoint = e.GetPosition(BlochSphereImage);
+ _startAzimuth = vm.HorizontalDegree;
+ _startElevation = vm.VerticalDegree;
+
+ // Capture pointer so drag continues even if the pointer leaves the image.
+ e.Pointer.Capture(BlochSphereImage);
+
+ // if (GetVisualRoot() is TopLevel top)
+ // Cursor = new Cursor(StandardCursorType.SizeAll);
+ }
+
+ private void BlochSphereImage_OnPointerMoved(object sender, PointerEventArgs e)
+ {
+ if (!_isDragging)
+ return;
+ if (DataContext is not BlochSphereViewModel vm)
+ return;
+
+ var p = e.GetPosition(BlochSphereImage);
+ var dx = p.X - _pressPoint.X;
+ var dy = p.Y - _pressPoint.Y;
+
+ // Horizontal mouse movement -> azimuth (increase to the right)
+ // Vertical mouse movement -> elevation (drag up decreases dy, typically increase elevation)
+ // change - to + to invert direction of rotation.
+ var newAzimuth = Normalize360(_startAzimuth - (int)(dx * DegreesPerPixel));
+ var newElevation = Normalize360(_startElevation - (int)(dy * DegreesPerPixel));
+
+ vm.HorizontalDegree = newAzimuth;
+ vm.VerticalDegree = newElevation;
+ }
+
+ private void BlochSphereImage_OnPointerReleased(object sender, PointerReleasedEventArgs e)
+ {
+ if (!_isDragging)
+ return;
+
+ _isDragging = false;
+ e.Pointer.Capture(null);
+ }
+
+ private int Normalize360(int degrees)
+ {
+ // keep 0 mapped to 360 for consistency.
+ return BlochSphereGenerator.Mod360(degrees);
+ }
+}
\ No newline at end of file
diff --git a/QuIDE/Views/Controls/CircuitGrid.axaml b/QuIDE/Views/Controls/CircuitGrid.axaml
index db3f597..5685222 100644
--- a/QuIDE/Views/Controls/CircuitGrid.axaml
+++ b/QuIDE/Views/Controls/CircuitGrid.axaml
@@ -62,7 +62,6 @@
@@ -90,50 +89,53 @@
+
+
-
+
-
+
-
+
-
+
-
+
-
@@ -259,7 +261,7 @@
-