gpp_domain

Contents:

gpp_domain.hpp

This file contains “DomainType” classes that specify different kinds of domains (e.g., TensorProduct, Simplex). These are currently used to describe domain limits for optimizers (defined in gpp_optimization, used by gpp_math, gpp_model_selection).

Currently, we only support domains with planar (linear) boundaries.

Each domain provides functions to describe the set of boundary planes, check whether a point is inside/outside, generate random points inside, and limit updates (from optimizers) so that a path stays inside the domain.

See gpp_geometry.hpp for how to specify a plane.

namespace optimal_learning

Macro to allow restrict as a keyword for C++ compilation and CUDA/nvcc compilation. See related entry in gpp_common.hpp for more details.

Enums

DomainTypes enum

Enumerating domains for convenience. Useful for selecting which tests to run and also used by the Python interface to communicate domain type to C++.

Values:

class DummyDomain

A dummy domain; commonly paired with the NullOptimizer. Use when domain is irrelevant.

It does not track any member data and claims all points are inside.

Public Functions

bool CheckPointInside(double const *restrict OL_UNUSED)

Always returns true: DummyDomain contains all points.

Parameters:
point[dim]:point to check
Returns:
true if point is inside the domain or on its boundary, false otherwise

Public Static Attributes

constexpr char const * kName

string name of this domain for logging

class RepeatedDomain

A generic domain type for simultaneously manipulating num_repeats points in a “regular” domain (the kernel).

Note

Comments in this class are copied to RepeatedDomain in optimal_learning/python/repated_domain.py.

Note

the kernel domain is not copied. Instead, the kernel functions are called num_repeats times in a loop. In some cases, data reordering is also necessary to preserve the output properties (e.g., uniform distribution).

For some use cases (e.g., q,p-EI optimization with q > 1), we need to simultaneously manipulate several points within the same domain. To support this use case, we have the RepeatedDomain, a light-weight wrapper around any DomainType object that kernalizes that object’s functionality.

In general, kernel domain operations need be performed num_repeats times, once for each point. This class hides the looping logic so that use cases like various Optimizer implementations (gpp_optimization.hpp) do not need to be explicitly aware of whether they are optimizing 1 point or 50 points. Instead, an optimizable Evaluator/State pair provides GetProblemSize() and appropriately sized gradient information. Coupled with RepeatedDomain, Optimizers can remain oblivious.

In simpler terms, say we want to solve 5,0-EI in a parameter-space of dimension 3. So we would have 5 points moving around in a 3D space. The 3D space, whatever it is, is the kernel domain. We “repeat” the kernel 5 times; in practice this mostly amounts to simple loops around kernel functions and sometimes data reordering is also needed.

Note

this operation is more complex than just working in a higher dimensional space. 3 points in a 2D simplex is not the same as 1 point in a 6D simplex; e.g., [(0.5, 0.5), (0.5, 0.5), (0.5, 0.5)] is valid in the first scenario but not in the second.

Where the member domain takes kernel_input, this class’s members take an array with of num_repeats data with the same size as kernel_input, ordered sequentially. So if we have kernel_input[dim][num_points], we now have repeated_input[dim][num_points][num_repeats]. The same is true for outputs.

For example, CheckPointInside() calls the kernel domain’s CheckPointInside() function num_repeats times, returning True only if all num_repeats input points are inside the kernel domain.

Public Type

typedef DomainType_ DomainType

Public Functions

RepeatedDomain()

RepeatedDomain(const DomainType & domain, int num_repeats_in)

Construct a RepeatedDomain object, which kernalizes and repeats an input DomainType object.

Note

this class maintains a pointer to the input domain. Do not let the domain object go out of scope before this object goes out of scope.

Parameters:
domain:the domain to repeat
num_repeats:number of times to repeat the input domain

int dim()

int num_repeats()

bool CheckPointInside(double const *restrict point)

Check if a point is inside the domain/on its domain or outside

Parameters:
point[dim][num_repeats]:
 point to check
Returns:
true if point is inside the domain or on its boundary, false otherwise

bool GeneratePointInDomain(UniformRandomGenerator * uniform_generator, double *restrict random_point)

Generates “point” such that CheckPointInside(point) returns true.

May use rejection sampling so point generation may fail.

Parameters:
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_point[dim][num_repeats]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_point[dim][num_repeats]:
 point with coordinates inside the domain (left in invalid state if fcn returns false)
Returns:
true if point generation succeeded

int GenerateUniformPointsInDomain(int num_points, UniformRandomGenerator * uniform_generator, double *restrict random_points)

Generates AT MOST num_points points in the domain (i.e., such that CheckPointInside(point) returns true). The points will be uniformly distributed.

May use rejection sampling so we are not guaranteed to generate num_points samples.

