Skip to content

[PEx] Adds hybrid stateful backtracking, improves storing search tasks #749

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

Merged
merged 3 commits into from
Jul 15, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.Setter;
import pexplicit.runtime.machine.buffer.BufferSemantics;
import pexplicit.runtime.scheduler.explicit.StateCachingMode;
import pexplicit.runtime.scheduler.explicit.StatefulBacktrackingMode;
import pexplicit.runtime.scheduler.explicit.strategy.SearchStrategyMode;

/**
Expand Down Expand Up @@ -52,9 +53,9 @@ public class PExplicitConfig {
// state caching mode
@Setter
StateCachingMode stateCachingMode = StateCachingMode.Murmur3_128;
// use stateful backtracking
// stateful backtracking mode
@Setter
boolean statefulBacktrackEnabled = true;
StatefulBacktrackingMode statefulBacktrackingMode = StatefulBacktrackingMode.IntraTask;
// search strategy mode
@Setter
SearchStrategyMode searchStrategyMode = SearchStrategyMode.Random;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.apache.commons.cli.*;
import pexplicit.runtime.scheduler.explicit.StateCachingMode;
import pexplicit.runtime.scheduler.explicit.StatefulBacktrackingMode;
import pexplicit.runtime.scheduler.explicit.strategy.SearchStrategyMode;

import java.io.PrintWriter;
Expand Down Expand Up @@ -165,13 +166,15 @@ public class PExplicitOptions {
addHiddenOption(stateCachingMode);

// whether or not to disable stateful backtracking
Option backtrack =
Option backtrackMode =
Option.builder()
.longOpt("no-backtrack")
.desc("Disable stateful backtracking")
.numberOfArgs(0)
.longOpt("stateful-backtrack")
.desc("Stateful backtracking mode: none, intra-task, all (default: intra-task)")
.numberOfArgs(1)
.hasArg()
.argName("Backtrack Mode (string)")
.build();
addHiddenOption(backtrack);
addHiddenOption(backtrackMode);

// max number of schedules to explore per search task
Option maxSchedulesPerTask =
Expand Down Expand Up @@ -363,8 +366,22 @@ public static PExplicitConfig ParseCommandlineArgs(String[] args) {
String.format("Unrecognized state caching mode, got %s", option.getValue()));
}
break;
case "no-backtrack":
config.setStatefulBacktrackEnabled(false);
case "stateful-backtrack":
switch (option.getValue()) {
case "none":
config.setStatefulBacktrackingMode(StatefulBacktrackingMode.None);
break;
case "intra-task":
config.setStatefulBacktrackingMode(StatefulBacktrackingMode.IntraTask);
break;
case "all":
config.setStatefulBacktrackingMode(StatefulBacktrackingMode.All);
break;
default:
optionError(
option,
String.format("Unrecognized stateful backtrack mode, got %s", option.getValue()));
}
break;
case "schedules-per-task":
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
import java.util.function.Function;

public class ForeignFunctionInterface {
/**
* Invoke a foreign function with a void return type
*
* @param fn function to invoke
* @param args arguments
*/
public static void accept(Consumer<List<Object>> fn, Object... args) {
fn.accept(List.of(args));
}
/**
* Invoke a foreign function with a void return type
*
* @param fn function to invoke
* @param args arguments
*/
public static void accept(Consumer<List<Object>> fn, Object... args) {
fn.accept(List.of(args));
}

