Gaussian Unitary Distribution (GUE) Matrices

<<BProbeM` (* load the package BProbe *)

Let Mathematica generate a specified amount of random Matrices of specified dimension distributed according to the Gaussian Unitary Distribution:

(*Generate 5x10x10 random GUE matrices*)
RandoMatrices=ConstantArray[0,{5}];
For[i=1,i≤5,i++,
RandoMatrices[[i]]=RandomVariate[GaussianUnitaryMatrixDistribution[10]];
];

Please note that these matrices are Hermitian and not unitary, the ‘unitary’ in the name does not refer to the resulting matrices.
See a textbook on Random Matrices such as (Mehta, M.L., 2004. Random Matrices, Third Edition. ed. Elsevier) for further details.

NOTE: Since the matrices here are created with a random number generator, results of this .nb will vary
when you go through it! This is intended. The variations will not typically affect any outcome significantly.

Laplacian Point Probe

Initialize the probe

First we show an initialization which calculates a global minimum, since no starting point is manually set.

ProbeInit[RandoMatrices]

Testing the waters using Directional Scans

When unfamiliar and uncertain about the geometry contained in a matrix set, it is sensible to first try and perform some
more naive scans to generate some intuitions about locations of potential minima and thus locations of potential structure
to scan. One method to do this is to use the directional scan feature of BProbeM. 

Note how we start with a rough, i.e. large step size and the default 100 steps, and gradually focus in. This is a typical use
scenario of directional scans. We keep ShowAutoPlot on by default to see how the plot changes.

ProbeDirectionalScan[5];

All five dimensions show the typical parabolic growth of the energy as we retreat from the origin. At this scale,
the directions seem to be largely equivalent and exchangeable. Since nothing appears to be present far away 
from the origin, we reduce the step size.

ProbeDirectionalScan[1];

At this scale, small discrepancies (due to the random nature of the matrices) become apparent between the directions.
We are not confident that the relevant structure will be centered around the origin and can reduce the stepsize significantly
while now forcing an increase in step numbers.

ProbeDirectionalScan[0.01,StepNumber->1000];

We can also create customized plots by using the ProbeGetDirectionalData command to grab the results of the most recent scan:

ProbeDirectionalScan[0.001,StepNumber->10000,ShowAutoPlot-> False];

ListLinePlot[ProbeGetDirectionalData[],AxesLabel->Automatic,PlotLabel->"Customized Line Plot", PlotLegends->Automatic,PlotRange-> Full]

Note how most likely certain directions have global minima slightly away from the origin but most
of the minima still seem to surround the origin more or less. The Global minimum calculated by ProbeInit above
is where the combined energies of all these directions is minimal but given what we see in these scans, we will
likely primarily be interested in the structure around the origin.

Change the starting point of the scan in light of the directional scan

We can at this point still decide that we do not wish to use the calculated global minimum as the starting point, since
we already know something about the matrices via the directional scans that suggests to us that the origin might be
a better place to start the computation. We can change the scan starting point to the origin without recompiling
the operator by using the ProbeReset command:

ProbeReset[StartingPoint->{0,0,0,0,0}]

Note the changed starting point. Also note that in both starting points, the Hessian eigenvalues show no clear hierarchy.
This is as one would expect, since a set of random matrices obviously will not contain any sensible semi-classical geometry
outside of pure noise. This .nb is merely intended as showing use-cases of the BProbeM package.

Start the scan with default values

How do we determine what a sensible step size would be? If we have no idea, the step size guess of BProbeM is a decent option.
However, we can also look at the directional scans and observe that most of the interesting structure (insofar as random matrices
even have any) will be occurring approximately with [-5,5] in all directions. Our step size should thus certainly be smaller than that.
Another thing to check is the distance between approximate local minima in different directions, since the scanning algorithm will
need to be able to jump from one to the next. Given all of this, the algorithm guessed step size of 2.04583 is very reasonable 
(it will often be like that but not always). For the sake of example we will still modify this default step size to a rounded down 2.
It is instructive to try the same scan with different step sizes to see how the results change.

Important note: Since there is no clear hierarchy of the Hessian EVs, we have to force the scan to consider a certain number of 
directions. In this case, since we know all directions to be just about equivalent, we will force a scan in all directions.

Depending on the comp. power of your device, this scan might take some time to complete. In repeated and especially large-scale calculations, 
we would likely turn off the various Trackers for improved computation time unless we specifically care about that information.

ProbeScan[StepSize->2,Dimension-> 5,EnergyTracker->True,EVTracker->True,GradientTracker->True]

Retrieving results ...

The obtained data here will be 5 dimensional, since we used 5 matrices and did not specify a subspace.

(* point cloud *)
pc = ProbeGetPoints[];

(* generalized coherent states *)
cs = ProbeGetGroundstates[];

... and visualize it with PROJECTIONS:

5 dimensional data cannot be plotted directly. When working with fuzzy geometry, one will often encounter spaces
of higher dimensions than 3. To visualize these, we have a variety of different options. The first and almost always most
useful method is to plot projections of the data on 2 or more commonly 3 axes.

Here are some sample projections on various axes (for random matrices, these will be amorphous point clouds, i.e. noise):

ListPointPlot3D[pc[[All,{1,2,3}]],PlotLabel->"Projection onto (x1,x2,x3)", AxesLabel->{"x1","x2","x3"}, BoxRatios->Automatic]

ListPointPlot3D[pc[[All,{3,4,5}]],PlotLabel->"Projection onto (x3,x4,x5)", AxesLabel->{"x3","x4","x5"}, BoxRatios->Automatic]

ListPointPlot3D[pc[[All,{1,3,5}]],PlotLabel->"Projection onto (x1,x3,x5)", AxesLabel->{"x1","x3","x5"}, BoxRatios->Automatic]

... or visualize it with a SECTION THROUGH A PLANE:

A second option for plotting higher dimensional data aside from projections are sections through planes,
i.e. cuts through certain sections. To do this with BProbeM, we restrict the subspace to the desired axes
with ProbeInit. We do a 2D cut here for the sake of simplicity but in practice any sort of cut can be computed.

Note how now that starting point needs to match the dimension of the subspace:

ProbeInit[RandoMatrices,Subspace->{1,5},StartingPoint-> {0,0}]

Perform a directional scan to make sure nothing unexpected has happened:

ProbeDirectionalScan[0.01,StepNumber->1000];

We again force the dimension to be maximal and alter the stepsize.

ProbeScan[Dimension-> 2,StepSize->1]

Plot the now 2D data of a cut through the (x1,x5)-plane. Obviously in the case of GUE matrices this will again just be
an amorphous point cloud:

ListPlot[ProbeGetPoints[],PlotLabel->"Cut through (x1,x5)", AxesLabel->{"x1","x5"}]

Now we perform a 3D cut:

ProbeInit[RandoMatrices,Subspace->{1,2,3},StartingPoint-> {0,0,0}]

ProbeDirectionalScan[0.01,StepNumber->1000];

ProbeScan[Dimension-> 3,StepSize-> 1]

ListPointPlot3D[ProbeGetPoints[],PlotLabel->"Cut through (x1,x2,x3)", AxesLabel->{"x1","x2","x3"}]

Note how this cut is not typically the same as a projection of the structure onto (x1,x2,x3) as we plotted previously.
In a typical scenario, projections will result in more sensible visualizations, since it allows the algorithm to cross
local energy maxima in this plane by moving to another plane. Cuts are more sensitive to such local peaks.

Dirac Point Probe

The procedure for the Dirac and squared Dirac operator is similar. Here we only show another calculation for the Dirac operator
without much further commentary.

Note however that skipping the calculation of the global minimum by selection a specific starting point is especially time conserving
on the Dirac and squared Dirac operator, where this would take quite a bit of time.

Initialize the probe

ProbeInit[RandoMatrices,Probe->"Dirac",StartingPoint-> {0,0,0,0,0}]

ProbeDirectionalScan[0.01,StepNumber->1000];

Scans with the Dirac operator take significantly more time than using the Laplace operator but often result in better scans.

ProbeScan[Dimension-> 5,StepSize-> 2.5,EnergyTracker->True,EVTracker->True,GradientTracker->True]

Retrieving results ...

The obtained data here will be 5 dimensional, since we used 5 matrices and did not specify a subspace.

(* point cloud *)
pc = ProbeGetPoints[];

... and visualize it with PROJECTIONS:

ListPointPlot3D[pc[[All,{1,2,3}]],PlotLabel->"Projection onto (x1,x2,x3)", AxesLabel->{"x1","x2","x3"}, BoxRatios->Automatic]

ListPointPlot3D[pc[[All,{3,4,5}]],PlotLabel->"Projection onto (x3,x4,x5)", AxesLabel->{"x3","x4","x5"}, BoxRatios->Automatic]

ListPointPlot3D[pc[[All,{1,3,5}]],PlotLabel->"Projection onto (x1,x3,x5)", AxesLabel->{"x1","x3","x5"}, BoxRatios->Automatic]

We will not repeat the section-through-a-plane computations here but obviously those can also be performed in the same way for the
Dirac and the squared Dirac operator.

We note again that since these matrices are random matrices, there is no semi-classical structure present beyond an amorphous point cloud.
Studying this behavior for random matrices can however be very useful in later on being able to tell apart noise from actual results contained
in matrix sets, so it is recommended to play around with the GUE matrices and the 2-sphere in particular to get intuitions for the scanning
algorithm and the BProbeM package.