The Parser namespace contains the tools to make calls to Lattice Builder using text arguments similar to those of the command-line tool (see Command-Line Tutorial).
The Parser::Search class provides a parse()
method that returns a pointer to a Task::Search instance. The arguments to parse()
are all text of the same format as the command-line arguments (in the following order) to:
–construction
–lattice-type
–size
–dimension
–figure-of-merit
–weights
–filters
–multilevel-filters
–combiner
Constructing and Using Ordinary Lattice Rules
The following piece of code calls Lattice Builder to perform a fast CBC construction of an ordinary lattice rule with \(n=2^8\) points in dimension 10 using the coordinate-symmetric implementation (required by fast CBC) of the \(\mathcal P_2\) criterion, with product weights with \(\gamma_j=0.1\) for all \(j\), using no filters:
LatticePoints search()
{
cmd.construction = "fast-CBC";
cmd.size = "2^8";
cmd.dimension = "10";
cmd.figure = "CS:sum:P2";
cmd.weights = std::vector<std::string>{"product:0.1"};
auto search = cmd.parse();
std::cout << *search << std::endl;
search->execute();
std::cout << "BEST LATTICE: " << search->bestLattice() << std::endl;
std::cout << "MERIT: " << search->bestMeritValue() << std::endl;
const auto& lat = search->bestLattice();
return LatticePoints(lat.sizeParam().numPoints(), lat.gen());
}
The combiner
argument is set to a valid value, but it is not used. The resulting lattice definition can be retrieved with search->bestLattice()
. Our function returns an instance of the virtual container LatticePoints
, defined in tutorial/LatticePoints.h as:
#ifndef LATTICE_POINTS_H
#define LATTICE_POINTS_H
class LatticePoints {
public:
typedef std::vector<double> value_type;
typedef size_t size_type;
LatticePoints(size_type numPoints, std::vector<unsigned long> gen):
m_numPoints(numPoints),
m_intGen(std::move(gen)),
m_gen(m_intGen.size())
{ updateGen(); }
size_type numPoints() const { return m_numPoints; }
size_type size() const { return m_numPoints; }
size_type dimension() const { return m_gen.size(); }
value_type operator[](size_type i) const
{
std::vector<double> point(dimension());
for (size_type j = 0; j < point.size(); j++) {
double x = i * m_gen[j];
point[j] = x - int(x);
}
return point;
}
private:
size_type m_numPoints;
std::vector<unsigned long> m_intGen;
std::vector<double> m_gen;
void updateGen()
{
for (size_type j = 0; j < m_gen.size(); j++)
m_gen[j] = double(m_intGen[j]) / m_numPoints;
}
};
#endif
which can be used to enumerate the lattice points. The following piece of code shows how it could be used by simulation software.
void simulate(const LatticePoints& lat)
{
for (size_t i = 0; i < lat.size(); i++)
std::cout << "point " << i << ":\t" << lat[i] << std::endl;
}
In this example, we just print the points to standard output; in practice we would use them to integrate multidimensional functions. The complete example can be found in tutorial/ParserFastCBC.cc.
Constructing and Using Embedded Lattice Rules
To construct embedded lattices, we change the lattice type to embedded and the combiner to sum:
cmd.construction = "fast-CBC";
cmd.size = "2^8";
cmd.dimension = "10";
cmd.figure = "CS:sum:P2";
cmd.weights = std::vector<std::string>{"product:0.1"};
cmd.multilevelFilters = std::vector<std::string>{"norm:P2-SL10", "low-pass:1.0"};
cmd.combiner = "sum";
auto search = cmd.parse();
We also add normalization and low-pass filters:
cmd.multilevelFilters = std::vector<std::string>{"norm:P2-SL10", "low-pass:1.0"};
And, our search()
functions now returns an instance of EmbeddedLatticePoints
instead of LatticePoints:
const auto& lat = search->bestLattice();
return EmbeddedLatticePoints(lat.sizeParam().base(), lat.sizeParam().maxLevel(), lat.gen());
The virtual container EmbeddedLatticePoints
is defined in tutorial/EmbeddedLatticePoints.h as:
#ifndef EMBEDDED_LATTICE_POINTS_H
#define EMBEDDED_LATTICE_POINTS_H
class EmbeddedLatticePoints {
public:
typedef std::vector<double> value_type;
typedef size_t size_type;
EmbeddedLatticePoints(size_type base, size_type maxLevel, std::vector<unsigned long> gen):
m_base(base),
m_maxLevel(maxLevel),
m_intGen(std::move(gen)),
m_gen(m_intGen.size())
{ reset(); }
void reset() { m_level = 0; m_numPoints = 1; updateGen(); }
void extend() { m_level++; m_numPoints *= m_base; updateGen(); }
size_type base() const { return m_base; }
size_type maxLevel() const { return m_maxLevel; }
size_type level() const { return m_level; }
size_type numPoints() const { return m_numPoints; }
size_type size() const { return numPoints() <= 1 ? numPoints() : (base() - 1) * numPoints() / base(); }
size_type dimension() const { return m_gen.size(); }
value_type operator[](size_type i) const
{
std::vector<double> point(dimension());
for (size_type j = 0; j < point.size(); j++) {
double x = map(i) * m_gen[j];
point[j] = x - int(x);
}
return point;
}
private:
size_type m_base;
size_type m_maxLevel;
std::vector<unsigned long> m_intGen;
std::vector<double> m_gen;
size_type m_numPoints;
size_type m_level;
size_type map(size_type i) const { return numPoints() <= 1 ? i : (base() + 1) * (i + 1) / base(); }
void updateGen()
{
for (size_type j = 0; j < m_gen.size(); j++)
m_gen[j] = double(m_intGen[j]) / m_numPoints;
}
};
#endif
Finally, we modify our simulate()
function to use the points level by level:
void simulate(EmbeddedLatticePoints lat)
{
while (lat.level() <= lat.maxLevel()) {
std::cout << "==> level " << lat.level() << std::endl;
for (size_t i = 0; i < lat.size(); i++)
std::cout << "point " << i << ":\t" << lat[i] << std::endl;
lat.extend();
}
}
The complete example can be found in tutorial/ParserFastCBCEmbedded.cc.
- See Also
- Parser Task