Skip to content

Commit

Permalink
Implemented variance and bias vector as user-defined parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
guillexm committed Jul 31, 2023
1 parent 40ab1f9 commit 8bb2388
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
23 changes: 16 additions & 7 deletions dingo/PolytopeSampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def generate_steady_states(
return steady_states

def generate_steady_states_no_multiphase(
self, method = 'billiard_walk', n=1000, burn_in=0, thinning=1
self, method = 'billiard_walk', n=1000, burn_in=0, thinning=1, variance=1.0, bias_vector=None
):
"""A member function to sample steady states.
Expand All @@ -197,12 +197,17 @@ def generate_steady_states_no_multiphase(
burn_in -- the number of points to burn before sampling
thinning -- the walk length of the chain
"""

self.get_polytope()

P = HPolytope(self._A, self._b)

if bias_vector is None:
bias_vector = np.ones(self._A.shape[1], dtype=np.float64)
else:
bias_vector = bias_vector.astype('float64')

samples = P.generate_samples(method, n, burn_in, thinning, self._parameters["fast_computations"])
samples = P.generate_samples(method, n, burn_in, thinning, self._parameters["fast_computations"], variance, bias_vector)
samples_T = samples.T

steady_states = map_samples_to_steady_states(
Expand Down Expand Up @@ -243,7 +248,7 @@ def sample_from_polytope(

@staticmethod
def sample_from_polytope_no_multiphase(
A, b, method = 'billiard_walk', n=1000, burn_in=0, thinning=1
A, b, method = 'billiard_walk', n=1000, burn_in=0, thinning=1, variance=1.0, bias_vector=None
):
"""A static function to sample from a full dimensional polytope with an MCMC method.
Expand All @@ -255,14 +260,18 @@ def sample_from_polytope_no_multiphase(
burn_in -- the number of points to burn before sampling
thinning -- the walk length of the chain
"""

if bias_vector is None:
bias_vector = np.ones(A.shape[1], dtype=np.float64)
else:
bias_vector = bias_vector.astype('float64')

P = HPolytope(A, b)

try:
import gurobipy
samples = P.generate_samples(method, n, burn_in, thinning, True)
samples = P.generate_samples(method, n, burn_in, thinning, True, variance, bias_vector)
except ImportError as e:
samples = P.generate_samples(method, n, burn_in, thinning, False)
samples = P.generate_samples(method, n, burn_in, thinning, False, variance, bias_vector)

samples_T = samples.T
return samples_T
Expand Down
43 changes: 28 additions & 15 deletions dingo/bindings/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ double HPolytopeCPP::apply_sampling(int walk_len,
int method,
double* inner_point,
double radius,
double* samples) {
double* samples,
double variance_value,
double* bias_vector){

RNGType rng(HP.dimension());
HP.normalize();
int d = HP.dimension();
Expand All @@ -103,7 +106,8 @@ double HPolytopeCPP::apply_sampling(int walk_len,
HP.set_InnerBall(CheBall);
starting_point = inner_point2;
std::list<Point> rand_points;
NT variance = 1.0;

NT variance = variance_value;

if (method == 1) { // cdhr
uniform_sampling<CDHRWalk>(rand_points, HP, rng, walk_len, number_of_points,
Expand All @@ -118,27 +122,36 @@ double HPolytopeCPP::apply_sampling(int walk_len,
} else if (method == 4) { // ball walk
uniform_sampling<BallWalk>(rand_points, HP, rng, walk_len, number_of_points,
starting_point, number_of_points_to_burn);
} else if (method == 5) { // dikin walk {
} else if (method == 5) { // dikin walk
uniform_sampling<DikinWalk>(rand_points, HP, rng, walk_len, number_of_points,
starting_point, number_of_points_to_burn);
} else if (method == 6) { // john walk {
} else if (method == 6) { // john walk
uniform_sampling<JohnWalk>(rand_points, HP, rng, walk_len, number_of_points,
starting_point, number_of_points_to_burn);
} else if (method == 7) { // vaidya walk {
} else if (method == 7) { // vaidya walk
uniform_sampling<VaidyaWalk>(rand_points, HP, rng, walk_len, number_of_points,
starting_point, number_of_points_to_burn);
}
else if (method == 8) { // gaussian sampling with gaussian HMC exact walk {
NT a = NT(1)/(NT(2)*variance);
gaussian_sampling<GaussianHamiltonianMonteCarloExactWalk>(rand_points, HP, rng, walk_len, number_of_points, a,
} else if (method == 8) { // gaussian sampling with gaussian HMC exact walk
NT a = NT(1)/(NT(2)*variance);
gaussian_sampling<GaussianHamiltonianMonteCarloExactWalk>(rand_points, HP, rng, walk_len, number_of_points, a,
starting_point, number_of_points_to_burn);
}
else if (method == 9) { // exponential sampling with exponential HMC exact walk {
Point c(d);
c = GetDirection<Point>::apply(d, rng, false);
exponential_sampling<ExponentialHamiltonianMonteCarloExactWalk>(rand_points, HP, rng, walk_len, number_of_points, c, variance,
} else if (method == 9) { // exponential sampling with exponential HMC exact walk

//----------------------------
Point bias_vector_final;
VT c(d);

for (int i = 0; i < d; i++){
c(i) = bias_vector[i];
}
Point bias_vector2(c);

bias_vector_final = bias_vector2;
//----------------------------

exponential_sampling<ExponentialHamiltonianMonteCarloExactWalk>(rand_points, HP, rng, walk_len, number_of_points, bias_vector_final, variance,
starting_point, number_of_points_to_burn);
}
}

else {
throw std::runtime_error("This function must not be called.");
Expand Down
2 changes: 1 addition & 1 deletion dingo/bindings/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class HPolytopeCPP{

// the apply_sampling() function
double apply_sampling(int walk_len, int number_of_points, int number_of_points_to_burn,
int method, double* inner_point, double radius, double* samples);
int method, double* inner_point, double radius, double* samples, double variance_value, double* bias_vector);

void mmcs_initialize(int d, int ess, bool psrf_check, bool parallelism, int num_threads);

Expand Down
8 changes: 5 additions & 3 deletions dingo/volestipy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ cdef extern from "bindings.h":

# Random sampling
double apply_sampling(int walk_len, int number_of_points, int number_of_points_to_burn, \
int method, double* inner_point, double radius, double* samples)
int method, double* inner_point, double radius, double* samples, double variance_value, double* bias_vector)

# Initialize the parameters for the (m)ultiphase (m)onte (c)arlo (s)ampling algorithm
void mmcs_initialize(unsigned int d, int ess, int psrf_check, int parallelism, int num_threads);
Expand Down Expand Up @@ -122,7 +122,7 @@ cdef class HPolytope:
raise Exception('"{}" is not implemented to compute volume. Available methods are: {}'.format(vol_method, volume_methods))

# Likewise, the generate_samples() function
def generate_samples(self, method, number_of_points, number_of_points_to_burn, walk_len, fast_mode):
def generate_samples(self, method, number_of_points, number_of_points_to_burn, walk_len, fast_mode, variance_value, bias_vector):

n_variables = self._A.shape[1]
cdef double[:,::1] samples = np.zeros((number_of_points, n_variables), dtype = np.float64, order = "C")
Expand All @@ -135,6 +135,8 @@ cdef class HPolytope:

cdef double[::1] inner_point_for_c = np.asarray(temp_center)

cdef double[::1] bias_vector_ = np.asarray(bias_vector)

if method == 'cdhr':
int_method = 1
elif method == 'rdhr':
Expand All @@ -157,7 +159,7 @@ cdef class HPolytope:
raise RuntimeError("Uknown MCMC sampling method")

self.polytope_cpp.apply_sampling(walk_len, number_of_points, number_of_points_to_burn, \
int_method, &inner_point_for_c[0], radius, &samples[0,0])
int_method, &inner_point_for_c[0], radius, &samples[0,0], variance_value, &bias_vector_[0])
return np.asarray(samples)


Expand Down

0 comments on commit 8bb2388

Please sign in to comment.