Parameters:
num_points:number of random points to generate
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_points[dim][num_repeats][num_points]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_points[dim][num_repeats][num_points]:
 point with coordinates inside the domain
Returns:
number of points actually generated

void LimitUpdate(double max_relative_change, double const *restrict current_point, double *restrict update_vector)

Changes update_vector so that:

point_new = point + update_vector

has coordinates such that CheckPointInside(point_new) returns true.

update_vector is UNMODIFIED if point_new is already inside the domain.

Note

we modify update_vector (instead of returning point_new) so that further update limiting/testing may be performed.

Parameters:
max_relative_change:
 max change allowed per update (as a relative fraction of current distance to boundary)
current_point[dim][num_repeats]:
 starting point
update_vector[dim][num_repeats]:
 proposed update
Outputs:
update_vector[dim][num_repeats]:
 modified update so that the final point remains inside the domain

Private Members

int num_repeats_

number of times to repeat the input domain

const DomainType *restrict domain_

pointer to the domain to repeat

class SimplexIntersectTensorProductDomain

Domain class for the intersection of the unit simplex with an arbitrary tensor product domain. To that end, this object has a TensorProductDomain object as a data member and uses its functions when possible.

See TensorProductDomain for what that means. The unit d-simplex is defined as the set of x_i such that:

  1. x_i >= 0 \forall i  (i ranging over dimension)
  2. \sum_i x_i <= 1

(Implying that x_i <= 1 \forall i)

ASSUMPTION: most of the volume of the tensor product region lies inside the simplex region.

Public Functions

SimplexIntersectTensorProductDomain()

SimplexIntersectTensorProductDomain(ClosedInterval const *restrict domain, int dim_in)

Constructs a SimplexIntersectTensorProductDomain. The bounds of the tensor product region are specified through the “domain” input, just as with TensorProductDomain.

Parameters:
domain[dim]:array of ClosedInterval specifying the boundaries of a dim-dimensional tensor-product domain.
dim_in:number of spatial dimensions

int dim()

int GetMaxNumberOfBoundaryPlanes()

Maximum number of planes that define the boundary of this domain. Used for testing.

This result is NOT exact.

Returns:
max number of planes defining the boundary of this domain

void GetBoundaryPlanes(Plane *restrict planes)

Fills an input array with all bounding planes of this domain. See struct Plane in gpp_geometry.hpp for how to specify a plane. Used for testing.

Let max_num_bound = GetMaxNumberOfBoundaryPlanes()

Parameters:
planes[max_num_bound]:
 properly allocated space: max_num_bound Plane objects in dim spatial dimensions
Outputs:
planes[max_num_bound]:
 array of planes of this domain

bool CheckPointInside(double const *restrict point)

Check if a point is inside the domain/on its domain or outside

Parameters:
point[dim]:point to check
Returns:
true if point is inside the domain or on its boundary, false otherwise

bool GeneratePointInDomain(UniformRandomGenerator * uniform_generator, double *restrict random_point)

Generates “point” such that CheckPointInside(point) returns true.

Uses rejection sampling so point generation may fail.

Parameters:
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_point[dim]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_point[dim]:
 point with coordinates inside the domain (left in invalid state if fcn returns false)
Returns:
true if point generation succeeded

int GenerateUniformPointsInDomain(int num_points, UniformRandomGenerator * uniform_generator, double *restrict random_points)

Generates AT MOST num_points points in the domain (i.e., such that CheckPointInside(point) returns true). The points will be uniformly distributed.

Uses rejection sampling so we are not guaranteed to generate num_points samples.

Parameters:
num_points:number of random points to generate
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_points[dim][num_points]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_points[dim][num_points]:
 point with coordinates inside the domain
Returns:
number of points actually generated

void LimitUpdate(double max_relative_change, double const *restrict current_point, double *restrict update_vector)

Changes update_vector so that:

point_new = point + update_vector

has coordinates such that CheckPointInside(point_new) returns true.

update_vector is UNMODIFIED if point_new is already inside the domain.

Note

we modify update_vector (instead of returning point_new) so that further update limiting/testing may be performed.

Parameters:
max_relative_change:
 max change allowed per update (as a relative fraction of current distance to boundary)
current_point[dim]:
 starting point
update_vector[dim]:
 proposed update
Outputs:
update_vector[dim]:
 modified update so that the final point remains inside the domain

Public Static Attributes

constexpr char const * kName

string name of this domain for logging

Private Members

int dim_

the number of spatial dimensions of this domain

TensorProductDomain tensor_product_domain_

the tensor product domain to intersect with

Plane simplex_plane_

the plane defining the simplex

Private Static Attributes

constexpr double kPointGenerationRatio

