LatNet Builder Manual  2.0.1-11
Software Package for Constructing Highly Uniform Point Sets
Customized tasks

Standard tasks are meant to evaluate a figure of merit for a digital net or to search for the best one.

However, it is possible to define customized tasks if one wants to achieve more specific tasks.

Search tasks have a template template parameter OBSERVER whose template parameter is a member of NetConstruction enumeration. MinimumObserver is the observer which is used by the command-line tool but users can define customized observers.

In the following example, we want to estimate the quantiles of the distribution of the \(P_2\) discrepancy. For this purpose, we will use a random search which will explore a random sample of digital nets. In practice, we only need to change the observer of the task.

We first write a QuantilesObserver class which derives from the MinimumObserver class. This class has the same behaviour as the MinimumObserver class but also computes the quantiles of the values it observes.

template <NetConstruction NC>
class QuantilesObserver : public Task::MinimumObserver<NC>
{
public:
typedef accumulator_set<Real, features<tag::count, tag::min, tag::max, tag::mean, tag::tail_quantile<boost::accumulators::left>>> QuantilesAccumulator;
QuantilesObserver(typename NetConstructionTraits<NC>::SizeParameter sizeParameter, int verbose = 0):
Task::MinimumObserver<NC>(sizeParameter, verbose),
m_numSamples(0),
m_acc(tag::tail<boost::accumulators::left>::cache_size = m_numSamples)
{};
virtual void reset(bool hard = true) override
{
if (hard)
m_acc = QuantilesAccumulator(tag::tail<boost::accumulators::left>::cache_size = 0);
}
void setNumSamples(size_t numSamples)
{
m_numSamples = numSamples;
m_acc = QuantilesAccumulator(tag::tail<boost::accumulators::left>::cache_size = m_numSamples);
}
virtual bool observe(std::unique_ptr<DigitalNetConstruction<NC>> net, const Real& merit) override
{
m_acc(merit);
return Task::MinimumObserver<NC>::observe(std::move(net), merit);
}
const QuantilesAccumulator& accumulator()
{
return m_acc;
}
private:
size_t m_numSamples;
QuantilesAccumulator m_acc;
};

Then we define the parameters of this exploration: the number of samples, the dimension of the digital nets, the size of the random matrices and the figure of merit to consider.

size_t numSamples = 1000;
Dimension s = 10;
NetConstructionTraits<NetConstruction::EXPLICIT>::SizeParameter sizeParam(10, 10);
unsigned int alpha = 2;
auto kernel = LatBuilder::Kernel::PAlphaPLR(alpha);
auto weights = std::make_unique<LatticeTester::ProductWeights>(.7);
auto figure = std::make_unique<FigureOfMerit::CoordUniformFigureOfMerit<LatBuilder::Kernel::PAlphaPLR, EmbeddingType::UNILEVEL>>(std::move(weights), kernel);
std::cout << figure->format() << std::endl;

We then need to construct and execute the task:

auto task = Task::RandomSearch<NetConstruction::EXPLICIT, EmbeddingType::UNILEVEL, QuantilesObserver>(s, sizeParam, std::move(figure), (unsigned int) numSamples);
task.observer().setNumSamples(numSamples);
task.execute();

Finally, we can read from the accumulator of the observer of the task the estimation of the quantiles of the figure of merit and output it in a human-readable manner:

const auto& acc = task.observer().accumulator();
unsigned int numBins = 20;
printTableRow("# mean:", mean(acc));
printTableRow("prob", "quantile");
printTableRow(0.0, boost::accumulators::min(acc));
for (unsigned int i = 1; i < numBins; i++) {
double p = double(i) / numBins;
Real q = quantile(acc, quantile_probability = p);
printTableRow(p, q);
}
printTableRow(1.0, boost::accumulators::max(acc));

The complete example can be found in tutorial/NetQuantiles.cc.

This example should output the following results:

Coordinate Uniform with Kernel: P2_PLR
Embedding type: Unilevel
Weights: ProductWeights([], default=0.7)
Norm type: 2
# mean: 6.16774766e+00
prob    quantile
0.000   5.81887701e+00
0.050   5.89738657e+00
0.100   5.92831303e+00
0.150   5.94717674e+00
0.200   5.96752109e+00
0.250   5.98872143e+00
0.300   6.00881990e+00
0.350   6.02547298e+00
0.400   6.05052482e+00
0.450   6.07692036e+00
0.500   6.10098986e+00
0.550   6.12755673e+00
0.600   6.15089129e+00
0.650   6.18134374e+00
0.700   6.21538113e+00
0.750   6.25750003e+00
0.800   6.31277026e+00
0.850   6.39424244e+00
0.900   6.51032358e+00
0.950   6.72322679e+00
1.000   7.39756149e+00