Skip to content

Commit c2afe31

Browse files
authored
Merge pull request #1269 from mathics/fix1260
fix 1260
2 parents eb71f33 + 106df9d commit c2afe31

3 files changed

Lines changed: 54 additions & 8 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Enhancements
1818
* ``ToString`` accepts an optional *form* parameter.
1919
* ``ToExpression`` handles multi-line string input
2020
* ``FileNames`` returns a sorted list (#1250).
21+
* ``ReplaceRepeated`` and ``FixedPoint`` now supports the ``MaxIteration`` option (#1260).
22+
* ``FixedPoint`` now supports the ``SameTest`` option.
2123

2224
Bug fixes
2325
+++++++++

mathics/builtin/control.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ class FixedPoint(Builtin):
506506
<dt>'FixedPoint[$f$, $expr$]'
507507
<dd>starting with $expr$, iteratively applies $f$ until the result no longer changes.
508508
<dt>'FixedPoint[$f$, $expr$, $n$]'
509-
<dd>performs at most $n$ iterations.
509+
<dd>performs at most $n$ iterations. The same that using $MaxIterations->n$
510510
</dl>
511511
512512
>> FixedPoint[Cos, 1.0]
@@ -524,24 +524,46 @@ class FixedPoint(Builtin):
524524
= 0.739085
525525
"""
526526

527-
def apply(self, f, expr, n, evaluation):
528-
"FixedPoint[f_, expr_, n_:DirectedInfinity[1]]"
527+
options = {
528+
"MaxIterations": "Infinity",
529+
"SameTest": "Automatic",
530+
}
529531

532+
def apply(self, f, expr, n, evaluation, options):
533+
"FixedPoint[f_, expr_, n_:DirectedInfinity[1], OptionsPattern[FixedPoint]]"
530534
if n == Expression("DirectedInfinity", 1):
531535
count = None
532536
else:
533537
count = n.get_int_value()
534538
if count is None or count < 0:
535539
evaluation.message("FixedPoint", "intnn")
536540
return
541+
542+
if count is None:
543+
count = self.get_option(options, "MaxIterations", evaluation)
544+
if count.is_numeric():
545+
count = count.get_int_value()
546+
else:
547+
count = None
548+
537549
result = expr
538550
index = 0
551+
sametest = self.get_option(options, "SameTest", evaluation)
552+
if sametest == Symbol("Automatic"):
553+
sametest = None
554+
539555
while count is None or index < count:
540556
evaluation.check_stopped()
541557
new_result = Expression(f, result).evaluate(evaluation)
542-
if new_result == result:
543-
result = new_result
544-
break
558+
if sametest:
559+
same = Expression(sametest, result, new_result).evaluate(evaluation)
560+
same = same.is_true()
561+
if same:
562+
break
563+
else:
564+
if new_result == result:
565+
result = new_result
566+
break
545567
result = new_result
546568
index += 1
547569

mathics/builtin/patterns.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ class ReplaceRepeated(BinaryOperator):
305305
>> a+b+c //. c->d
306306
= a + b + d
307307
308+
>> f = ReplaceRepeated[c->d];
309+
>> f[a+b+c]
310+
= a + b + d
311+
>> Clear[f];
312+
308313
Simplification of logarithms:
309314
>> logrules = {Log[x_ * y_] :> Log[x] + Log[y], Log[x_ ^ y_] :> y * Log[x]};
310315
>> Log[a * (b * c) ^ d ^ e * f] //. logrules
@@ -324,8 +329,16 @@ class ReplaceRepeated(BinaryOperator):
324329
"rmix": "Elements of `1` are a mixture of lists and nonlists.",
325330
}
326331

327-
def apply_list(self, expr, rules, evaluation):
328-
"ReplaceRepeated[expr_, rules_]"
332+
options = {
333+
"MaxIterations": "65535",
334+
}
335+
336+
rules = {
337+
"ReplaceRepeated[rules_][expr_]": "ReplaceRepeated[expr, rules]",
338+
}
339+
340+
def apply_list(self, expr, rules, evaluation, options):
341+
"ReplaceRepeated[expr_, rules_, OptionsPattern[ReplaceRepeated]]"
329342
try:
330343
rules, ret = create_rules(rules, expr, "ReplaceRepeated", evaluation)
331344
except PatternError:
@@ -335,8 +348,17 @@ def apply_list(self, expr, rules, evaluation):
335348
if ret:
336349
return rules
337350

351+
maxit = self.get_option(options, "MaxIterations", evaluation)
352+
if maxit.is_numeric():
353+
maxit = maxit.get_int_value()
354+
else:
355+
maxit = -1
356+
338357
while True:
339358
evaluation.check_stopped()
359+
if maxit == 0:
360+
break
361+
maxit -= 1
340362
result, applied = expr.apply_rules(rules, evaluation)
341363
if applied:
342364
result = result.evaluate(evaluation)

0 commit comments

Comments
 (0)