View Javadoc
1   package net.bmahe.genetics4j.gp.program;
2   
3   import java.util.List;
4   import java.util.Objects;
5   import java.util.Set;
6   import java.util.random.RandomGenerator;
7   import java.util.stream.Collectors;
8   import java.util.stream.Stream;
9   
10  import org.apache.commons.lang3.Validate;
11  import org.apache.logging.log4j.LogManager;
12  import org.apache.logging.log4j.Logger;
13  
14  import net.bmahe.genetics4j.gp.OperationFactory;
15  
16  public class ProgramHelper {
17  	public final static Logger logger = LogManager.getLogger(ProgramHelper.class);
18  
19  	private final RandomGenerator randomGenerator;
20  
21  	public ProgramHelper(final RandomGenerator _randomGenerator) {
22  		Objects.requireNonNull(_randomGenerator);
23  
24  		this.randomGenerator = _randomGenerator;
25  	}
26  
27  	public OperationFactory pickRandomFunction(final Program program) {
28  		Objects.requireNonNull(program);
29  		Validate.isTrue(program.functions().size() > 0);
30  
31  		final Set<OperationFactory> functions = program.functions();
32  		return functions.stream().skip(randomGenerator.nextInt(functions.size())).findFirst().get();
33  	}
34  
35  	public <T> OperationFactory pickRandomFunction(final Program program, final Class<T> requiredClass) {
36  		Objects.requireNonNull(program);
37  		Objects.requireNonNull(requiredClass);
38  		Validate.isTrue(program.functions().size() > 0);
39  
40  		final Set<OperationFactory> functions = program.functions();
41  		@SuppressWarnings("unchecked")
42  		final List<OperationFactory> candidates = functions.stream()
43  				.filter((operationFactory) -> operationFactory.returnedType().isAssignableFrom(requiredClass))
44  				.collect(Collectors.toList());
45  
46  		if (candidates == null || candidates.isEmpty()) {
47  			throw new IllegalArgumentException("Could not find a suitable function returning a " + requiredClass);
48  		}
49  
50  		return candidates.get(randomGenerator.nextInt(candidates.size()));
51  	}
52  
53  	public <T> OperationFactory pickRandomTerminal(final Program program, final Class<T> requiredClass) {
54  		Objects.requireNonNull(program);
55  		Objects.requireNonNull(requiredClass);
56  
57  		final Set<OperationFactory> terminals = program.terminal();
58  		@SuppressWarnings("unchecked")
59  		final List<OperationFactory> candidates = terminals.stream()
60  				.filter((operationFactory) -> operationFactory.returnedType().isAssignableFrom(requiredClass))
61  				.collect(Collectors.toList());
62  
63  		if (candidates == null || candidates.isEmpty()) {
64  			throw new IllegalArgumentException("Could not find a suitable terminal returning a " + requiredClass);
65  		}
66  
67  		return candidates.get(randomGenerator.nextInt(candidates.size()));
68  	}
69  
70  	public OperationFactory pickRandomTerminal(final Program program) {
71  		Objects.requireNonNull(program);
72  
73  		final Set<OperationFactory> terminals = program.terminal();
74  		final List<OperationFactory> candidates = terminals.stream().collect(Collectors.toList());
75  
76  		return candidates.get(randomGenerator.nextInt(candidates.size()));
77  	}
78  
79  	public OperationFactory pickRandomFunctionOrTerminal(final Program program) {
80  		Objects.requireNonNull(program);
81  
82  		final Set<OperationFactory> terminals = program.terminal();
83  		final Set<OperationFactory> functions = program.functions();
84  		final int totalNumberCandidates = terminals.size() + functions.size();
85  
86  		final Stream<OperationFactory> candidates = Stream.concat(terminals.stream(), functions.stream());
87  		final int chosenCandidate = randomGenerator.nextInt(totalNumberCandidates);
88  
89  		return candidates.skip(chosenCandidate).findFirst().get();
90  	}
91  
92  	public <T> OperationFactory pickRandomFunctionOrTerminal(final Program program, final Class<T> requiredClass) {
93  		Objects.requireNonNull(program);
94  		Objects.requireNonNull(requiredClass);
95  
96  		final Set<OperationFactory> terminals = program.terminal();
97  		final Set<OperationFactory> functions = program.functions();
98  
99  		final Stream<OperationFactory> candidates = Stream.concat(terminals.stream(), functions.stream());
100 
101 		@SuppressWarnings("unchecked")
102 		final List<OperationFactory> filteredCandidates = candidates
103 				.filter((operationFactory) -> operationFactory.returnedType().isAssignableFrom(requiredClass))
104 				.collect(Collectors.toList());
105 
106 		final int filteredCandidatesCount = filteredCandidates.size();
107 		if (filteredCandidatesCount == 0) {
108 			logger.error(
109 					"No candidate terminals or functions found that can return an instance of class {}",
110 						requiredClass);
111 			logger.debug("\tKnown terminals: {}", program.terminal().stream());
112 			logger.debug("\tKnown functions: {}", program.functions());
113 
114 			throw new IllegalArgumentException(
115 					"No candidate terminals or functions found that can return an instance of class " + requiredClass);
116 		}
117 
118 		final int chosenCandidate = randomGenerator.nextInt(filteredCandidates.size());
119 
120 		return filteredCandidates.get(chosenCandidate);
121 	}
122 }