From 242fc6e63fd448e2520b8d52870288794071f969 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Tue, 23 Apr 2024 21:04:15 +0000 Subject: [PATCH] [PExplicit] Improve state caching Adds storing hashcode and string representation during PValue initialization Adds new state caching modes using hash functions from guava library New state caching modes include: hashcode (java built in, 32-bit), siphash24 (64-bit), murmur3_128 (128-bit, default), sha256 (256-bit), or exact (using exact string representation) --- .../src/main/java/pexplicit/PExplicit.java | 2 + .../commandline/PExplicitConfig.java | 2 +- .../commandline/PExplicitOptions.java | 15 ++++- .../runtime/logger/PExplicitLogger.java | 2 +- .../pexplicit/runtime/logger/TraceLogger.java | 2 +- .../pexplicit/runtime/machine/PMachine.java | 2 +- .../java/pexplicit/runtime/machine/State.java | 2 +- .../runtime/machine/buffer/MessageQueue.java | 2 +- .../runtime/machine/events/PContinuation.java | 1 + .../runtime/scheduler/Scheduler.java | 9 ++- .../explicit/ExplicitSearchScheduler.java | 27 ++++----- .../scheduler/explicit/StateCachingMode.java | 5 +- .../java/pexplicit/values/ComputeHash.java | 40 ++++++++++++- .../src/main/java/pexplicit/values/PBool.java | 17 +++--- .../src/main/java/pexplicit/values/PEnum.java | 16 +++--- .../main/java/pexplicit/values/PEvent.java | 22 ++++---- .../main/java/pexplicit/values/PFloat.java | 17 +++--- .../src/main/java/pexplicit/values/PInt.java | 17 +++--- .../java/pexplicit/values/PMachineValue.java | 15 ++--- .../src/main/java/pexplicit/values/PMap.java | 41 +++++++------- .../machine/events => values}/PMessage.java | 30 +++++----- .../java/pexplicit/values/PNamedTuple.java | 42 +++++++------- .../src/main/java/pexplicit/values/PSeq.java | 33 +++++------ .../src/main/java/pexplicit/values/PSet.java | 33 +++++------ .../main/java/pexplicit/values/PString.java | 15 ++--- .../main/java/pexplicit/values/PTuple.java | 34 +++++------ .../main/java/pexplicit/values/PValue.java | 56 ++++++++++++++----- 27 files changed, 304 insertions(+), 195 deletions(-) rename Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/{runtime/machine/events => values}/PMessage.java (83%) diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/PExplicit.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/PExplicit.java index 23788d88ca..8e3f64e78b 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/PExplicit.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/PExplicit.java @@ -12,6 +12,7 @@ import pexplicit.utils.monitor.MemoryMonitor; import pexplicit.utils.monitor.TimeMonitor; import pexplicit.utils.random.RandomNumberGenerator; +import pexplicit.values.ComputeHash; import java.lang.reflect.InvocationTargetException; import java.util.Optional; @@ -32,6 +33,7 @@ public static void main(String[] args) { // parse the commandline arguments to create the configuration PExplicitGlobal.setConfig(PExplicitOptions.ParseCommandlineArgs(args)); PExplicitLogger.Initialize(PExplicitGlobal.getConfig().getVerbosity()); + ComputeHash.Initialize(); // get reflections corresponding to the model Reflections reflections = new Reflections("pexplicit.model"); diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitConfig.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitConfig.java index 60d9453881..1c88845f46 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitConfig.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitConfig.java @@ -55,7 +55,7 @@ public class PExplicitConfig { BufferSemantics bufferSemantics = BufferSemantics.SenderQueue; // state caching mode @Setter - StateCachingMode stateCachingMode = StateCachingMode.Fingerprint; + StateCachingMode stateCachingMode = StateCachingMode.Murmur3_128; // use stateful backtracking @Setter boolean statefulBacktrackEnabled = true; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitOptions.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitOptions.java index 55f2ba0cd4..f1cc0f29c6 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitOptions.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/commandline/PExplicitOptions.java @@ -155,7 +155,7 @@ public class PExplicitOptions { Option stateCachingMode = Option.builder() .longOpt("state-caching") - .desc("State caching mode: none, fingerprint, exact (default: fingerprint)") + .desc("State caching mode: none, hashcode, siphash24, murmur3_128, sha256, exact (default: murmur3_128)") .numberOfArgs(1) .hasArg() .argName("Caching Mode (string)") @@ -312,8 +312,17 @@ public static PExplicitConfig ParseCommandlineArgs(String[] args) { case "none": config.setStateCachingMode(StateCachingMode.None); break; - case "fingerprint": - config.setStateCachingMode(StateCachingMode.Fingerprint); + case "hashcode": + config.setStateCachingMode(StateCachingMode.HashCode); + break; + case "siphash24": + config.setStateCachingMode(StateCachingMode.SipHash24); + break; + case "murmur3_128": + config.setStateCachingMode(StateCachingMode.Murmur3_128); + break; + case "sha256": + config.setStateCachingMode(StateCachingMode.Sha256); break; case "exact": config.setStateCachingMode(StateCachingMode.Exact); diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/PExplicitLogger.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/PExplicitLogger.java index f01366613d..5afc5913cd 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/PExplicitLogger.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/PExplicitLogger.java @@ -12,13 +12,13 @@ import pexplicit.runtime.machine.PMonitor; import pexplicit.runtime.machine.State; import pexplicit.runtime.machine.events.PContinuation; -import pexplicit.runtime.machine.events.PMessage; import pexplicit.runtime.scheduler.explicit.ExplicitSearchScheduler; import pexplicit.runtime.scheduler.explicit.SearchStatistics; import pexplicit.runtime.scheduler.explicit.StateCachingMode; import pexplicit.runtime.scheduler.replay.ReplayScheduler; import pexplicit.utils.monitor.MemoryMonitor; import pexplicit.values.PEvent; +import pexplicit.values.PMessage; import pexplicit.values.PValue; import java.io.PrintWriter; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/TraceLogger.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/TraceLogger.java index 22464adb40..67eeb64de5 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/TraceLogger.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/logger/TraceLogger.java @@ -12,7 +12,7 @@ import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.layout.PatternLayout; import pexplicit.runtime.machine.PMachine; -import pexplicit.runtime.machine.events.PMessage; +import pexplicit.values.PMessage; import java.io.File; import java.io.FileOutputStream; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/PMachine.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/PMachine.java index 1f79f4e611..56f8003540 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/PMachine.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/PMachine.java @@ -7,13 +7,13 @@ import pexplicit.runtime.machine.buffer.SenderQueue; import pexplicit.runtime.machine.eventhandlers.EventHandler; import pexplicit.runtime.machine.events.PContinuation; -import pexplicit.runtime.machine.events.PMessage; import pexplicit.utils.exceptions.BugFoundException; import pexplicit.utils.misc.Assert; import pexplicit.utils.serialize.SerializableBiFunction; import pexplicit.utils.serialize.SerializableRunnable; import pexplicit.values.PEvent; import pexplicit.values.PMachineValue; +import pexplicit.values.PMessage; import pexplicit.values.PValue; import java.io.Serializable; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/State.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/State.java index df89575a92..4c2718890a 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/State.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/State.java @@ -3,10 +3,10 @@ import pexplicit.runtime.machine.eventhandlers.DeferEventHandler; import pexplicit.runtime.machine.eventhandlers.EventHandler; import pexplicit.runtime.machine.eventhandlers.IgnoreEventHandler; -import pexplicit.runtime.machine.events.PMessage; import pexplicit.runtime.machine.events.StateEvents; import pexplicit.utils.misc.Assert; import pexplicit.values.PEvent; +import pexplicit.values.PMessage; import pexplicit.values.PValue; import java.io.Serializable; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/buffer/MessageQueue.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/buffer/MessageQueue.java index 1239cc2f71..fec6afbcf1 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/buffer/MessageQueue.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/buffer/MessageQueue.java @@ -2,8 +2,8 @@ import lombok.Getter; import pexplicit.runtime.machine.PMachine; -import pexplicit.runtime.machine.events.PMessage; import pexplicit.utils.misc.Assert; +import pexplicit.values.PMessage; import java.io.Serializable; import java.util.ArrayList; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PContinuation.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PContinuation.java index 4335be93a2..6bac8eb1a9 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PContinuation.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PContinuation.java @@ -6,6 +6,7 @@ import pexplicit.utils.serialize.SerializableBiFunction; import pexplicit.utils.serialize.SerializableRunnable; import pexplicit.values.PEvent; +import pexplicit.values.PMessage; import java.util.HashSet; import java.util.Set; diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/Scheduler.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/Scheduler.java index f57bba3ef2..e0321a33d8 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/Scheduler.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/Scheduler.java @@ -6,7 +6,6 @@ import pexplicit.runtime.logger.PExplicitLogger; import pexplicit.runtime.machine.PMachine; import pexplicit.runtime.machine.PMonitor; -import pexplicit.runtime.machine.events.PMessage; import pexplicit.runtime.scheduler.explicit.StepState; import pexplicit.utils.exceptions.DeadlockException; import pexplicit.utils.exceptions.LivenessException; @@ -44,6 +43,10 @@ public abstract class Scheduler implements SchedulerInterface { @Getter @Setter protected transient int stepNumLogs = 0; + /** + * Whether last step was a sticky step (i.e., createMachine step) + */ + protected boolean isStickyStep = true; /** * Constructor @@ -85,6 +88,7 @@ protected Scheduler() { * Reset the scheduler. */ protected void reset() { + isStickyStep = true; } /** @@ -219,7 +223,8 @@ public void executeStep(PMachine sender) { // pop message from sender queue PMessage msg = sender.getSendBuffer().remove(); - if (!msg.getEvent().isCreateMachineEvent()) { + isStickyStep = msg.getEvent().isCreateMachineEvent(); + if (!isStickyStep) { // update step number stepState.setStepNumber(stepState.getStepNumber() + 1); } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/ExplicitSearchScheduler.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/ExplicitSearchScheduler.java index 808608a0e6..e7d5021c8b 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/ExplicitSearchScheduler.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/ExplicitSearchScheduler.java @@ -1,5 +1,6 @@ package pexplicit.runtime.scheduler.explicit; +import com.google.common.hash.Hashing; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -11,6 +12,7 @@ import pexplicit.runtime.machine.PMachine; import pexplicit.runtime.scheduler.Choice; import pexplicit.runtime.scheduler.Scheduler; +import pexplicit.utils.exceptions.PExplicitRuntimeException; import pexplicit.utils.misc.Assert; import pexplicit.utils.monitor.MemoryMonitor; import pexplicit.utils.monitor.TimeMonitor; @@ -181,7 +183,7 @@ protected void runStep() throws TimeoutException { boolean skipRemainingSchedule() { if (PExplicitGlobal.getConfig().getStateCachingMode() != StateCachingMode.None) { // perform state caching only if beyond backtrack choice number - if (stepState.getChoiceNumber() > backtrackChoiceNumber) { + if (!isStickyStep && stepState.getChoiceNumber() > backtrackChoiceNumber) { // increment state count SearchStatistics.totalStates++; @@ -223,18 +225,16 @@ boolean skipRemainingSchedule() { * @return */ Object getCurrentStateKey() { - Object stateKey = null; - if (PExplicitGlobal.getConfig().getStateCachingMode() == StateCachingMode.Fingerprint) { - // use fingerprinting by hashing values from each machine vars - int fingerprint = ComputeHash.getHashCode(stepState.getMachineSet()); - stateKey = fingerprint; - } else { - // use exact values from each machine vars - List> machineValues = new ArrayList<>(); - for (PMachine machine : stepState.getMachineSet()) { - machineValues.add(machine.getLocalVarValues()); - } - stateKey = machineValues; + Object stateKey; + switch (PExplicitGlobal.getConfig().getStateCachingMode()) { + case HashCode -> stateKey = ComputeHash.getHashCode(stepState.getMachineSet()); + case SipHash24 -> stateKey = ComputeHash.getHashCode(stepState.getMachineSet(), Hashing.sipHash24()); + case Murmur3_128 -> + stateKey = ComputeHash.getHashCode(stepState.getMachineSet(), Hashing.murmur3_128((int) PExplicitGlobal.getConfig().getRandomSeed())); + case Sha256 -> stateKey = ComputeHash.getHashCode(stepState.getMachineSet(), Hashing.sha256()); + case Exact -> stateKey = ComputeHash.getExactString(stepState.getMachineSet()); + default -> + throw new PExplicitRuntimeException(String.format("Unexpected state caching mode: %s", PExplicitGlobal.getConfig().getStateCachingMode())); } return stateKey; } @@ -376,6 +376,7 @@ private void postIterationCleanup() { } PExplicitLogger.logBacktrack(cIdx, newStepNumber); if (newStepNumber == 0) { + reset(); stepState.resetToZero(); } else { stepState.setTo(choice.getChoiceStep()); diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/StateCachingMode.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/StateCachingMode.java index 421548476d..03c92ab6b6 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/StateCachingMode.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/scheduler/explicit/StateCachingMode.java @@ -2,6 +2,9 @@ public enum StateCachingMode { None, - Fingerprint, + HashCode, + SipHash24, + Murmur3_128, + Sha256, Exact } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/ComputeHash.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/ComputeHash.java index 64269bb4ea..89669fc074 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/ComputeHash.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/ComputeHash.java @@ -1,7 +1,10 @@ package pexplicit.values; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; import pexplicit.runtime.machine.PMachine; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -11,6 +14,9 @@ * Static class to compute hash values */ public class ComputeHash { + public static void Initialize() { + } + /** * Compute hash value for a collection of PValues. @@ -47,7 +53,10 @@ public static int getHashCode(PMachine machine, PValue... values) { } /** - * Compute hash value for a PMachine local variables. + * Get the hash code of the protocol state using Java inbuilt hashCode() function. + * + * @param machines Sorted set of protocol machines + * @return Integer representing hash code corresponding to the protocol state */ public static int getHashCode(SortedSet machines) { int hashValue = 0x802CBBDB; @@ -59,4 +68,33 @@ public static int getHashCode(SortedSet machines) { } return hashValue; } + + /** + * Get the hash code of the protocol state given a hash function. + * + * @param machines Sorted set of protocol machines + * @param hashFunction Hash function to hash with + * @return HashCode representing protocol state hashed by the given hash function + */ + public static HashCode getHashCode(SortedSet machines, HashFunction hashFunction) { + return hashFunction.hashString(getExactString(machines), StandardCharsets.UTF_8); + } + + /** + * Get the exact protocol state as a string. + * + * @param machines Sorted set of protocol machines + * @return String representing the exact protocol state + */ + public static String getExactString(SortedSet machines) { + StringBuilder sb = new StringBuilder(); + for (PMachine machine : machines) { + sb.append(machine); + for (Object value : machine.getLocalVarValues()) { + sb.append(value); + } + } + return sb.toString(); + } + } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PBool.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PBool.java index b38b5aaa13..cbeb14dbc2 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PBool.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PBool.java @@ -16,6 +16,7 @@ public class PBool extends PValue { */ public PBool(boolean val) { value = val; + setRep(); } /** @@ -26,6 +27,7 @@ public PBool(boolean val) { public PBool(Object val) { if (val instanceof PBool) value = ((PBool) val).value; else value = (boolean) val; + setRep(); } /** @@ -35,6 +37,7 @@ public PBool(Object val) { */ public PBool(PBool val) { value = val.value; + setRep(); } /** @@ -90,8 +93,13 @@ public PBool clone() { } @Override - public int hashCode() { - return Boolean.valueOf(value).hashCode(); + protected void setHashCode() { + hashCode = Boolean.valueOf(value).hashCode(); + } + + @Override + protected void setStringRep() { + stringRep = Boolean.toString(value); } @Override @@ -102,9 +110,4 @@ else if (!(obj instanceof PBool)) { } return this.value == ((PBool) obj).value; } - - @Override - public String toString() { - return Boolean.toString(value); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEnum.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEnum.java index 71ae81ed79..87ce77d825 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEnum.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEnum.java @@ -21,6 +21,7 @@ public PEnum(String type, String name, int val) { this.type = type; this.name = name; this.value = val; + setRep(); } /** @@ -32,6 +33,7 @@ public PEnum(PEnum val) { type = val.type; name = val.name; value = val.value; + setRep(); } /** @@ -49,8 +51,13 @@ public PEnum clone() { } @Override - public int hashCode() { - return Long.hashCode(value); + protected void setHashCode() { + hashCode = Long.hashCode(value); + } + + @Override + protected void setStringRep() { + stringRep = name; } @Override @@ -61,9 +68,4 @@ else if (!(obj instanceof PEnum)) { } return this.value == ((PEnum) obj).value; } - - @Override - public String toString() { - return name; - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEvent.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEvent.java index bc51686654..d48de93f1a 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEvent.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PEvent.java @@ -28,6 +28,7 @@ public class PEvent extends PValue { */ public PEvent(String name) { this.name = name; + setRep(); } /** @@ -37,6 +38,7 @@ public PEvent(String name) { */ public PEvent(PEvent event) { this.name = event.name; + setRep(); } public boolean isCreateMachineEvent() { @@ -53,21 +55,21 @@ public PEvent clone() { } @Override - public boolean equals(Object obj) { - if (obj == this) return true; - else if (!(obj instanceof PEvent)) { - return false; - } - return this.name.equals(((PEvent) obj).name); + protected void setHashCode() { + hashCode = Objects.hash(name); } @Override - public int hashCode() { - return Objects.hash(name); + protected void setStringRep() { + stringRep = name; } @Override - public String toString() { - return name; + public boolean equals(Object obj) { + if (obj == this) return true; + else if (!(obj instanceof PEvent)) { + return false; + } + return this.name.equals(((PEvent) obj).name); } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PFloat.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PFloat.java index c1c1f5bfd9..f2d657113b 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PFloat.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PFloat.java @@ -16,6 +16,7 @@ public class PFloat extends PValue { */ public PFloat(double val) { value = val; + setRep(); } /** @@ -29,6 +30,7 @@ public PFloat(Object val) { value = ((PFloat) val).value; else value = (double) val; + setRep(); } /** @@ -38,6 +40,7 @@ public PFloat(Object val) { */ public PFloat(PFloat val) { value = val.value; + setRep(); } /** @@ -155,8 +158,13 @@ public PFloat clone() { } @Override - public int hashCode() { - return Double.valueOf(value).hashCode(); + protected void setHashCode() { + hashCode = Double.valueOf(value).hashCode(); + } + + @Override + protected void setStringRep() { + stringRep = Double.toString(value); } @Override @@ -168,9 +176,4 @@ else if (!(obj instanceof PFloat)) { } return this.value == ((PFloat) obj).value; } - - @Override - public String toString() { - return Double.toString(value); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PInt.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PInt.java index 2e92c7b74c..09cf2d5130 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PInt.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PInt.java @@ -16,6 +16,7 @@ public class PInt extends PValue { */ public PInt(int val) { value = val; + setRep(); } /** @@ -28,6 +29,7 @@ public PInt(Object val) { value = ((PInt) val).value; else value = (int) val; + setRep(); } /** @@ -37,6 +39,7 @@ public PInt(Object val) { */ public PInt(PInt val) { value = val.value; + setRep(); } /** @@ -153,8 +156,13 @@ public PInt clone() { } @Override - public int hashCode() { - return ((Integer) value).hashCode(); + protected void setHashCode() { + hashCode = ((Integer) value).hashCode(); + } + + @Override + protected void setStringRep() { + stringRep = Long.toString(value); } @Override @@ -166,9 +174,4 @@ else if (!(obj instanceof PInt)) { } return this.value == ((PInt) obj).value; } - - @Override - public String toString() { - return Long.toString(value); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMachineValue.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMachineValue.java index b2f2c3acda..85e14bc3c2 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMachineValue.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMachineValue.java @@ -19,6 +19,7 @@ public class PMachineValue extends PValue { */ public PMachineValue(PMachine val) { value = val; + setRep(); } /** @@ -39,8 +40,13 @@ public PMachineValue clone() { } @Override - public int hashCode() { - return value.hashCode(); + protected void setHashCode() { + hashCode = value.hashCode(); + } + + @Override + protected void setStringRep() { + stringRep = value.toString(); } @Override @@ -51,9 +57,4 @@ else if (!(obj instanceof PMachineValue)) { } return this.value.equals(((PMachineValue) obj).value); } - - @Override - public String toString() { - return value.toString(); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMap.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMap.java index bdb4a85731..8e8ceea7c7 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMap.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMap.java @@ -23,6 +23,7 @@ public PMap(Map, PValue> input_map) { for (Map.Entry, PValue> entry : input_map.entrySet()) { map.put(PValue.clone(entry.getKey()), PValue.clone(entry.getValue())); } + setRep(); } /** @@ -156,8 +157,26 @@ public PMap clone() { } @Override - public int hashCode() { - return ComputeHash.getHashCode(map.values()) ^ ComputeHash.getHashCode(map.keySet()); + protected void setHashCode() { + hashCode = ComputeHash.getHashCode(map.values()) ^ ComputeHash.getHashCode(map.keySet()); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + boolean hadElements = false; + for (PValue key : map.keySet()) { + if (hadElements) { + sb.append(", "); + } + sb.append(key); + sb.append("-> "); + sb.append(map.get(key)); + hadElements = true; + } + sb.append("}"); + stringRep = sb.toString(); } @Override @@ -179,22 +198,4 @@ public boolean equals(Object obj) { } return true; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("("); - boolean hadElements = false; - for (PValue key : map.keySet()) { - if (hadElements) { - sb.append(", "); - } - sb.append(key); - sb.append("-> "); - sb.append(map.get(key)); - hadElements = true; - } - sb.append(")"); - return sb.toString(); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PMessage.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMessage.java similarity index 83% rename from Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PMessage.java rename to Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMessage.java index de03689bc9..aeb32d92a7 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/runtime/machine/events/PMessage.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PMessage.java @@ -1,10 +1,7 @@ -package pexplicit.runtime.machine.events; +package pexplicit.values; import lombok.Getter; import pexplicit.runtime.machine.PMachine; -import pexplicit.values.ComputeHash; -import pexplicit.values.PEvent; -import pexplicit.values.PValue; /** * Represents a message containing details about the event, target machine, and event payload. @@ -26,6 +23,7 @@ public PMessage(PEvent event, PMachine target, PValue payload) { this.event = event; this.target = target; this.payload = payload; + setRep(); } public PMessage setTarget(PMachine target) { @@ -38,8 +36,18 @@ public PMessage clone() { } @Override - public int hashCode() { - return ComputeHash.getHashCode(target, event, payload); + protected void setHashCode() { + hashCode = ComputeHash.getHashCode(target, event, payload); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s@%s", event, target)); + if (payload != null) { + sb.append(String.format(" :payload %s", payload)); + } + stringRep = sb.toString(); } @Override @@ -58,14 +66,4 @@ public boolean equals(Object obj) { } return this.payload == other.payload; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(String.format("%s@%s", event, target)); - if (payload != null) { - sb.append(String.format(" :payload %s", payload)); - } - return sb.toString(); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PNamedTuple.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PNamedTuple.java index 0e3dea737b..207976293b 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PNamedTuple.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PNamedTuple.java @@ -27,6 +27,7 @@ public PNamedTuple(List input_fields, List> input_values) { for (int i = 0; i < input_fields.size(); i++) { values.put(input_fields.get(i), input_values.get(i)); } + setRep(); } /** @@ -39,6 +40,7 @@ public PNamedTuple(Map> input_values) { for (Map.Entry> entry : input_values.entrySet()) { values.put(entry.getKey(), PValue.clone(entry.getValue())); } + setRep(); } /** @@ -108,8 +110,26 @@ public PNamedTuple clone() { } @Override - public int hashCode() { - return ComputeHash.getHashCode(values.values()); + protected void setHashCode() { + hashCode = ComputeHash.getHashCode(values.values()); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + boolean hadElements = false; + for (String name : values.keySet()) { + if (hadElements) { + sb.append(", "); + } + sb.append(name); + sb.append(": "); + sb.append(values.get(name)); + hadElements = true; + } + sb.append(")"); + stringRep = sb.toString(); } @Override @@ -133,22 +153,4 @@ public boolean equals(Object obj) { } return true; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("("); - boolean hadElements = false; - for (String name : values.keySet()) { - if (hadElements) { - sb.append(", "); - } - sb.append(name); - sb.append(": "); - sb.append(values.get(name)); - hadElements = true; - } - sb.append(")"); - return sb.toString(); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSeq.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSeq.java index 02d7d470ba..e1b07b5a2e 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSeq.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSeq.java @@ -21,6 +21,7 @@ public PSeq(List> input_seq) { for (PValue entry : input_seq) { seq.add(PValue.clone(entry)); } + setRep(); } /** @@ -111,8 +112,22 @@ public PSeq clone() { } @Override - public int hashCode() { - return ComputeHash.getHashCode(seq); + protected void setHashCode() { + hashCode = ComputeHash.getHashCode(seq); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + String sep = ""; + for (PValue item : seq) { + sb.append(sep); + sb.append(item); + sep = ", "; + } + sb.append("]"); + stringRep = sb.toString(); } @Override @@ -135,20 +150,6 @@ public boolean equals(Object obj) { return true; } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("["); - String sep = ""; - for (PValue item : seq) { - sb.append(sep); - sb.append(item); - sep = ", "; - } - sb.append("]"); - return sb.toString(); - } - @Override public PInt size() { return new PInt(seq.size()); diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSet.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSet.java index 69526ba3b8..6a18dd6f18 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSet.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PSet.java @@ -23,6 +23,7 @@ public class PSet extends PValue implements PCollection { public PSet(List> input_set) { entries = new ArrayList<>(input_set); unique_entries = new HashSet<>(input_set); + setRep(); } /** @@ -108,8 +109,22 @@ public PSet clone() { } @Override - public int hashCode() { - return ComputeHash.getHashCode(unique_entries); + protected void setHashCode() { + hashCode = ComputeHash.getHashCode(unique_entries); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + String sep = ""; + for (PValue item : entries) { + sb.append(sep); + sb.append(item); + sep = ", "; + } + sb.append("}"); + stringRep = sb.toString(); } @Override @@ -132,20 +147,6 @@ public boolean equals(Object obj) { return true; } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("("); - String sep = ""; - for (PValue item : entries) { - sb.append(sep); - sb.append(item); - sep = ", "; - } - sb.append(")"); - return sb.toString(); - } - @Override public PInt size() { return new PInt(unique_entries.size()); diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PString.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PString.java index fc63a02e48..81e0ae184d 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PString.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PString.java @@ -32,6 +32,7 @@ public PString(String base, PValue... args) { } this.value = MessageFormat.format(base, args); } + setRep(); } /** @@ -101,8 +102,13 @@ public PString clone() { } @Override - public int hashCode() { - return value.hashCode(); + protected void setHashCode() { + hashCode = value.hashCode(); + } + + @Override + protected void setStringRep() { + stringRep = value; } @Override @@ -113,9 +119,4 @@ else if (!(obj instanceof PString)) { } return this.value.equals(((PString) obj).value); } - - @Override - public String toString() { - return value; - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PTuple.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PTuple.java index 396e1320aa..d82828b5c4 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PTuple.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PTuple.java @@ -18,6 +18,7 @@ public PTuple(PValue... input_fields) { for (int i = 0; i < input_fields.length; i++) { this.fields[i] = PValue.clone(input_fields[i]); } + setRep(); } /** @@ -28,6 +29,7 @@ public PTuple(PTuple other) { for (int i = 0; i < other.fields.length; i++) { this.fields[i] = PValue.clone(other.fields[i]); } + setRep(); } /** @@ -61,8 +63,22 @@ public PTuple clone() { } @Override - public int hashCode() { - return Arrays.hashCode(fields); + protected void setHashCode() { + hashCode = Arrays.hashCode(fields); + } + + @Override + protected void setStringRep() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + String sep = ""; + for (PValue field : fields) { + sb.append(sep); + sb.append(field); + sep = ", "; + } + sb.append(")"); + stringRep = sb.toString(); } @Override @@ -84,18 +100,4 @@ public boolean equals(Object obj) { } return true; } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("("); - String sep = ""; - for (PValue field : fields) { - sb.append(sep); - sb.append(field); - sep = ", "; - } - sb.append(")"); - return sb.toString(); - } } diff --git a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PValue.java b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PValue.java index 633caf0ef8..8f9b752d8a 100644 --- a/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PValue.java +++ b/Src/PRuntimes/PExplicitRuntime/src/main/java/pexplicit/values/PValue.java @@ -1,6 +1,7 @@ package pexplicit.values; import java.io.Serializable; +import java.util.Objects; /** * Interface that must be implemented by all P data types. @@ -8,6 +9,15 @@ * @param T is the type of P Value */ public abstract class PValue> implements Serializable { + /** + * Hash code corresponding to the PValue + */ + protected int hashCode; + /** + * String representation of the PValue + */ + protected String stringRep; + /** * Create a safe clone of the passed PValue * @@ -49,32 +59,52 @@ public static boolean notEqual(PValue val1, PValue val2) { } /** - * Function to create a deep clone of the PValue + * Returns the hash code for the PValue * - * @return deep clone of the PValue + * @return hash code */ - public abstract T clone(); + public int hashCode() { + return hashCode; + } /** - * Returns the hash code for the PValue + * Returns the string representation of the PValue * - * @return hash code + * @return string representation of the PValue */ - public abstract int hashCode(); + public String toString() { + return stringRep; + } + + protected void setRep() { +// setHashCode(); + setStringRep(); + hashCode = Objects.hashCode(stringRep); + } /** - * Checks if the current PValue is equal to the passed PValue + * Computes the hash representation for the PValue + */ + protected abstract void setHashCode(); + + /** + * Computes the string representation for the PValue + */ + protected abstract void setStringRep(); + + /** + * Function to create a deep clone of the PValue * - * @param other the other value - * @return true if the two values are equal and false otherwise + * @return deep clone of the PValue */ - public abstract boolean equals(Object other); + public abstract T clone(); /** - * Returns the string representation of the PValue + * Checks if the current PValue is equal to the passed PValue * - * @return string representation of the PValue + * @param other the other value + * @return true if the two values are equal and false otherwise */ - public abstract String toString(); + public abstract boolean equals(Object other); }