|
33 | 33 | expressionDestroyerEventCounts, destroyerChoices, instantiationCounts, instantiations}, |
34 | 34 | Module[{rules, maxGeneration, maxDestroyerEvents, minEventInputs, maxEventInputs, maxEvents, init, terminationReason}, |
35 | 35 | rules = parseRules[rawRules]; |
| 36 | + ruleInputCountRanges = inputCountRange /@ rules; |
36 | 37 | {maxGeneration, maxDestroyerEvents, minEventInputs, maxEventInputs} = Values @ rawEventSelection; |
| 38 | + minEventInputs = Max[minEventInputs, Min[ruleInputCountRanges[[All, 1]]]]; |
| 39 | + maxEventInputs = Min[maxEventInputs, Max[ruleInputCountRanges[[All, 2]]]]; |
37 | 40 | parseTokenDeduplication[rawTokenDeduplication]; (* Token deduplication is not implemented at the moment *) |
38 | 41 | parseEventOrdering[rawEventOrdering]; (* Event ordering is not implemented at the moment *) |
39 | 42 | {maxEvents} = Values @ rawStoppingCondition; |
|
95 | 98 | (* Matching *) |
96 | 99 |
|
97 | 100 | findMatch[rules_, maxGeneration_, maxDestroyerEvents_, minEventInputs_, maxEventInputs_] := ModuleScope[ |
| 101 | + If[minEventInputs === Infinity || minEventInputs > maxEventInputs, Throw["Complete", $$terminationReason]]; |
98 | 102 | eventInputsCountRange = {minEventInputs, Min[maxEventInputs, expressions["Length"]]}; |
99 | 103 | subsetCount = With[{n = expressions["Length"], a = eventInputsCountRange[[1]], b = eventInputsCountRange[[2]]}, |
100 | 104 | (* Sum[Binomial[n, k], {k, a, b}] *) |
@@ -236,6 +240,85 @@ according to some (but not all) ordering functions. This new data structure will |
236 | 240 | parseRules[rawRules_] := throw[Failure["invalidMultisetRules", <|"rules" -> rawRules|>]]; |
237 | 241 | parseRules[rawRules___] /; !CheckArguments[MultisetSubstitutionSystem[rawRules], 1] := throw[Failure[None, <||>]]; |
238 | 242 |
|
| 243 | +inputCountRange[(input_ :> _) | (input_ -> _)] := inputCountRange[input]; |
| 244 | +inputCountRange[Verbatim[HoldPattern][input_List]] := |
| 245 | + Total[Append[ReleaseHold @ Map[sequencePatternLengthRange, Hold[input], {2}], {0, 0}]]; |
| 246 | +inputCountRange[input_List] := inputCountRange[HoldPattern[input]]; |
| 247 | +inputCountRange[Verbatim[Alternatives][patterns__]] := MinMax[inputCountRange /@ {patterns}]; |
| 248 | +inputCountRange[(Verbatim[Condition] | Verbatim[PatternTest])[input_, _]] := inputCountRange[input]; |
| 249 | +inputCountRange[Verbatim[Pattern][_, obj_]] := inputCountRange[obj]; |
| 250 | +inputCountRange[Verbatim[Except][_, p_]] := inputCountRange[p]; |
| 251 | +inputCountRange[Verbatim[Verbatim][p_List]] := ConstantArray[Length[p], 2]; |
| 252 | +inputCountRange[_] := {0, Infinity}; |
| 253 | + |
| 254 | +(* We need to hold the pattern from now on because sequencePatternLengthRange may be called from inside HoldPattern. *) |
| 255 | + |
| 256 | +Attributes[sequencePatternLengthRange] := {HoldFirst}; |
| 257 | + |
| 258 | +(* Here we enumerate all possible WL pattern constructs from https://reference.wolfram.com/language/guide/Patterns.html. |
| 259 | + If a pattern construct has incorrect syntax, we return {Infinity, 0}, which means nothing can be matched. *) |
| 260 | + |
| 261 | +sequencePatternLengthRange[Verbatim[Pattern][_, obj_]] := sequencePatternLengthRange[obj]; |
| 262 | +sequencePatternLengthRange[Verbatim[Pattern][___]] := {Infinity, 0}; |
| 263 | + |
| 264 | +sequencePatternLengthRange[_Blank] := {1, 1}; |
| 265 | +sequencePatternLengthRange[_BlankSequence] := {1, Infinity}; |
| 266 | +sequencePatternLengthRange[_BlankNullSequence] := {0, Infinity}; |
| 267 | +sequencePatternLengthRange[Verbatim[Alternatives][p__]] := |
| 268 | + MinMax[ReleaseHold @ Map[sequencePatternLengthRange, Hold[{p}], {2}]]; |
| 269 | +sequencePatternLengthRange[Verbatim[Alternatives][]] := {Infinity, 0}; (* this does not match to anything *) |
| 270 | + |
| 271 | +zeroPreferenceProduct[0, _] := 0; |
| 272 | +zeroPreferenceProduct[_, 0] := 0; |
| 273 | +zeroPreferenceProduct[a_, b_] := a * b; |
| 274 | +zeroPreferenceProduct[{a_, b_}, {c_, d_}] := {zeroPreferenceProduct[a, c], zeroPreferenceProduct[b, d]}; |
| 275 | + |
| 276 | +sequencePatternLengthRange[Verbatim[Repeated][p_]] := {Min @ sequencePatternLengthRange[p], Infinity}; |
| 277 | +sequencePatternLengthRange[Verbatim[RepeatedNull][_]] := {0, Infinity}; |
| 278 | +sequencePatternLengthRange[Verbatim[Repeated][p_, max_]] := |
| 279 | + zeroPreferenceProduct[{1, max}, sequencePatternLengthRange[p]]; |
| 280 | +sequencePatternLengthRange[Verbatim[RepeatedNull][p_, max_]] := |
| 281 | + {0, zeroPreferenceProduct[max, Max @ sequencePatternLengthRange[p]]}; |
| 282 | +sequencePatternLengthRange[(Verbatim[Repeated] | Verbatim[RepeatedNull])[p_, {min_, max_}]] := |
| 283 | + zeroPreferenceProduct[{min, max}, sequencePatternLengthRange[p]]; |
| 284 | +sequencePatternLengthRange[(Verbatim[Repeated] | Verbatim[RepeatedNull])[p_, {n_}]] := |
| 285 | + zeroPreferenceProduct[{n, n}, sequencePatternLengthRange[p]]; |
| 286 | +sequencePatternLengthRange[Verbatim[Repeated][___]] := {Infinity, 0}; |
| 287 | +sequencePatternLengthRange[Verbatim[RepeatedNull][___]] := {Infinity, 0}; |
| 288 | + |
| 289 | +(* Variable-length sequences are not allowed as a second argument to Except. *) |
| 290 | +sequencePatternLengthRange[_Except] := {1, 1}; |
| 291 | + |
| 292 | +sequencePatternLengthRange[Verbatim[Longest][p_]] := sequencePatternLengthRange[p]; |
| 293 | +sequencePatternLengthRange[Verbatim[Longest][___]] := {Infinity, 0}; |
| 294 | +sequencePatternLengthRange[Verbatim[Shortest][p_]] := sequencePatternLengthRange[p]; |
| 295 | +sequencePatternLengthRange[Verbatim[Shortest][___]] := {Infinity, 0}; |
| 296 | + |
| 297 | +sequencePatternLengthRange[_OptionsPattern] := {0, Infinity}; |
| 298 | + |
| 299 | +sequencePatternLengthRange[(Verbatim[PatternSequence] | Verbatim[OrderlessPatternSequence])[ps___]] := |
| 300 | + Total[Append[ReleaseHold @ Map[sequencePatternLengthRange, Hold[{ps}], {2}], {0, 0}]]; |
| 301 | + |
| 302 | +sequencePatternLengthRange[_Verbatim] := {1, 1}; |
| 303 | + |
| 304 | +sequencePatternLengthRange[Verbatim[HoldPattern][p_]] := sequencePatternLengthRange[p]; |
| 305 | +sequencePatternLengthRange[Verbatim[HoldPattern][___]] := {Infinity, 0}; |
| 306 | + |
| 307 | +sequencePatternLengthRange[_KeyValuePattern] := {1, 1}; |
| 308 | + |
| 309 | +sequencePatternLengthRange[Verbatim[Condition][p_, _]] := sequencePatternLengthRange[p]; |
| 310 | +sequencePatternLengthRange[Verbatim[Condition][___]] := {Infinity, 0}; |
| 311 | + |
| 312 | +sequencePatternLengthRange[Verbatim[PatternTest][p_, _]] := sequencePatternLengthRange[p]; |
| 313 | +sequencePatternLengthRange[Verbatim[PatternTest][___]] := {Infinity, 0}; |
| 314 | + |
| 315 | +sequencePatternLengthRange[Verbatim[Optional][p_, _]] := {0, Max @ sequencePatternLengthRange[p]}; |
| 316 | +sequencePatternLengthRange[Verbatim[Optional][___]] := {Infinity, 0}; |
| 317 | + |
| 318 | +(* Since we have enumerated all pattern constructs above, this case does not correspond to a pattern. |
| 319 | + However, the completeness of checks above needs to be checked for every new WL version. *) |
| 320 | +sequencePatternLengthRange[_] := If[$VersionNumber <= 12.3, {1, 1}, {0, Infinity}]; |
| 321 | + |
239 | 322 | parseTokenDeduplication[None] := None; |
240 | 323 | declareMessage[General::multisetTokenDeduplicationNotImplemented, |
241 | 324 | "Token deduplication is not implemented for Multiset Substitution System."]; |
|
0 commit comments