/** * */ package org.cmg.ml.sam.sim.pm; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * The instances of this class represent a generic population state having species of type <code>S</code>. * * * @author loreti * */ public class PopulationState<S> { /** * Internally the state is represented via a mapping from <code>S</code> to <code>Integer</code>. */ private final HashMap<S,Integer> population; /** * Creates a new population state with a given population. * * @param population */ public PopulationState( HashMap<S,Integer> population ) { this.population = population; } /** * Creates an empty population state. */ public PopulationState() { this( new HashMap<>() ); } protected Set<Map.Entry<S, Integer>> getEntries() { return population.entrySet(); } public int getOccupancy( S s ) { return population.getOrDefault(s, 0); } public void set( S s , Integer value ) { population.put(s, value); } public void apply( S s , Drift d ) { int value = population.getOrDefault(s, 0); population.put(s, value-d.getPreset()+d.getPoset()); } @SuppressWarnings("unchecked") public PopulationState<S> copy() { return new PopulationState<>( (HashMap<S, Integer>) population.clone() ); } public double min( Function<S, Double> f ) { return min( s -> true , f ); } public double min( Predicate<S> p , Function<S, Double> f) { double min = Double.MAX_VALUE; for (Entry<S, Integer> entry : getEntries()) { S s = entry.getKey(); if (p.test(s)&&entry.getValue()>0) { min = Math.min(min, f.apply(s)); } } return min; } public double max( Function<S, Double> f ) { return max( s -> true , f ); } public double max( Predicate<S> p , Function<S, Double> f) { double max = Double.MIN_VALUE; for (Entry<S, Integer> entry : getEntries()) { S s = entry.getKey(); if (p.test(s)&&entry.getValue()>0) { max = Math.max(max, f.apply(s)); } } return max; } public double average( Predicate<S> p , Function<S, Double> f ) { double total = 0.0; int counter = 0; for (Entry<S, Integer> entry : getEntries()) { S s = entry.getKey(); int value = entry.getValue(); if (p.test(s)&&value>0) { total += entry.getValue()*f.apply(s); counter += value; } } return total/counter; } public double average( Function<S, Double> f ) { return average( s -> true , f ); } public Stream<Entry<S, Integer>> select( Predicate<S> p ) { return getEntries().stream().filter(e -> (e.getValue()>0)&&(p.test(e.getKey()))); } }