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:
Parth Karia 2017-06-06 00:25:47 +05:30 committed by maibin
parent 97c1291359
commit 137e182f55
3 changed files with 307 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}