GenerateUniformPointsInDomain() is happy if ratio*requested_points number of points is generated.

constexpr double kValidPointRatioFloor

in GenerateUniformPointsInDomain(), if the ratio of valid points is > this, we retry requesting 1/ratio points. otherwise we retry with 5x the points (i.e., flooring ratio at 5)

constexpr int kMaxPointRatioGrowth

1/kValidPointRatioFloor; the most we’ll increase the number of requested points on a retry

constexpr double kInvalidStepScaleFactor

attempt to scale down the step-size (or distance to wall) by this factor when a domain-exiting (i.e., invalid) step is requested

constexpr double kRelativeChangeEpsilonTweak

small tweak to relative_change (to prevent max_relative_change == 1.0 exactly; see LimitUpdate comments)

class TensorProductDomain

Domain type for a tensor product domain.

A d-dimensional tensor product domain is D = [x_0_{min}, x_0_{max}] X [x_1_{min}, x_1_{max}] X ... X [x_d_{min}, x_d_{max}]

Public Functions

TensorProductDomain()

TensorProductDomain(ClosedInterval const *restrict domain, int dim_in)

Constructs a TensorProductDomain.

Parameters:
domain[dim]:array of ClosedInterval specifying the boundaries of a dim-dimensional tensor-product domain.
dim_in:number of spatial dimensions

int dim()

void SetDomain(ClosedInterval const *restrict domain)

Explicitly set the domain boundaries. Assumes specified domain is non-empty.

Parameters:
domain[dim]:array of ClosedInterval specifying the boundaries of a dim-dimensional tensor-product domain.

int GetMaxNumberOfBoundaryPlanes()

Maximum number of planes that define the boundary of this domain. Used for testing.

This result is exact.

Returns:
max number of planes defining the boundary of this domain

void GetBoundaryPlanes(Plane *restrict planes)

Fills an input array with all bounding planes of this domain. See struct Plane in gpp_geometry.hpp for how to specify a plane. Used for testing.

Let max_num_bound = GetMaxNumberOfBoundaryPlanes()

Parameters:
planes[max_num_bound]:
 properly allocated space: max_num_bound Plane objects in dim spatial dimensions
Outputs:
planes[max_num_bound]:
 array of planes of this domain

bool CheckPointInside(double const *restrict point)

Check if a point is inside the domain/on its boundary or outside.

Parameters:
point[dim]:point to check
Returns:
true if point is inside the domain or on its boundary, false otherwise

bool GeneratePointInDomain(UniformRandomGenerator * uniform_generator, double *restrict random_point)

Generates “point” such that CheckPointInside(point) returns true.

Parameters:
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_point[dim]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_point[dim]:
 point with coordinates inside the domain (left in invalid state if fcn returns false)
Returns:
true if point generation succeeded

int GenerateUniformPointsInDomain(int num_points, UniformRandomGenerator * uniform_generator, double *restrict random_points)

Generates num_points points in the domain (i.e., such that CheckPointInside(point) returns true). The points will be uniformly distributed.

Parameters:
num_points:number of random points to generate
uniform_generator[1]:
 a UniformRandomGenerator object providing the random engine for uniform random numbers
random_points[dim][num_points]:
 properly sized array
Outputs:
uniform_generator[1]:
 UniformRandomGenerator object will have its state changed due to random draws
random_points[dim][num_points]:
 point with coordinates inside the domain
Returns:
number of points generated (always num_points; ok to not use this result)

void LimitUpdate(double max_relative_change, double const *restrict current_point, double *restrict update_vector)

Changes update_vector so that:

point_new = point + update_vector

has coordinates such that CheckPointInside(point_new) returns true.

update_vector is UNMODIFIED if point_new is already inside the domain.

Note

we modify update_vector (instead of returning point_new) so that further update limiting/testing may be performed.

Parameters:
max_relative_change:
 max change allowed per update (as a relative fraction of current distance to boundary)
current_point[dim]:
 starting point
update_vector[dim]:
 proposed update
Outputs:
update_vector[dim]:
 modified update so that the final point remains inside the domain

Public Static Attributes

constexpr char const * kName

string name of this domain for logging

Private Members

int dim_

the number of spatial dimensions of this domain

std::vector< ClosedInterval > domain_

the list of ClosedInterval that define the boundaries of this tensor product domain

Private Static Attributes

constexpr double kInvalidStepScaleFactor

attempt to scale down the step-size (or distance to wall) by this factor when a domain-exiting (i.e., invalid) step is requested

gpp_domain.cpp

This file contains definitions for constructors and member functions of the various domain classes in gpp_domain.hpp.

namespace optimal_learning

Macro to allow restrict as a keyword for C++ compilation and CUDA/nvcc compilation. See related entry in gpp_common.hpp for more details.