Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory additions #3

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion paladinus
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@
DIR=$(dirname "$0")
JAR=$DIR/target/paladinus-1.1-jar-with-dependencies.jar

java -jar $JAR -translatorPath $DIR/translator-fond/translate.py "$@"
# restrict the max heap size that can be used by the JVM
# MAX_HEAP=-Xmx512m
MAX_HEAP=""

# if one wants to use JCMD https://www.baeldung.com/running-jvm-diagnose
JCMD="-XX:NativeMemoryTracking=summary"
JCMD=""

java $MAX_HEAP $JCMD -jar $JAR -translatorPath $DIR/translator-fond/translate.py "$@"
49 changes: 44 additions & 5 deletions src/main/java/paladinus/PaladinusPlanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public class PaladinusPlanner {
public PaladinusPlanner(String[] args) throws FileNotFoundException, IOException {
new Global().initialize();
initialize(args);

// do a frist memory report
printMEMStats();
}

// public PaladinusPlanner() {}
Expand Down Expand Up @@ -126,6 +129,38 @@ public static void main(String[] args) throws IOException, FileNotFoundException
}
}

/**
* Print some Garbage Collector stats.
*/
public void printMEMStats() {
// Print memory usage
// https://stackoverflow.com/questions/3571203/what-are-runtime-getruntime-totalmemory-and-freememory
// https://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html

// System.gc(); // call GC explicitly to get more accurate memory usage
// Runtime.getRuntime().gc();
// System.out.println("\nGarbage collection called before memory consumtion check");


Runtime r = Runtime.getRuntime();
double gb = Math.pow(1024, 3);

double maxMemory = r.maxMemory() / gb; // max memory it can ever use, limit
double totalMemory = r.totalMemory() / gb; // current reserved memory (less than max)
double freeMemory = r.freeMemory() / gb; // free memory that can be allocated (less than total)
double usedMemory = totalMemory - freeMemory; // current memory been used (from totalMemory)

System.out.println("==============================");
System.out.println("MEMORY REPORTING (all in GB)");
System.out.println("==============================");
System.out.println("Max memory: " + maxMemory);
System.out.println("Total reserved memory: " + totalMemory);
System.out.println("Free memory: " + freeMemory);
System.out.println("Used memory: " + usedMemory);
System.out.println("==============================");
}


