Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple MC Integrate Feature #163

Merged
merged 36 commits into from
Oct 3, 2021

Conversation

surajchoubey
Copy link
Contributor

@surajchoubey surajchoubey commented Jun 13, 2021

Simple MC Integrate is a new feature which is proposed to be added to GeomScale/volume_approximation
It involves include/integration/simple_MC_integration.hpp and for the tests tests/simple_mc_integration.cpp with 6 tests written for ( all for H-rrepresentations) :

  1. Cubes
  2. Rectangles
  3. Simplices
  4. Product Simplices
  5. Cross Polytopes
  6. Birkhoff Polytopes

Link to the blog post: https://surajchoubey.github.io/gsoc21/simple-mc-integration/

Link to the tests: https://github.com/surajchoubey/latte-integrale-checks

Testing has been done using Latte-Integrale Software.

References:
LL = Lower Limits
UL = Upper Limits
N = unsigned integer number of sample points

simple_MC_integration.hpp involves 5 functions :

template
< typename Point = Point, typename NT = NT >
bool valid_limits(Point LL, Point UL)

To check if given two Points represent proper integration limits LL(i) <= UL(i) ; 0<i<LL.dimension() and LL.dimension() should be equal to UL.dimension()

template
<  typename Point = Point, typename NT = NT >
Point init_limit(Limit L, Uint dim)

This function is designed for simple_mc_integrate() to tailor a hyper-rectangle using the assigned limits which is supposed to be the subspace for performing MC Algorithm.
3.

template
<  typename Point = Point, typename NT = NT >
void initiate_unit_limits(Point& LL, Point& UL, int dim)

This is function is designed to initiate unit limits from [-1,1]^n as default integration limits.

template 
<
    typename WalkType = BallWalk,
    typename Polytope = HPOLYTOPE,
    typename RNG = RandomNumberGenerator,
    typename NT = NT,
    typename Functor
>
NT simple_mc_polytope_integrate(Functor Fx, 
                                Polytope &P, 
                                Uint N = 10000, 
                                volumetype voltype = SOB, 
                                int walk_length = 1, 
                                NT e = 0.1, 
                                Point Origin = pt) 
  • This function is designed to hold convex bodies in general for integration limits.
  • Type of random walk can be entered manually by user ( default set to BallWalk )
  • Polytope(or a convex body) is to be supplied meant to be supplied as a parameter in the function .
  • Volume of subspace is calculated using volesti volume libraries.
template
<
    typename WalkType = BallWalk,
    typename RNG = RandomNumberGenerator,
    typename NT = NT,
    typename Functor
>
NT simple_mc_integrate (Functor Fx, 
                        Uint dim, 
                        Uint N = 10000, 
                        volumetype voltype = SOB, 
                        Limit LowLimit = lt, 
                        Limit UpLimit = lt, 
                        int walk_length = 10, 
                        NT e = 0.1) 
  • This function is designed to hold integration limits in general
  • A hyper-rectangle is tailored from the limits entered which is supposed to be subspace for performing MC Algorithm.

Copy link
Collaborator

@papachristoumarios papachristoumarios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your PR!

