Tomographer  v5.3
Tomographer C++ Framework Documentation
Tomorun and custom figures of merit

The tomorun executable has several figures of merit built into the program: the trace distance, the purified distance, or the fidelity to any reference state, as well as the expectation value of an observable. If you wish to produce a histogram of a different figure of merit which can't be cast into one of these, you have the following options.

I. Use the Python module, which allows you to specify any custom figure of merit given as a Python callable;

II. Write a small, special-purpose C++ program which does exactly what you need, in which you can code your custom figure of merit;

III. Modify the source of the tomorun program itself, to add your new figure of merit.

Option I is the simplest, and should be your default choice; options II and III require a bit more work.

Option II may be easier if you have a very special purpose which might not warrant inclusion into the generic tomorun program. You can simply combine the required tools into a new special-purpose program. This is not difficult, and there are already examples ready—see Creating a custom tomorun-like program.

In the following we describe the necessary steps for Option III.

Note
If you perform modifications which may be useful to others, please fork the repository on github, perform your changes, and send me a pull request. This way your changes will be availble to other users who would like to use the Tomographer project. Please see here for information on how to contribute.

We'll illustrate these steps with a simple example: the two-norm distance (aka. the Hilbert-Schmidt distance) to any reference state, defined by \( d_\mathrm{HS}(\rho,\rho_{\mathrm{Ref}}) = \Vert \rho-\rho_{\mathrm{Ref}}\Vert_2 \), with \( \Vert A\Vert_2 = \mathrm{tr}\left(A^\dagger A\right) \).

1. Code how to calculate your figure of merit

First, you should write the code which calculates the figure of merit, complying to a ValueCalculator Interface type interface. Your new class should in particular have a method getValue(const MatrixType & T) taking as argument an Eigen matrix type which will be a matrix square root (see T Parameterization) of the quantum state rho for which the function should calculate the figure of merit.

You should do this in a new header file, that's the easiest.

For our example, we can get inspired by the code for, e.g., Tomographer::DenseDM::TSpace::TrDistToRefCalculator defined in tspacefigofmerit.h. For example, let's create a file called "hs_dist.h" inside the "tomorun/" directory of the tomographer project:

#ifndef HS_DIST_H
#define HS_DIST_H
#include <Eigen/Eigen>
template<typename DMTypes_, typename ValueType_ = double>
class HSDistToRefCalculator
: public virtual Tomographer::Tools::NeedOwnOperatorNew<typename DMTypes_::MatrixType>::ProviderType
{
public:
typedef DMTypes_ DMTypes;
// this is the type to use to store a dense (dim x dim) matrix:
typedef typename DMTypes::MatrixType MatrixType;
typedef typename DMTypes::MatrixTypeConstRef MatrixTypeConstRef;
// For the ValueCalculator interface: the value type
typedef ValueType_ ValueType;
private:
const MatrixType rho_ref;
public:
// Constructor, the reference state is 'rho_ref'
TrDistToRefCalculator(MatrixTypeConstRef rho_ref_)
: rho_ref(rho_ref_)
{
}
// This method actually calculates the given value. The argument "T" is
// the T-parameterization of the density matrix rho, which is simply a
// square root of rho. (This is indeed the representation used during the
// random walk.)
inline ValueType getValue(MatrixTypeConstRef T) const
{
// rho is obtained with T*T.adjoint(). With Eigen, the HS-norm (Frobenius) of a
// matrix is given by A.norm().
return (T*T.adjoint() - rho_ref).norm();
}
};
#endif // HS_DIST_H

The part about needownoperatornew.h and Tomographer::Tools::NeedOwnOperatorNew is to make sure that the object, when created, is aligned in memory. This is needed because the object has a Eigen member (rho_ref) which must be aligned in memory for vectorized operations (see Eigen's docs for alignment issues, there's a lot on that). In the Tomographer project, the Tomographer::Tools::NeedOwnOperatorNew virtual base makes sure that the necessary operator new() is defined so that objects are aligned in memory when allocated.

2. Integrate the new figure of merit into the tomorun program

In order to integrate a new figure of merit into the tomorun program, one simply has to declare it in the "tomorun/tomorun_figofmerit.h" header file.

All you have to do is (1) Write a class which describes how to create the value calculator for this figure of merit, what help text to display, and the option name; and (2) add this class to the list of known figures of merit (at the bottom of the file).

For (1), in our example, we might define the class HsDistFigureOfMerit as follows. (Also, we need to add #include "hs_dist.h" at the top of the file.)

struct HsDistFigureOfMerit
{
// The name of the figure merit for the --value-type option: here, --value-type="HS-dist"
const std::string name{"HS-dist"};
// The ValueCalculator class we need to use, for the given DMTypes
template<typename DMTypes> using ValueCalculator = HSDistToRefCalculator<DMTypes,TomorunReal>;
// The code which instanciates a new ValueCalculator with the appropriate input data
template<typename DMTypes>
static inline ValueCalculator<DMTypes> *
createValueCalculator(DMTypes dmt, const std::string & ref_obj_name, Tomographer::MAT::File * matf)
{
// create the value calculator
return new ValueCalculator<DMTypes>(read_ref_state_rho<DMTypes>(matf, ref_obj_name)) ;
}
// Print some help text to the screen when queried with --help. We can insert footnotes
// using footnotes.addFootNote(...)
static void print(std::ostream & stream, Tomographer::Tools::FmtFootnotes & footnotes) {
stream <<
"The Hilbert-Schmidt distance to a reference state "
<< footnotes.addFootNote(
"The Hilbert-Schmidt distance is computed as d_{HS}(rho,sigma) = "
"tr( (rho - sigma)^\\dagger (rho - sigma) )."
)
<< ". <RefObject> should be the name of a MATLAB variable present in the "
"MATLAB data file. This object should be a complex dim x dim matrix, the "
"density matrix of the reference state. If no <RefObject> is specified, "
"then 'rho_ref' is used."
;
}
};

Finally, for (2), you have to insert your class name (here HsDistFigureOfMerit) into the TomorunFiguresOfMerit tuple at the bottom of the file, in order to make the program aware of this new figure of merit.

Recompile tomorun (and fix any build issues etc.). You may now use your custom figure of merit with the option "--value-type=HS-dist" or "--value-type=HS-dist:varname". Notice that it also appears in the help text when you run "tomorun --help"