-
Notifications
You must be signed in to change notification settings - Fork 122
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
Changes from 21 commits
18582ee
386a253
a96f4eb
09c0109
ee6e631
671d414
6c4f676
cc3cf5f
8e4a377
37d6104
2949acb
b49256f
e7cea91
1e6471e
1b0cd55
364c9eb
11783b1
78c83d2
9d7a5d5
d6f0bc2
e3b892f
85963a5
200f019
3176dd2
91373bf
10cc6e8
977541f
92503ff
8385366
740279d
e26e424
e4e6da4
17f5b2f
5b35e7d
bb0b394
808a5f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
|
||
test/build | ||
examples/build | ||
.vscode | ||
test/Testing/Temporary/CTestCostData.txt | ||
*.log | ||
.Rproj.user | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
// VolEsti (volume computation and sampling library) | ||
|
||
// Copyright (c) 2012-2021 Vissarion Fisikopoulos | ||
// Copyright (c) 2018-2021 Apostolos Chalkis | ||
|
||
// Contributed and/or modified by Suraj Choubey, as part of Google Summer of Code 2021 program. | ||
|
||
// Licensed under GNU LGPL.3, see LICENCE file | ||
|
||
#ifndef SIMPLE_MC_INTEGRATION_HPP | ||
#define SIMPLE_MC_INTEGRATION_HPP | ||
|
||
#include <iostream> | ||
#include <fstream> | ||
#include <random> | ||
#include <vector> | ||
#include "convex_bodies/hpolytope.h" | ||
#include "Eigen/Eigen" | ||
#include "generators/known_polytope_generators.h" | ||
#include "boost_random_number_generator.hpp" | ||
#include "cartesian_geom/cartesian_kernel.h" | ||
#include "random_walks/random_walks.hpp" | ||
#include "volume/volume_sequence_of_balls.hpp" | ||
#include "volume/volume_cooling_gaussians.hpp" | ||
#include "volume/volume_cooling_balls.hpp" | ||
#include "misc.h" | ||
|
||
typedef double NT; | ||
typedef Cartesian<NT> Kernel; | ||
typedef typename Kernel::Point Point; | ||
typedef std::vector<Point> Points; | ||
typedef HPolytope<Point> HPOLYTOPE; | ||
typedef boost::mt19937 RNGType; | ||
typedef BoostRandomNumberGenerator<RNGType, NT> RandomNumberGenerator; | ||
typedef typename HPolytope<Point>::MT MT; | ||
typedef typename HPolytope<Point>::VT VT; | ||
|
||
typedef const unsigned int Uint; // positive constant value for no of samples & dimensions | ||
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){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is meant to check if UL[i] >= LL[i] There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
if( UL.dimension() == LL.dimension() ) { | ||
for ( int i = 0 ; i< LL.dimension() ; i++){ | ||
if( LL[i] > UL[i]){ | ||
std::cout << "Invalid integration limits\n"; | ||
return false; | ||
} | ||
} | ||
return true; | ||
}else{ | ||
std::cout << "Invalid integration limits\n"; | ||
return false; | ||
} | ||
} | ||
|
||
// Hyper-Rectangle volume calculator in n-dimensions | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
NT hyperRectVolume(Point LL, Point UL){ | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
NT product=1; | ||
if(validLimits(LL,UL)){ | ||
for(int i=0; i<LL.dimension(); ++i){ | ||
product = product * ( UL[i] - LL[i] ); | ||
} | ||
return product; | ||
} | ||
else return 0; | ||
} | ||
|
||
// To sample a point between two n-dimensional points using inbuilt random sampling | ||
// Point samplerBWLimits(Point LL, Point UL){ | ||
// Point sample_point(LL.dimension()); | ||
// for(int i=0; i<LL.dimension(); ++i){ | ||
// sample_point.set_coord(i , LL[i] + (NT)(rand()) / ((NT)(RAND_MAX/(UL[i] - LL[i]))) ); | ||
// } | ||
// return sample_point; | ||
// } | ||
|
||
// Simple MC Integration over Hyper-Rectangles | ||
template | ||
< | ||
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){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this function take a generic polytope as an argument? Moreover, please check the spacing in the code which is not consistent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well not actually
|
||
Uint dim=LL.dimension(); | ||
NT sum = 0; | ||
if(validLimits(LL,UL)){ | ||
|
||
// Creating an MT & VT for HPolytope(Hyper-Rectangle) for integration limits using LL & UL | ||
MT mt(dim*2,dim); | ||
VT vt(dim*2); | ||
for(int i=0 ; i<dim ; i++){ | ||
mt(i,i)=1; | ||
vt(i)=UL[i]; | ||
mt(dim+i,i)=-1; | ||
vt(dim+i)=LL[i]*-1; | ||
} | ||
|
||
// Initialization of H-Polytope and setting up params for random walks | ||
HPOLYTOPE P(dim,mt,vt); | ||
// P.print(); | ||
std::pair<Point, NT> inner_ball = P.ComputeInnerBall(); | ||
RandomNumberGenerator rng(1); | ||
Point x0 = inner_ball.first; | ||
typename WalkType::template Walk<HPOLYTOPE, RandomNumberGenerator> walk(P,x0,rng); | ||
|
||
for (int i = 0; i <=N; i++ ) { | ||
walk.apply(P,x0,walk_length,rng); | ||
sum = sum + Fx(x0); | ||
} | ||
NT volume = hyperRectVolume(LL,UL); | ||
std::cout << "Volume of the subspace: " << volume << std::endl; | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
std::cout << "Integral Value: " << volume * sum / N << "\n"; | ||
}else{ | ||
std::cout << "Invalid integration limits\n"; | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
|
||
// Simple MC Integration Over Polytopes | ||
const Point origin(0); | ||
template | ||
< | ||
typename WalkType=BallWalk, | ||
typename Polytope=HPOLYTOPE, | ||
typename RNG=RandomNumberGenerator, | ||
typename Functor | ||
> | ||
void simple_mc_polytope_integrate(Functor Fx,Polytope &P, Uint N, volType vT=SOB, int walk_length=1, NT e=0.1 ,Point Origin=origin){ | ||
|
||
Uint dim = P.dimension(); | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Check if origin is shifted | ||
if(Origin.dimension() == 0 ){ | ||
Origin.set_dimension(dim); | ||
Origin.set_to_origin(); | ||
} | ||
|
||
// Volume calculation for HPolytope | ||
vissarion marked this conversation as resolved.
Show resolved
Hide resolved
|
||
NT volume=0; | ||
|
||
switch(vT){ | ||
case CB: | ||
volume = volume_cooling_balls<BallWalk, RNG, Polytope>(P, e, walk_length).second; | ||
break; | ||
case CG: | ||
volume = volume_cooling_gaussians<GaussianBallWalk, RNG, Polytope>(P, e, walk_length); | ||
break; | ||
case SOB: | ||
volume = volume_sequence_of_balls<BallWalk, RNG, Polytope>(P, e, walk_length); | ||
break; | ||
default: | ||
std::cout << "Error in volume type: CB / SOB / CG" << std::endl; | ||
volume = 0; | ||
break; | ||
} | ||
|
||
// Volume of the Polytope | ||
std::cout << "Volume of the Polytope = " << volume << std::endl; | ||
|
||
// For implementing Uniform Walks | ||
RNG rng(1); | ||
std::pair<Point, NT> inner_ball = P.ComputeInnerBall(); | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Point x0 = inner_ball.first; | ||
typename WalkType::template Walk<Polytope,RNG> walk(P,x0,rng); | ||
|
||
// For storing sampled points | ||
Points points; | ||
NT sum=0; | ||
|
||
// Applying and walking through Uniform Walks + Storing Points in Vector<Point> | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (int i = 0; i < N; i++ ){ | ||
walk.apply(P,x0,walk_length,rng); | ||
sum+=Fx(x0+Origin); | ||
|
||
// points.push_back(x0+Origin); | ||
// (x0+Origin).print(); | ||
} | ||
|
||
// To print sampled points | ||
// for(auto i_th_point : points){ | ||
// i_th_point.print(); | ||
// } | ||
|
||
/* | ||
Core idea of Monte Carlo Integration algorithm used here : https://en.wikipedia.org/wiki/Monte_Carlo_integration#Overview | ||
*/ | ||
|
||
// Integration Value | ||
std::cout << "Integral Value over Polytope = " << volume * sum / N << std::endl; | ||
|
||
} | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#include "doctest.h" | ||
#include "simple_MC_integration.hpp" | ||
#include "Eigen/Eigen" | ||
#include <vector> | ||
#include "cartesian_geom/cartesian_kernel.h" | ||
#include "hpolytope.h" | ||
#include "known_polytope_generators.h" | ||
#include "ode_solvers/oracle_functors.hpp" | ||
#include "random_walks/random_walks.hpp" | ||
#include <iostream> | ||
#include <fstream> | ||
#include "misc.h" | ||
|
||
typedef double NT; | ||
typedef Cartesian<NT> Kernel; | ||
typedef typename Kernel::Point Point; | ||
typedef std::vector<Point> Points; | ||
typedef HPolytope<Point> HPOLYTOPE; | ||
typedef VPolytope<Point> VPOLYTOPE; | ||
typedef boost::mt19937 RNGType; | ||
typedef BoostRandomNumberGenerator<RNGType, NT> RandomNumberGenerator; | ||
|
||
NT exp_N_Dim(Point X){ | ||
return exp(-X.squared_length()) ; | ||
} | ||
|
||
void call_test_simple_mc_over_hyperrectangle(){ | ||
srand(time(0)); | ||
std::cout << "\nTESTS FOR SIMPLE MC INTEGRATION OVER HYPER-RECTANGLES USING UNIFORM WALKS\n"; | ||
|
||
std::vector<NT> ll{-1,-1}; | ||
std::vector<NT> ul{1,1}; | ||
Point LL(2,ll), UL(2,ul); | ||
simple_mc_integrate(exp_N_Dim,10000,LL,UL); | ||
|
||
std::vector<NT> ll1{0,0}; | ||
std::vector<NT> ul1{2,2}; | ||
Point LL1(2,ll1), UL1(2,ul1); | ||
simple_mc_integrate(exp_N_Dim,10000,LL1,UL1); | ||
|
||
|
||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void call_test_simple_mc_over_polytope(){ | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
std::cout << "\nTESTS FOR SIMPLE MC INTEGRATION OVER H-POLYTOPES USING UNIFORM SAMPLING\n"; | ||
|
||
// H-Polytope Integration Test:1 for 2D Polytope around the origin | ||
HPOLYTOPE HP = generate_cube<HPOLYTOPE>(2, false); | ||
simple_mc_polytope_integrate<BilliardWalk,HPOLYTOPE>(exp_N_Dim, HP, 10000, SOB, 10, 0.01); | ||
|
||
// H-Polytope Integration Test:2 for 2D Polytope shifted to (1,1) from origin | ||
std::vector<NT> origin{1,1}; | ||
Point newOrigin(2,origin); | ||
simple_mc_polytope_integrate<BilliardWalk,HPOLYTOPE>(exp_N_Dim, HP, 10000, SOB, 1, 0.01, newOrigin); | ||
|
||
// H-Polytope Integration Test:3 | ||
HPOLYTOPE HP1 = generate_cube<HPOLYTOPE>(4, false); | ||
simple_mc_polytope_integrate<BilliardWalk,HPOLYTOPE>(exp_N_Dim, HP1, 10000, SOB); | ||
|
||
// V-Polytope Integration Test:4 | ||
VPOLYTOPE VP = generate_cross<VPOLYTOPE>(2, true); | ||
surajchoubey marked this conversation as resolved.
Show resolved
Hide resolved
|
||
simple_mc_polytope_integrate<BilliardWalk,VPOLYTOPE>(exp_N_Dim, VP, 10000, CB); | ||
|
||
// Polytope Integration Test:3 Reading a HPolytope from ine file for 20 Dimensions | ||
// std::string fileName("cube10.ine"); | ||
// std::ifstream inp; | ||
// std::vector<std::vector<NT> > Pin; | ||
// inp.open(fileName, std::ifstream::in); | ||
// read_pointset(inp,Pin); | ||
// HPOLYTOPE HP2(Pin); | ||
// SimpleMCPolytopeIntegrate(exp_N_dim, HP2, 15000, SOB); | ||
// inp.close(); | ||
} | ||
|
||
TEST_CASE("simple_mc_integration_over_hyperrectangles") { | ||
call_test_simple_mc_over_hyperrectangle(); | ||
} | ||
|
||
TEST_CASE("simple_mc_integration_over_polytopes") { | ||
call_test_simple_mc_over_polytope(); | ||
} |
There was a problem hiding this comment.
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 OKThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
HPOLYTOPE
->Hpolytope