/**
* Print some Garbage Collector stats.
*/
Expand Down Expand Up @@ -267,10 +302,10 @@ public Result runProblem() {
System.out.println("\nResult: No policy found. Undecided.");
} else {
assert planFound == Result.EXPANDED_ALL;
System.out.println("\nResult: Search-space exapanded.");
System.out.println("\nResult: Search-space expanded.");
}
System.out.println();
System.out.println("Time needed for preprocess (Parsing, PDBs, ...): " + timeUsedForPreprocessing / 1000.0 + " seconds.");
System.out.println("Time needed for preprocessing (parsing, PDBs, ...): " + timeUsedForPreprocessing / 1000.0 + " seconds.");
System.out.println("Time needed for search: " + (timeUsedOverall - timeUsedForPreprocessing) / 1000.0 + " seconds.");
System.out.println("Time needed: " + timeUsedOverall / 1000.0 + " seconds.");
printGCStats();
Expand Down Expand Up @@ -339,7 +374,7 @@ public Result runProblemWithoutStats() {
if(heuristic != null)
search = new IterativeDepthFirstSearchPruning(problem, heuristic, Global.options.actionSelectionCriterion, Global.options.evaluationFunctionCriterion, Global.options.checkSolvedStates);
break;

case ITERATIVE_DFS_LEARNING:
System.out.println("Algorithm: Iterative Depth-First Search Learning for FOND Planning");
if(heuristic != null)
Expand All @@ -362,6 +397,7 @@ public Result runProblemWithoutStats() {
}
search.setTimeout(Global.options.timeout - timeUsedForPreprocessing);

// submit the search job to the thread pool
ExecutorService service = Executors.newFixedThreadPool(1);
Future<Result> futureResult = service.submit(search);
try{
Expand All @@ -372,7 +408,8 @@ public Result runProblemWithoutStats() {
} catch (InterruptedException e) {
planFound = Result.TIMEOUT;
e.printStackTrace();
} catch (ExecutionException e) {
} catch (ExecutionException e) { // https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ExecutionException.html
// #TODO: shouldn't this go last?
planFound = Result.OUT_OF_MEMORY;
if(e.getCause() instanceof NullPointerException)
planFound = Result.TIMEOUT;
Expand All @@ -384,7 +421,9 @@ public Result runProblemWithoutStats() {
}
/* Stop measuring search time. */
timeUsedOverall = System.currentTimeMillis() - startTime;
System.out.println("\nTotal Memory (GB) = " + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/ (1024.0 * 1024.0 * 1024.0)) + "\n");

printMEMStats();

assert planFound != null;
return planFound;
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/paladinus/search/dfs/DepthFirstSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public class DepthFirstSearch extends HeuristicSearch {
protected double estimatedValueBestConnectorFromInitialState = 0;

protected int NUMBER_ITERATIONS = 0;

// to track memory usage
protected float memoryUsed = 0;
protected long lastMemTaken;

protected Map<BigInteger, Double> stateNodeMapHValue = new HashMap<BigInteger, Double>();

Expand All @@ -75,6 +79,14 @@ public DepthFirstSearch(Problem problem, Heuristic heuristic) {
super(problem, heuristic);
}

// probes current memory consumption and stores it if greater than previous probe
protected void updateMem() {
if (System.currentTimeMillis() - lastMemTaken > 1000) {
this.memoryUsed = Math.max(this.memoryUsed, Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
lastMemTaken = System.currentTimeMillis();
}
}

@Override
public void doIteration() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public Result run() {
}

protected SearchFlag doIterativeSearch(Boolean unitaryBound, SearchNode node) {
long memUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

if(unitaryBound) {
this.POLICY_BOUND = 0;
} else {
Expand Down Expand Up @@ -90,13 +92,22 @@ protected SearchFlag doIterativeSearch(Boolean unitaryBound, SearchNode node) {
} else this.POLICY_BOUND = this.NEW_POLICY_BOUND;

this.NEW_POLICY_BOUND = Double.POSITIVE_INFINITY;


memUsed = Math.max(memUsed, Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());

} while (flag != SearchFlag.GOAL && this.POLICY_BOUND < Double.POSITIVE_INFINITY && flag != SearchFlag.TIMEOUT);

System.out.println("\nMax total Memory (GB) = " + memUsed / Math.pow(1024, 3) + "\n");

return flag;
}

protected Pair<SearchFlag, Set<SearchNode>> doIterativeSearch(SearchNode node, Set<SearchNode> closedSolved, double policySize, double policyBound) {
if (DEBUG)
if (DEBUG) {
dumpStateSpace(this.NUMBER_ITERATIONS);
this.updateMem(); // probe memory consumption
}

if(timeout())
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.TIMEOUT, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ protected SearchFlag doIterativeSearch(Boolean unitaryBound, SearchNode node) {
}

protected Pair<SearchFlag, Set<SearchNode>> doIterativeSearch(SearchNode node, Set<SearchNode> closedSolved, double policySize, double policyBound) {
if (DEBUG)
if (DEBUG) {
dumpStateSpace();
this.updateMem(); // probe memory consumption
}


if(timeout())
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.TIMEOUT, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
import paladinus.util.Pair;

/**
*
*
* An iterative (pruning) depth-first search algorithm for FOND Planning.
*
*
* @author Ramon Fraga Pereira
*
*/
public class IterativeDepthFirstSearchPruning extends DepthFirstSearch {

protected double POLICY_SIZE = 0;
protected double NEW_POLICY_BOUND = 0;

private boolean checkSolvedStates = false;

public IterativeDepthFirstSearchPruning(Problem problem, Heuristic heuristic, String strategies, String criterion, String checkSolved) {
Expand All @@ -33,7 +33,7 @@ public IterativeDepthFirstSearchPruning(Problem problem, Heuristic heuristic, St
System.out.println("Check Solveds: TRUE");
}
}

@Override
public Result run() {
/* Start measuring search time. */
Expand All @@ -48,118 +48,128 @@ public Result run() {

/* Finish measuring search time. */
endtime = System.currentTimeMillis();

System.out.println("\n# Closed-Solved Nodes = " + this.closedSolvedNodes.size());
System.out.println("\n# Closed-Non-Promising Nodes = " + this.closedDeadEndsNodes.size());

if (DEBUG)

if (DEBUG) {
System.out.println("\nMax total Memory probed (GB) = " + this.memoryUsed / Math.pow(1024, 3) + "\n");
dumpStateSpace(this.NUMBER_ITERATIONS);
}

if(timeout())
return Result.TIMEOUT;

if (flag == SearchFlag.GOAL) {
return Result.PROVEN;
} else if (flag == SearchFlag.DEAD_END || flag == SearchFlag.NO_POLICY) {
return Result.DISPROVEN;
} else return Result.TIMEOUT;
}

protected SearchFlag doIterativeSearch(Boolean unitaryBound, SearchNode node) {
if(unitaryBound) {
this.POLICY_BOUND = 0;
this.POLICY_BOUND = 0;
} else {
this.POLICY_BOUND = node.getHeuristic();
if(this.POLICY_BOUND == Double.POSITIVE_INFINITY)
return SearchFlag.NO_POLICY;
}
SearchFlag flag = SearchFlag.NO_POLICY;

this.NEW_POLICY_BOUND = Double.POSITIVE_INFINITY;

System.out.println("\n> Bound Initial: " + this.POLICY_BOUND);
System.out.println();
do {
System.out.println("> Bound: " + this.POLICY_BOUND);
System.out.println("> Bounds: " + this.POLICY_BOUND);
this.POLICY_SIZE = 0d;

this.dumpingCounterStateSpace = 0;
this.NUMBER_ITERATIONS++;

Set<SearchNode> closedSolved = new HashSet<>();
this.closedVisitedNodes.clear();
this.closedDeadEndsNodes.clear();

Pair<SearchFlag, Set<SearchNode>> resultSearch = doIterativeSearch(node, closedSolved, this.POLICY_SIZE, this.POLICY_BOUND);
flag = resultSearch.first;
this.closedSolvedNodes = resultSearch.second;

if(unitaryBound) {
this.POLICY_BOUND++;
this.POLICY_BOUND++;
} else this.POLICY_BOUND = this.NEW_POLICY_BOUND;

this.NEW_POLICY_BOUND = Double.POSITIVE_INFINITY;

} while (flag != SearchFlag.GOAL && this.POLICY_BOUND < Double.POSITIVE_INFINITY && flag != SearchFlag.TIMEOUT);

return flag;
}

protected Pair<SearchFlag, Set<SearchNode>> doIterativeSearch(SearchNode node, Set<SearchNode> closedSolved, double policySize, double policyBound) {
if (DEBUG)
if (DEBUG) {
dumpStateSpace(this.NUMBER_ITERATIONS);

this.updateMem(); // probe memory consumption
}



if(RECURSION_COUNTER >= Integer.MAX_VALUE)
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.DEAD_END, closedSolved);

if(timeout())
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.TIMEOUT, null);

RECURSION_COUNTER++;

if(node.isGoalNode() || closedSolved.contains(node)) {
closedSolved.addAll(this.closedVisitedNodes);
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.GOAL, closedSolved);
} else if (node.isDeadEndNode() || this.closedDeadEndsNodes.contains(node)) {
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.DEAD_END, closedSolved);
} else if (this.closedVisitedNodes.contains(node))
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.VISITED, closedSolved);

this.closedVisitedNodes.add(node);

PriorityQueue<SearchConnector> connectors = this.getNodeConnectors(node);
NODE_EXPANSIONS++;

boolean allConnectorsDeadEnds = true;
while(!connectors.isEmpty()) {
SearchConnector c = connectors.poll();

if(policySize + 1 + c.getEvaluationFunctionAccordingToCriterion() > policyBound && closedSolved.size() == 0) {
if(policySize + 1 + c.getEvaluationFunctionAccordingToCriterion() < this.NEW_POLICY_BOUND )
this.NEW_POLICY_BOUND = policySize + 1 + c.getEvaluationFunctionAccordingToCriterion();
this.NEW_POLICY_BOUND = policySize + 1 + c.getEvaluationFunctionAccordingToCriterion();
} else if(policySize + 1 > policyBound) {
if(policySize + 1 < this.NEW_POLICY_BOUND)
this.NEW_POLICY_BOUND = policySize + 1;
} else {
} else {
Set<SearchNode> pathsFound = new HashSet<>();

boolean newGoalPathFound = true;

boolean connectorDeadEnd = false;

Set<SearchNode> copyClosedSolved = new HashSet<>(closedSolved);

while(newGoalPathFound == true) {

newGoalPathFound = false;
Set<SearchNode> findingGoalPath = new HashSet<>();

for(SearchNode s: c.getChildren()) {
if(!pathsFound.contains(s))
findingGoalPath.add(s);
}
for(SearchNode s: findingGoalPath) {
// recursive call!
Pair<SearchFlag, Set<SearchNode>> resultSearch = doIterativeSearch(s, copyClosedSolved, policySize+1, policyBound);
SearchFlag flag = resultSearch.first;
copyClosedSolved = new HashSet<SearchNode>(resultSearch.second);

if(flag == SearchFlag.DEAD_END) {
newGoalPathFound = false;
connectorDeadEnd = true;
Expand All @@ -185,11 +195,11 @@ protected Pair<SearchFlag, Set<SearchNode>> doIterativeSearch(SearchNode node, S
this.closedDeadEndsNodes.add(node);
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.DEAD_END, closedSolved);
}

this.closedVisitedNodes.remove(node);
return new Pair<SearchFlag, Set<SearchNode>>(SearchFlag.VISITED, closedSolved);
}

@Override
public void printStats(boolean simulatePlan) {
System.out.println("# Number Iterations = " + this.NUMBER_ITERATIONS);
Expand Down