I want to highlight some issues that need to be addressed before merging it, which I believe would need a considerable amount of work:

  1. Coding style: I have noticed that the coding style is inconsistent across all files (e.g. whitespaces, clauses, names of identifiers etc.), and even within functions. I suggest you look at the current code style and format your code accordingly.
  2. Lack of tests: The current code that is in the test directory contains no tests. By tests I mean taking the output of two different methods (e.g. naive method and LattE's method and comparing them). Also, you should do tests that check the values of known integrals over simple domains.
  3. Redundant code: There is redundant code across this PR. Please have a better look at the codebase and more specifically include/ode_solvers/oracle_functors.cpp. Also, the same function is defined multiply with no apparent reason.
  4. Suppose that you are given a distribution p(x) = f(x) / Z where Z is the integral of f(x) over the domain K (i.e. the normalization constant of p(x)), and a function g(x) defined on K. Then given samples X_1, ..., X_n ~ p and their transformations Y_i = g(X_i) their average, i.e. sum(Y_1, ..., Y_n) / n should converge to (1 / Z) * integral_K f(x) g(x) dx = integral_K p(x) g(x) dx where in general Z does not equal vol(K). When p is the uniform distribution over K then Z = vol(K) and f(x) = 1, so the average converges to (1 / vol(K)) * integral_K g(x) dx. That said, I believe that #L175 in simple_MC_integration.hpp calculates the wrong quantity.

Please make the appropriate changes and let us know when to re-review.

Thank you in advance

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
// To return ||X||^2 for a VT
NT normSquared(VT& X){
NT sum=0;
for( int i=0; i < X.rows() ; i++ ){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid writing in loops things that can be vectorized.

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
VT newOrigin(4);
newOrigin << 0.2, -0.7, 0.96, -0.79;
HPOLYTOPE HP1 = generate_cube<HPOLYTOPE>(4, false);
SimpleMCPolytopeIntegrate(expXY4D, HP1, 15000, SOB , newOrigin);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to add CHECK() here?

Copy link
Member

@vissarion vissarion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @surajchoubey for this PR! In general it is in good shape, I have some comments regarding the interface to inline with the interfaces of similar functions (e.g. volume). Also the code styling needs some polishing.

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Show resolved Hide resolved
include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@papachristoumarios papachristoumarios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR! In general, the PR has been improved a lot since the last iteration.
I have left some comments to address and I would like to highlight that you should be more careful with the code structure between header and source files. I have left you some advice regarding how to address them.

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
enum volType { CB , CG , SOB }; // Volume type for polytope

// To check if two n-dimensional points ensure valid limits in integration
bool validLimits(Point LL, Point UL){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this method throw an exception instead of giving an output to stdout?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is meant to check if UL[i] >= LL[i]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! What I meant was that these errors should be printed on stderr, which you do below.

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
typename WalkType=BallWalk,
typename Functor
>
void simple_mc_integrate(Functor Fx, Uint N ,Point LL, Point UL, int walk_length=10, NT e=0.1){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this function take a generic polytope as an argument?
You can create an extra function which is more user-friendly: ie it takes Point LL and Point UL and then calls this function.

Moreover, please check the spacing in the code which is not consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well not actually simple_mc_integrate() is designed to take integration limits as Points. (This is come up with thought to ease the user)

simple_mc_polytope_integrate() is designed to take generic polytope as argument.

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
test/simple_mc_integration.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@papachristoumarios papachristoumarios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work!

include/integration/simple_MC_integration.hpp Outdated Show resolved Hide resolved
}

template <typename NT>
void call_test_simple_mc_integration_over_rectangles() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this contains integration over segments too, so this could be included in the name

test/simple_mc_integration.cpp Show resolved Hide resolved
typedef Cartesian<NT> Kernel;
typedef typename Kernel::Point Point;
typedef std::vector<Point> Points;
typedef HPolytope<Point> HPOLYTOPE;
Copy link
Member

@vissarion vissarion Jul 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not a special type so calling it Hpolytope instead of capitilize, is OK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed HPOLYTOPE -> Hpolytope


switch (voltype) {
case CB:
volume = volume_cooling_balls <BallWalk, RNG, Polytope> (P, e, walk_length).second;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the walk parameter here should be part of the interface i.e. a new template e.g. VolumeWalkType that should be passed here instead of BallWalk

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOB/CG are fine to good to go on this.
What to do the CG Walktype? Cooling Gaussians seem to use GaussianFamily Walks only.


Limit LL1{0.5};
Limit UL1{10};
integration_value = simple_mc_integrate <BilliardWalk> (logx_natural_1D, 1, 100000, CB, LL1, UL1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100K is too much I think, tests are slow, do you get good enough (for tests) results with 1K ?

Copy link
Contributor Author

@surajchoubey surajchoubey Aug 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I am doing 1K mostly everywhere and 10K where dimensions are greater than 7.
  • I checked the results and I could see satisfiable relative errors.
  • Used 100K once only because I created some weird 1D Polytope sampling space

@vissarion vissarion merged commit 3a7d072 into GeomScale:develop Oct 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants