BAEL-875 Example of Hill Climbing algorithm (#1968)
* Dependency Injection examples Dependency Injection examples for evaluation article * Junit test cases added for dependency injection Junit test cases added for dependency injection * ClassNotFoundException vs NoClassDefFoundError Example to reproduce ClassNotFoundException & NoClassDefFoundError * JUnit test cases for ClassNotFoundException & NoClassDefFoundError test cases to reproduce ClassNotFoundException & NoClassDefFoundError * Deleting exampls for evaluation article * BAEL-831 Examples for ClassNotFoundException & NoClassDefFoundError * BAEL-831 Removed wrapper class * Removing evaluation article example * BAEL-831 removed wrapper class * BAEL-875 - Hill Climbing Algorithm BAEL-875 - Implementation for Hill Climbing Algorithm * BAEL-875 Modified algorithm with stream api
This commit is contained in:
parent
97c1291359
commit
137e182f55
|
@ -0,0 +1,199 @@
|
||||||
|
package com.baeldung.algorithms.hillclimbing;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class HillClimbing {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
HillClimbing hillClimbing = new HillClimbing();
|
||||||
|
String blockArr[] = { "B", "C", "D", "A" };
|
||||||
|
Stack<String> startState = hillClimbing.getStackWithValues(blockArr);
|
||||||
|
String goalBlockArr[] = { "A", "B", "C", "D" };
|
||||||
|
Stack<String> goalState = hillClimbing.getStackWithValues(goalBlockArr);
|
||||||
|
try {
|
||||||
|
List<State> solutionSequence = hillClimbing.getRouteWithHillClimbing(startState, goalState);
|
||||||
|
solutionSequence.forEach(HillClimbing::printEachStep);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printEachStep(State state) {
|
||||||
|
List<Stack<String>> stackList = state.getState();
|
||||||
|
System.out.println("----------------");
|
||||||
|
stackList.forEach(stack -> {
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
System.out.println(stack.pop());
|
||||||
|
}
|
||||||
|
System.out.println(" ");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stack<String> getStackWithValues(String[] blocks) {
|
||||||
|
Stack<String> stack = new Stack<String>();
|
||||||
|
for (String block : blocks)
|
||||||
|
stack.push(block);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method prepares path from init state to goal state
|
||||||
|
*
|
||||||
|
* @param initStateStack
|
||||||
|
* @param goalStateStack
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public List<State> getRouteWithHillClimbing(Stack<String> initStateStack, Stack<String> goalStateStack) throws Exception {
|
||||||
|
List<Stack<String>> initStateStackList = new ArrayList<Stack<String>>();
|
||||||
|
initStateStackList.add(initStateStack);
|
||||||
|
int initStateHeuristics = getHeuristicsValue(initStateStackList, goalStateStack);
|
||||||
|
State initState = new State(initStateStackList, initStateHeuristics);
|
||||||
|
|
||||||
|
List<State> resultPath = new ArrayList<>();
|
||||||
|
resultPath.add(new State(initState));
|
||||||
|
|
||||||
|
State currentState = initState;
|
||||||
|
boolean noStateFound = false;
|
||||||
|
while (!currentState.getState()
|
||||||
|
.get(0)
|
||||||
|
.equals(goalStateStack) || noStateFound) {
|
||||||
|
noStateFound = true;
|
||||||
|
State nextState = findNextState(currentState, goalStateStack);
|
||||||
|
if (nextState != null) {
|
||||||
|
noStateFound = false;
|
||||||
|
currentState = nextState;
|
||||||
|
resultPath.add(new State(nextState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noStateFound)
|
||||||
|
throw new Exception("No path found");
|
||||||
|
return resultPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method finds new state from current state based on goal and
|
||||||
|
* heuristics
|
||||||
|
*
|
||||||
|
* @param currentState
|
||||||
|
* @param goalStateStack
|
||||||
|
* @return a next state
|
||||||
|
*/
|
||||||
|
public State findNextState(State currentState, Stack<String> goalStateStack) {
|
||||||
|
List<Stack<String>> listOfStacks = currentState.getState();
|
||||||
|
int currentStateHeuristics = currentState.getHeuristics();
|
||||||
|
|
||||||
|
Optional<State> newState = listOfStacks.stream()
|
||||||
|
.map(stack -> {
|
||||||
|
State tempState = null;
|
||||||
|
List<Stack<String>> tempStackList = new ArrayList<Stack<String>>(listOfStacks);
|
||||||
|
String block = stack.pop();
|
||||||
|
if (stack.size() == 0)
|
||||||
|
tempStackList.remove(stack);
|
||||||
|
tempState = pushElementToNewStack(tempStackList, block, currentStateHeuristics, goalStateStack);
|
||||||
|
if (tempState == null) {
|
||||||
|
tempState = pushElementToExistingStacks(stack, tempStackList, block, currentStateHeuristics, goalStateStack);
|
||||||
|
}
|
||||||
|
if (tempState == null)
|
||||||
|
stack.push(block);
|
||||||
|
return tempState;
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return newState.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation to be applied on a state in order to find new states. This
|
||||||
|
* operation pushes an element into a new stack
|
||||||
|
*
|
||||||
|
* @param currentStackList
|
||||||
|
* @param block
|
||||||
|
* @param currentStateHeuristics
|
||||||
|
* @param goalStateStack
|
||||||
|
* @return a new state
|
||||||
|
*/
|
||||||
|
private State pushElementToNewStack(List<Stack<String>> currentStackList, String block, int currentStateHeuristics, Stack<String> goalStateStack) {
|
||||||
|
State newState = null;
|
||||||
|
Stack<String> newStack = new Stack<String>();
|
||||||
|
newStack.push(block);
|
||||||
|
|
||||||
|
currentStackList.add(newStack);
|
||||||
|
int newStateHeuristics = getHeuristicsValue(currentStackList, goalStateStack);
|
||||||
|
if (newStateHeuristics > currentStateHeuristics) {
|
||||||
|
newState = new State(currentStackList, newStateHeuristics);
|
||||||
|
} else {
|
||||||
|
currentStackList.remove(newStack);
|
||||||
|
}
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation to be applied on a state in order to find new states. This
|
||||||
|
* operation pushes an element into one of the other stacks to explore new
|
||||||
|
* states
|
||||||
|
*
|
||||||
|
* @param stack
|
||||||
|
* @param currentStackList
|
||||||
|
* @param block
|
||||||
|
* @param currentStateHeuristics
|
||||||
|
* @param goalStateStack
|
||||||
|
* @return a new state
|
||||||
|
*/
|
||||||
|
private State pushElementToExistingStacks(Stack currentStack, List<Stack<String>> currentStackList, String block, int currentStateHeuristics, Stack<String> goalStateStack) {
|
||||||
|
|
||||||
|
Optional<State> newState = currentStackList.stream()
|
||||||
|
.filter(stack -> stack != currentStack)
|
||||||
|
.map(stack -> {
|
||||||
|
stack.push(block);
|
||||||
|
int newStateHeuristics = getHeuristicsValue(currentStackList, goalStateStack);
|
||||||
|
if (newStateHeuristics > currentStateHeuristics) {
|
||||||
|
return new State(currentStackList, newStateHeuristics);
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
return newState.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns heuristics value for given state with respect to goal
|
||||||
|
* state
|
||||||
|
*
|
||||||
|
* @param currentState
|
||||||
|
* @param goalStateStack
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getHeuristicsValue(List<Stack<String>> currentState, Stack<String> goalStateStack) {
|
||||||
|
|
||||||
|
Integer heuristicValue = 0;
|
||||||
|
heuristicValue = currentState.stream()
|
||||||
|
.mapToInt(stack -> {
|
||||||
|
int stackHeuristics = 0;
|
||||||
|
boolean isPositioneCorrect = true;
|
||||||
|
int goalStartIndex = 0;
|
||||||
|
for (String currentBlock : stack) {
|
||||||
|
if (isPositioneCorrect && currentBlock.equals(goalStateStack.get(goalStartIndex))) {
|
||||||
|
stackHeuristics += goalStartIndex;
|
||||||
|
} else {
|
||||||
|
stackHeuristics -= goalStartIndex;
|
||||||
|
isPositioneCorrect = false;
|
||||||
|
}
|
||||||
|
goalStartIndex++;
|
||||||
|
}
|
||||||
|
return stackHeuristics;
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
return heuristicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.baeldung.algorithms.hillclimbing;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
public class State {
|
||||||
|
List<Stack<String>> state;
|
||||||
|
int heuristics;
|
||||||
|
|
||||||
|
public State() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public State(List<Stack<String>> state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public State(List<Stack<String>> state, int heuristics) {
|
||||||
|
this.state = state;
|
||||||
|
this.heuristics = heuristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public State(State state) {
|
||||||
|
if (state != null) {
|
||||||
|
this.state = new ArrayList<Stack<String>>();
|
||||||
|
for (Stack s : state.getState()) {
|
||||||
|
Stack s1 = new Stack();
|
||||||
|
s1 = (Stack) s.clone();
|
||||||
|
this.state.add(s1);
|
||||||
|
}
|
||||||
|
this.heuristics = state.getHeuristics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Stack<String>> getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(List<Stack<String>> state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeuristics() {
|
||||||
|
return heuristics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeuristics(int heuristics) {
|
||||||
|
this.heuristics = heuristics;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package algorithms;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.hillclimbing.HillClimbing;
|
||||||
|
import com.baeldung.algorithms.hillclimbing.State;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class HillClimbingAlgorithmTest {
|
||||||
|
Stack<String> initStack;
|
||||||
|
Stack<String> goalStack;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initStacks() {
|
||||||
|
String blockArr[] = { "B", "C", "D", "A" };
|
||||||
|
String goalBlockArr[] = { "A", "B", "C", "D" };
|
||||||
|
initStack = new Stack<String>();
|
||||||
|
for (String block : blockArr)
|
||||||
|
initStack.push(block);
|
||||||
|
goalStack = new Stack<String>();
|
||||||
|
for (String block : goalBlockArr)
|
||||||
|
goalStack.push(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInitAndGoalState_whenGetPathWithHillClimbing_thenPathFound() {
|
||||||
|
HillClimbing hillClimbing = new HillClimbing();
|
||||||
|
|
||||||
|
List<State> path;
|
||||||
|
try {
|
||||||
|
path = hillClimbing.getRouteWithHillClimbing(initStack, goalStack);
|
||||||
|
assertNotNull(path);
|
||||||
|
assertEquals(path.get(path.size() - 1)
|
||||||
|
.getState()
|
||||||
|
.get(0), goalStack);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCurrentState_whenFindNextState_thenBetterHeuristics() {
|
||||||
|
HillClimbing hillClimbing = new HillClimbing();
|
||||||
|
List<Stack<String>> initList = new ArrayList<Stack<String>>();
|
||||||
|
initList.add(initStack);
|
||||||
|
State currentState = new State(initList);
|
||||||
|
currentState.setHeuristics(hillClimbing.getHeuristicsValue(initList, goalStack));
|
||||||
|
State nextState = hillClimbing.findNextState(currentState, goalStack);
|
||||||
|
assertTrue(nextState.getHeuristics() > currentState.getHeuristics());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue