Skip to content

Commit b3b6d33

Browse files
authored
Move TimeConstrained from setSubstitutionSystem$cpp to libSetReplace (#647)
## Changes * Moves `TimeConstrained[...]` from `setSubstitutionSystem$cpp[...]` to inside `HypergraphSubstitutionSystem.cpp` in `libSetReplace`. * Adds a new `TerminationReasonCode`: `8 -> "TimeConstrained"`. ## Comments * `AbsoluteTiming` doesn't really match the time constraint: ```wl In[] := WolframModel[ {{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, Infinity, TimeConstraint -> 1] // AbsoluteTiming // First Out[] = 2.61478 ``` ## Examples ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, Infinity, TimeConstraint -> 1] ``` ![image](https://user-images.githubusercontent.com/40190339/118748655-b54bb000-b821-11eb-8b80-84c04b004e05.png) ```wl In[] := %["TerminationReason"] Out[] = "TimeConstraint" ``` <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/maxitg/setreplace/647) <!-- Reviewable:end -->
1 parent 37af637 commit b3b6d33

4 files changed

Lines changed: 74 additions & 33 deletions

File tree

Kernel/setSubstitutionSystem$cpp.m

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
importLibSetReplaceFunction[
2121
"hypergraphSubstitutionSystemReplace" -> cpp$setReplace,
2222
{Integer, (* set ID *)
23-
{Integer, 1, "Constant"}}, (* {events, generations, atoms, max expressions per atom, expressions} *)
23+
{Integer, 1, "Constant"}, (* {events, generations, atoms, max expressions per atom, expressions} *)
24+
Real}, (* time constraint *)
2425
"Void"];
2526

2627
importLibSetReplaceFunction[
@@ -114,7 +115,8 @@
114115
4 -> $maxFinalVertexDegree,
115116
5 -> $maxFinalExpressions,
116117
6 -> $fixedPoint,
117-
7 -> $Aborted
118+
7 -> $Aborted,
119+
8 -> $timeConstraint
118120
|>;
119121

120122
(* GlobalSpacelike is syntactic sugar for "EventSelectionFunction" -> "MultiwaySpacelike", "MaxDestroyerEvents" -> 1 *)
@@ -174,24 +176,30 @@
174176
Replace[eventDeduplication, $eventDeduplicationCodes],
175177
IntegerDigits[RandomInteger[{0, $maxUInt32}], 2^16, 2]
176178
];
177-
TimeConstrained[
178-
CheckAbort[
179-
cpp$setReplace[
180-
setID,
181-
stepSpec /@ {
182-
$maxEvents, $maxGenerationsLocal, $maxFinalVertices, $maxFinalVertexDegree, $maxFinalExpressions} /.
183-
{Infinity | (_ ? MissingQ) -> $unset}],
184-
If[!returnOnAbortQ, Abort[], terminationReason = $Aborted]],
185-
timeConstraint,
186-
If[!returnOnAbortQ, Return[$Aborted], terminationReason = $timeConstraint]];
179+
180+
CheckAbort[
181+
cpp$setReplace[
182+
setID,
183+
stepSpec /@ {
184+
$maxEvents, $maxGenerationsLocal, $maxFinalVertices, $maxFinalVertexDegree, $maxFinalExpressions} /.
185+
{Infinity | (_ ? MissingQ) -> $unset},
186+
timeConstraint /. Infinity -> $unset]
187+
,
188+
If[!returnOnAbortQ, Abort[]]
189+
];
190+
191+
terminationReason = $terminationReasonCodes[cpp$terminationReason[setID]];
192+
If[(terminationReason === $timeConstraint) && !returnOnAbortQ, Return @ $Aborted];
193+
terminationReason = Replace[terminationReason, $notTerminated -> $timeConstraint];
194+
187195
numericAtomLists = decodeAtomLists[cpp$setExpressions[setID]];
188196
events = decodeEvents[cpp$setEvents[setID]];
189197
maxCompleteGeneration = CheckAbort[
190-
Replace[cpp$maxCompleteGeneration[setID], LibraryFunctionError[___] -> Missing["Unknown", $Aborted]],
191-
If[!returnOnAbortQ, Abort[], terminationReason = $Aborted; Missing["Unknown", $Aborted]]];
192-
terminationReason = Replace[$terminationReasonCodes[cpp$terminationReason[setID]], {
193-
$Aborted -> terminationReason,
194-
$notTerminated -> $timeConstraint}];
198+
Replace[cpp$maxCompleteGeneration[setID], LibraryFunctionError[___] -> Missing["Unknown", $Aborted]]
199+
,
200+
If[!returnOnAbortQ, Abort[], Missing["Unknown", $Aborted]]
201+
];
202+
195203
resultAtoms = Union[Catenate[numericAtomLists]];
196204
inversePartialGlobalMap = Association[Reverse /@ Normal @ globalIndex];
197205
inverseGlobalMap = Association @ Thread[resultAtoms

libSetReplace/HypergraphSubstitutionSystem.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class HypergraphSubstitutionSystem::Implementation {
5656
return causalGraph_.tokenSeparation(first, second);
5757
}) {}
5858

59-
int64_t replaceOnce(const std::function<bool()> shouldAbort, bool resetStepSpec = false) {
59+
int64_t replaceOnce(const std::function<bool()> shouldAbortOrTimeOut, bool resetStepSpec = false) {
6060
if (resetStepSpec) {
6161
updateStepSpec(StepSpecification{});
6262
}
@@ -67,11 +67,7 @@ class HypergraphSubstitutionSystem::Implementation {
6767
return 0;
6868
}
6969

70-
indexNewTokens([this, &shouldAbort]() {
71-
const bool isAborted = shouldAbort();
72-
if (isAborted) terminationReason_ = TerminationReason::Aborted;
73-
return isAborted;
74-
});
70+
indexNewTokens(shouldAbortOrTimeOut);
7571
if (matcher_.empty()) {
7672
if (causalGraph_.largestGeneration() == stepSpec_.maxGenerationsLocal) {
7773
terminationReason_ = TerminationReason::MaxGenerationsLocal;
@@ -130,14 +126,35 @@ class HypergraphSubstitutionSystem::Implementation {
130126
return 1;
131127
}
132128

133-
int64_t replace(const StepSpecification stepSpec, const std::function<bool()>& shouldAbort) {
129+
int64_t replace(const StepSpecification stepSpec,
130+
const std::function<bool()>& shouldAbort,
131+
std::chrono::steady_clock::duration const timeConstraint) {
134132
updateStepSpec(stepSpec);
135133
int64_t count = 0;
136134
if (maxDestroyerEvents_ == 0) {
137135
return count;
138136
}
137+
138+
auto startTime = std::chrono::steady_clock::now();
139+
const std::function<bool()> shouldTimeOut = [startTime, timeConstraint]() {
140+
return (std::chrono::steady_clock::now() - startTime) > timeConstraint;
141+
};
142+
143+
const std::function<bool()> shouldAbortOrTimeOut = [this, &shouldAbort, &shouldTimeOut]() {
144+
if (shouldAbort()) {
145+
terminationReason_ = TerminationReason::Aborted;
146+
return true;
147+
}
148+
if (shouldTimeOut()) {
149+
terminationReason_ = TerminationReason::TimeConstrained;
150+
return true;
151+
}
152+
153+
return false;
154+
};
155+
139156
while (true) {
140-
if (replaceOnce(shouldAbort)) {
157+
if (replaceOnce(shouldAbortOrTimeOut)) {
141158
++count;
142159
} else {
143160
return count;
@@ -402,8 +419,9 @@ int64_t HypergraphSubstitutionSystem::replaceOnce(const std::function<bool()>& s
402419
}
403420

404421
int64_t HypergraphSubstitutionSystem::replace(const StepSpecification& stepSpec,
405-
const std::function<bool()>& shouldAbort) {
406-
return implementation_->replace(stepSpec, shouldAbort);
422+
const std::function<bool()>& shouldAbort,
423+
std::chrono::steady_clock::duration const timeConstraint) {
424+
return implementation_->replace(stepSpec, shouldAbort, timeConstraint);
407425
}
408426

409427
std::vector<AtomsVector> HypergraphSubstitutionSystem::tokens() const { return implementation_->tokens(); }

libSetReplace/HypergraphSubstitutionSystem.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef LIBSETREPLACE_HYPERGRAPHSUBSTITUTIONSYSTEM_HPP_
22
#define LIBSETREPLACE_HYPERGRAPHSUBSTITUTIONSYSTEM_HPP_
33

4+
#include <chrono>
45
#include <functional>
56
#include <limits>
67
#include <memory>
@@ -29,6 +30,9 @@ class HypergraphSubstitutionSystem {
2930

3031
static constexpr int64_t stepLimitDisabled = std::numeric_limits<int64_t>::max();
3132

33+
static constexpr std::chrono::steady_clock::duration timeConstraintDisabled =
34+
std::chrono::steady_clock::duration::max();
35+
3236
/** @brief Specification of conditions upon which to stop evaluation.
3337
* @details Each of these is UpTo, i.e., the evaluation is terminated when the first of these, fixed point, or an
3438
* abort is reached.
@@ -59,7 +63,8 @@ class HypergraphSubstitutionSystem {
5963
MaxFinalAtomDegree = 4,
6064
MaxFinalTokens = 5,
6165
Complete = 6,
62-
Aborted = 7
66+
Aborted = 7,
67+
TimeConstrained = 8,
6368
};
6469

6570
/** @brief Creates a new hypergraph system with given evaluation rules, and initial condition.
@@ -78,17 +83,20 @@ class HypergraphSubstitutionSystem {
7883
unsigned int randomSeed = 0);
7984

8085
/** @brief Perform a single substitution, create the corresponding event, and output tokens.
81-
* @param shouldAbort function that should return true if abort is requested.
86+
* @param shouldAbortOrTimeOut function that should return true if abort is requested or the evolution timed out.
8287
* @return 1 if substitution was made, 0 if no matches were found.
8388
*/
84-
int64_t replaceOnce(const std::function<bool()>& shouldAbort);
89+
int64_t replaceOnce(const std::function<bool()>& shouldAbortOrTimeOut);
8590

8691
/** @brief Run replaceOnce() stepSpec.maxEvents times, or until the next token violates constraints imposed by
8792
* stepSpec.
8893
* @param shouldAbort function that should return true if abort is requested.
94+
* @param timeConstraint number of seconds before timing out the evolution.
8995
* @return The number of subtitutions made, could be between 0 and stepSpec.maxEvents.
9096
*/
91-
int64_t replace(const StepSpecification& stepSpec, const std::function<bool()>& shouldAbort);
97+
int64_t replace(const StepSpecification& stepSpec,
98+
const std::function<bool()>& shouldAbort,
99+
std::chrono::steady_clock::duration const timeConstraint = timeConstraintDisabled);
92100

93101
/** @brief List of all tokens in the system, past and present.
94102
*/

libSetReplace/WolframLanguageAPI.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ int hypergraphSubstitutionSystemReplace(WolframLibraryData libData,
296296
mint argc,
297297
MArgument* argv,
298298
[[maybe_unused]] MArgument result) {
299-
if (argc != 2) {
299+
if (argc != 3) {
300300
return LIBRARY_FUNCTION_ERROR;
301301
}
302302

@@ -308,8 +308,15 @@ int hypergraphSubstitutionSystemReplace(WolframLibraryData libData,
308308
return LIBRARY_FUNCTION_ERROR;
309309
}
310310

311+
const double timeConstraintWL = MArgument_getReal(argv[2]);
312+
auto timeConstraint = HypergraphSubstitutionSystem::timeConstraintDisabled;
313+
if (timeConstraintWL > 0) {
314+
timeConstraint = std::chrono::duration_cast<std::chrono::steady_clock::duration>(
315+
std::chrono::duration<double>(timeConstraintWL));
316+
}
317+
311318
try {
312-
hypergraphSubstitutionSystemFromID(systemID).replace(stepSpec, shouldAbort(libData));
319+
hypergraphSubstitutionSystemFromID(systemID).replace(stepSpec, shouldAbort(libData), timeConstraint);
313320
} catch (...) {
314321
return LIBRARY_FUNCTION_ERROR;
315322
}

0 commit comments

Comments
 (0)