Skip to content

Commit

Permalink
[MORRIS] fix #367 sampling issues out of bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
chapuisk committed Nov 1, 2024
1 parent b6175ee commit 8e1e5ad
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ public void setChildren(final Iterable<? extends ISymbol> children) {}

/** ######################### EVALUATE MORRIS INDEXES ######################### */

@SuppressWarnings ("unchecked")
@Override
public void explore(final IScope scope) {
this.sample = Cast.asInt(scope, getFacet(Exploration.SAMPLE_SIZE).value(scope));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ public static List<Object> makeMorrisSampling(final int nb_levels, final int nb_
if (nb_levels % 2 != 0) throw GamaRuntimeException.error("The number of value should be even", scope);
int nb_attributes = parameters.size();

List<Trajectory> trajectories = new ArrayList<>();
trajectories = morrisTrajectories(nb_attributes, nb_levels, nb_sample, scope.getRandom().getGenerator(), trajectories);


List<Trajectory> trajectories =
morrisTrajectories(nb_attributes, nb_levels, nb_sample, scope.getRandom().getGenerator());
List<String> nameInputs = new ArrayList<>();
for (int i = 0; i < parameters.size(); i++) { nameInputs.add(parameters.get(i).getName()); }
List<Map<String, Double>> MorrisSamples = new ArrayList<>();
Expand Down Expand Up @@ -104,8 +103,8 @@ public static List<ParametersSet> makeMorrisSamplingOnly(final int nb_levels, fi
final List<Batch> parameters, final IScope scope) {
if (nb_levels % 2 != 0) throw GamaRuntimeException.error("The number of value should be even", scope);
int nb_attributes = parameters.size();
List<Trajectory> trajectories =
morrisTrajectories(nb_attributes, nb_levels, nb_sample, scope.getRandom().getGenerator());
List<Trajectory> trajectories = new ArrayList<>();
trajectories = morrisTrajectories(nb_attributes, nb_levels, nb_sample, scope.getRandom().getGenerator(), trajectories);
List<String> nameInputs = new ArrayList<>();
for (int i = 0; i < parameters.size(); i++) { nameInputs.add(parameters.get(i).getName()); }
List<Map<String, Double>> MorrisSamples = new ArrayList<>();
Expand All @@ -119,6 +118,18 @@ public static List<ParametersSet> makeMorrisSamplingOnly(final int nb_levels, fi
return buildParametersSetfromSample(scope, parameters, MorrisSamples);
}

/**
* Recursively generates r independent trajectories for k variables sampled with p levels.
*
* No specific strategy is used to sample trajectories - uniformely random
*/
private static List<Trajectory> morrisTrajectories(final int k, final int p, final int r, final Random rng, final List<Trajectory> acc) {
if (r == 0) return acc;
acc.add(generateTraj(k, p, rng));
return morrisTrajectories(k, p, r - 1, rng, acc);
}


/*
* Create one random trajectory following classical random strategy:
*
Expand Down Expand Up @@ -223,109 +234,5 @@ private static RealMatrix shuffleRow(RealMatrix m) {
}
return m;
}

//////////////////////////
//////////////////////////
/* OLD DIRTY TOM THINGS */

/**
* For a given number of parameters k, a number of levels p, generation an initial seed for this parameters
*/
private static List<Double> seed(final int k, final int p, final Random rng) {
List<Double> seed = new ArrayList<>();
double delta = 1 / (2 * ((double) p - 1));
IntStream.range(0, k).forEach(i -> seed.add((rng.nextInt(p * 2 - 2) + 1) * delta));
return seed;
}

/**
* Build a trajectory (2nd function)
*/
private static List<Object> trajectoryBuilder(final double delta, final List<Integer> order, final List<Integer> direction,
final List<Double> seed, final List<List<Double>> accPoints, final List<Double> accdelta, final int index) {
if (order.isEmpty()) {
List<Object> trajectory = new ArrayList<>();
trajectory.add(accPoints);
trajectory.add(accdelta);
return trajectory;
}
int idx = order.get(0);
double deltaOriented = delta * direction.get(0);
double valTemp = seed.get(idx) + deltaOriented;
List<Double> new_seed = new ArrayList<>(seed);
new_seed.set(idx, valTemp);
order.remove(0);
direction.remove(0);
accPoints.add(new_seed);
accdelta.add(deltaOriented);
return trajectoryBuilder(delta, order, direction, new_seed, accPoints, accdelta, index + 1);
}

/**
* Build a trajectory (1st function)
*/
private static List<Object> trajectoryBuilder(final double delta, final List<Integer> order, final List<Integer> direction,
final List<Double> seed) {
List<List<Double>> accPoints = new ArrayList<>();
List<Double> accDelta = new ArrayList<>();
if (order.isEmpty()) {
// This is probably never used
List<Object> trajectory = new ArrayList<>();
trajectory.add(accPoints);
trajectory.add(accDelta);
return trajectory;
}
int idx = order.get(0);
double deltaOriented = delta * direction.get(0);
double valTemp = seed.get(idx) + deltaOriented;
List<Double> new_seed = new ArrayList<>(seed);
new_seed.set(idx, valTemp);
order.remove(0);
direction.remove(0);
accPoints.add(new_seed);
accDelta.add(deltaOriented);
return trajectoryBuilder(delta, order, direction, new_seed, accPoints, accDelta, 1);

}

/**
* Create data for making trajectory k: Number of variable p: Number of levels (Should be even) return: new
* Trajectory composed of several points to visit
*/
@SuppressWarnings("unchecked")
private static Trajectory makeTrajectory(final int k, final int p, final Random rng) {
double delta = 1 / (2 * ((double) p - 1));
List<Double> seed = seed(k, p, rng);
List<Integer> orderVariables = new ArrayList<>();
IntStream.range(0, k).forEach(orderVariables::add);
Collections.shuffle(orderVariables);
List<Integer> directionVariables = new ArrayList<>();
IntStream.range(0, k).forEach(s -> directionVariables.add(rng.nextInt(2) * 2 - 1));
List<Object> List_p_d = trajectoryBuilder(delta, orderVariables, directionVariables, seed);
List<List<Double>> points = (List<List<Double>>) List_p_d.get(0);
return new Trajectory(points);
}

/**
* Recursive function that add trajectories
*/
private static List<Trajectory> addTrajectories(final int k, final int p, final int r, final Random rng,
final List<Trajectory> acc) {
if (r == 0) return acc;
acc.add(makeTrajectory(k, p, rng));
return addTrajectories(k, p, r - 1, rng, acc);
}

/**
* Generates r independent trajectories for k variables sampled with p levels.
*/
private static List<Trajectory> morrisTrajectories(final int k, final int p, final int r, final Random rng) {
List<Trajectory> acc = new ArrayList<>();
if (r == 0)
// Probably never used
return acc;
acc.add(makeTrajectory(k, p, rng));
return addTrajectories(k, p, r - 1, rng, acc);
}

}

0 comments on commit 8e1e5ad

Please sign in to comment.