/**
* Invoke a foreign function with a non-void return type
*
* @param fn function to invoke
* @param args arguments
* @return the return value of the function
*/
public static Object apply(Function<List<Object>, Object> fn, Object... args) {
return fn.apply(List.of(args));
}
/**
* Invoke a foreign function with a non-void return type
*
* @param fn function to invoke
* @param args arguments
* @return the return value of the function
*/
public static Object apply(Function<List<Object>, Object> fn, Object... args) {
return fn.apply(List.of(args));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import pexplicit.runtime.machine.PMonitor;
import pexplicit.runtime.machine.State;
import pexplicit.runtime.machine.events.PContinuation;
import pexplicit.runtime.scheduler.choice.Choice;
import pexplicit.runtime.scheduler.choice.ScheduleChoice;
import pexplicit.runtime.scheduler.choice.ScheduleSearchUnit;
import pexplicit.runtime.scheduler.choice.SearchUnit;
import pexplicit.runtime.scheduler.explicit.ExplicitSearchScheduler;
Expand Down Expand Up @@ -155,7 +153,7 @@ public static void logEndTask(SearchTask task, int numSchedules) {
* @param task Next search task
*/
public static void logNextTask(SearchTask task) {
if (verbosity > 1) {
if (verbosity > 0) {
log.info(String.format(" Next task: %s", task.toStringDetailed()));
}
}
Expand All @@ -171,6 +169,29 @@ public static void logNewTasks(List<SearchTask> tasks) {
}
}

/**
* Log when serializing a task
*
* @param task Task to serialize
* @param szBytes Bytes written
*/
public static void logSerializeTask(SearchTask task, long szBytes) {
if (verbosity > 1) {
log.info(String.format(" %,.1f MB written in %s", (szBytes / 1024.0 / 1024.0), task.getSerializeFile()));
}
}

/**
* Log when deserializing a task
*
* @param task Task that is deserialized
*/
public static void logDeserializeTask(SearchTask task) {
if (verbosity > 1) {
log.info(String.format(" Reading %s from %s", task, task.getSerializeFile()));
}
}

/**
* Log at the start of an iteration
*
Expand Down Expand Up @@ -209,9 +230,9 @@ public static void logFinishedIteration(int step) {
/**
* Log when backtracking to a search unit
*
* @param stepNum Step number
* @param stepNum Step number
* @param choiceNum Choice number
* @param unit Search unit to which backtracking to
* @param unit Search unit to which backtracking to
*/
public static void logBacktrack(int stepNum, int choiceNum, SearchUnit unit) {
if (verbosity > 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

@Getter
public class PMachineId {
public class PMachineId implements Serializable {
Class<? extends PMachine> type;
int typeId;
@Setter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.Getter;
import pexplicit.runtime.machine.PMachine;
import pexplicit.utils.exceptions.PExplicitRuntimeException;
import pexplicit.utils.misc.Assert;
import pexplicit.values.PMessage;

import java.io.Serializable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pexplicit.runtime.scheduler.choice.Choice;
import pexplicit.runtime.scheduler.choice.DataChoice;
import pexplicit.runtime.scheduler.choice.ScheduleChoice;
import pexplicit.runtime.scheduler.explicit.StatefulBacktrackingMode;
import pexplicit.runtime.scheduler.explicit.StepState;
import pexplicit.values.PValue;

Expand Down Expand Up @@ -62,16 +63,16 @@ public void removeChoicesAfter(int choiceNum) {
/**
* Set the schedule choice at a choice depth.
*
* @param stepNum Step number
* @param choiceNum Choice number
* @param current Machine to set as current schedule choice
* @param stepNum Step number
* @param choiceNum Choice number
* @param current Machine to set as current schedule choice
*/
public void setScheduleChoice(int stepNum, int choiceNum, PMachineId current) {
if (choiceNum == choices.size()) {
choices.add(null);
}
assert (choiceNum < choices.size());
if (PExplicitGlobal.getConfig().isStatefulBacktrackEnabled()
if (PExplicitGlobal.getConfig().getStatefulBacktrackingMode() != StatefulBacktrackingMode.None
&& stepNum != 0) {
assert (stepBeginState != null);
choices.set(choiceNum, new ScheduleChoice(stepNum, choiceNum, current, stepBeginState));
Expand All @@ -83,9 +84,9 @@ public void setScheduleChoice(int stepNum, int choiceNum, PMachineId current) {
/**
* Set the data choice at a choice depth.
*
* @param stepNum Step number
* @param choiceNum Choice number
* @param current PValue to set as current schedule choice
* @param stepNum Step number
* @param choiceNum Choice number
* @param current PValue to set as current schedule choice
*/
public void setDataChoice(int stepNum, int choiceNum, PValue<?> current) {
if (choiceNum == choices.size()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pexplicit.values.*;

import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.TimeoutException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void clearCurrent() {
*
* @return Choice object with the copied current choice
*/
abstract public Choice copyCurrent();
abstract public Choice copyCurrent(boolean copyState);

abstract public String toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public DataChoice(PValue<?> c) {
super(c);
}

public Choice copyCurrent() {
public Choice copyCurrent(boolean copyState) {
return new DataChoice(this.current);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.util.ArrayList;
import java.util.List;

public class DataSearchUnit extends SearchUnit<PValue<?>>{
public class DataSearchUnit extends SearchUnit<PValue<?>> {
/**
* Constructor
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ public ScheduleChoice(int stepNum, int choiceNum, PMachineId c, StepState s) {
this.choiceState = s;
}

public Choice copyCurrent() {
return new ScheduleChoice(this.stepNumber, this.choiceNumber, this.current, this.choiceState);
public Choice copyCurrent(boolean copyState) {
if (copyState) {
return new ScheduleChoice(this.stepNumber, this.choiceNumber, this.current, this.choiceState);
} else {
return new ScheduleChoice(this.stepNumber, this.choiceNumber, this.current, null);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package pexplicit.runtime.scheduler.choice;

import pexplicit.runtime.machine.PMachineId;
import pexplicit.runtime.scheduler.explicit.StepState;

import java.util.ArrayList;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import pexplicit.runtime.machine.PMachine;
import pexplicit.runtime.machine.PMachineId;
import pexplicit.runtime.scheduler.Scheduler;
import pexplicit.runtime.scheduler.choice.Choice;
import pexplicit.runtime.scheduler.choice.ScheduleChoice;
import pexplicit.runtime.scheduler.choice.SearchUnit;
import pexplicit.runtime.scheduler.explicit.strategy.*;
Expand Down Expand Up @@ -112,9 +111,9 @@ public void run() throws TimeoutException {
runIteration();
postProcessIteration();
}
PExplicitLogger.logEndTask(searchStrategy.getCurrTask(), searchStrategy.getNumSchedulesInCurrTask());
addRemainingChoicesAsChildrenTasks();
endCurrTask();
PExplicitLogger.logEndTask(searchStrategy.getCurrTask(), searchStrategy.getNumSchedulesInCurrTask());

if (searchStrategy.getPendingTasks().isEmpty() || PExplicitGlobal.getStatus() == STATUS.SCHEDULEOUT) {
// all tasks completed or schedule limit reached
Expand Down Expand Up @@ -193,7 +192,7 @@ protected void runStep() throws TimeoutException {
return;
}

if (PExplicitGlobal.getConfig().isStatefulBacktrackEnabled()
if (PExplicitGlobal.getConfig().getStatefulBacktrackingMode() != StatefulBacktrackingMode.None
&& stepNumber != 0) {
schedule.setStepBeginState(stepState.copyState());
}
Expand Down Expand Up @@ -431,7 +430,7 @@ private void postProcessIteration() {
private void addRemainingChoicesAsChildrenTasks() {
SearchTask parentTask = searchStrategy.getCurrTask();
int numChildrenAdded = 0;
for (int i: parentTask.getSearchUnitKeys(false)) {
for (int i : parentTask.getSearchUnitKeys(false)) {
SearchUnit unit = parentTask.getSearchUnit(i);
// if search unit at this depth is non-empty
if (!unit.getUnexplored().isEmpty()) {
Expand Down Expand Up @@ -462,7 +461,7 @@ private void setChildTask(SearchUnit unit, int choiceNum, SearchTask parentTask,
newTask.addSuffixSearchUnit(choiceNum, unit);

if (!isExact) {
for (int i: parentTask.getSearchUnitKeys(false)) {
for (int i : parentTask.getSearchUnitKeys(false)) {
if (i > choiceNum) {
if (i > maxChoiceNum) {
maxChoiceNum = i;
Expand All @@ -476,6 +475,7 @@ private void setChildTask(SearchUnit unit, int choiceNum, SearchTask parentTask,
newTask.addPrefixChoice(schedule.getChoice(i));
}

newTask.serializeTask();
parentTask.addChild(newTask);
searchStrategy.addNewTask(newTask);
}
Expand All @@ -494,11 +494,11 @@ public SearchTask setNextTask() {
}

public int getNumUnexploredChoices() {
return searchStrategy.getCurrTask().getNumUnexploredChoices() + searchStrategy.getNumPendingChoices();
return searchStrategy.getCurrTask().getCurrentNumUnexploredChoices() + searchStrategy.getNumPendingChoices();
}

public int getNumUnexploredDataChoices() {
return searchStrategy.getCurrTask().getNumUnexploredDataChoices() + searchStrategy.getNumPendingDataChoices();
return searchStrategy.getCurrTask().getCurrentNumUnexploredDataChoices() + searchStrategy.getNumPendingDataChoices();
}

/**
Expand All @@ -518,7 +518,7 @@ public double getUnexploredDataChoicesPercent() {

private void postIterationCleanup() {
SearchTask task = searchStrategy.getCurrTask();
for (int cIdx: task.getSearchUnitKeys(true)) {
for (int cIdx : task.getSearchUnitKeys(true)) {
SearchUnit unit = task.getSearchUnit(cIdx);
if (unit.getUnexplored().isEmpty()) {
task.clearSearchUnit(cIdx);
Expand All @@ -528,7 +528,7 @@ private void postIterationCleanup() {
backtrackChoiceNumber = cIdx;
int newStepNumber = 0;
ScheduleChoice scheduleChoice = null;
if (PExplicitGlobal.getConfig().isStatefulBacktrackEnabled()) {
if (PExplicitGlobal.getConfig().getStatefulBacktrackingMode() != StatefulBacktrackingMode.None) {
scheduleChoice = schedule.getScheduleChoiceAt(cIdx);
if (scheduleChoice != null && scheduleChoice.getChoiceState() != null) {
newStepNumber = scheduleChoice.getStepNumber();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package pexplicit.runtime.scheduler.explicit;

public enum StatefulBacktrackingMode {
None,
IntraTask,
All
}
Loading
Loading