Skip to content

Commit

Permalink
fix 1260
Browse files Browse the repository at this point in the history
  • Loading branch information
mmatera committed Apr 12, 2021
1 parent 0ac118c commit ca87528
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Enhancements
* ``ToString`` accepts an optional *form* parameter.
* ``ToExpression`` handles multi-line string input
* ``FileNames`` returns a sorted list (#1250).
* ``ReplaceRepeated`` and ``FixedPoint`` now supports the ``MaxIteration`` option (#1260).
* ``FixedPoint`` now supports the ``SameTest`` option.

Bug fixes
+++++++++
Expand Down
33 changes: 27 additions & 6 deletions mathics/builtin/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ class FixedPoint(Builtin):
<dt>'FixedPoint[$f$, $expr$]'
<dd>starting with $expr$, iteratively applies $f$ until the result no longer changes.
<dt>'FixedPoint[$f$, $expr$, $n$]'
<dd>performs at most $n$ iterations.
<dd>performs at most $n$ iterations. The same that using $MaxIterations->n$
</dl>
>> FixedPoint[Cos, 1.0]
Expand All @@ -524,24 +524,45 @@ class FixedPoint(Builtin):
= 0.739085
"""

def apply(self, f, expr, n, evaluation):
"FixedPoint[f_, expr_, n_:DirectedInfinity[1]]"
options = {'MaxIterations': 'Infinity',
"SameTest": "Automatic",
}

def apply(self, f, expr, n, evaluation, options):
"FixedPoint[f_, expr_, n_:DirectedInfinity[1], OptionsPattern[FixedPoint]]"
if n == Expression("DirectedInfinity", 1):
count = None
else:
count = n.get_int_value()
if count is None or count < 0:
evaluation.message("FixedPoint", "intnn")
return

if count is None:
count = self.get_option(options, "MaxIterations", evaluation)
if count.is_numeric():
count = count.get_int_value()
else:
count = None

result = expr
index = 0
sametest = self.get_option(options, "SameTest", evaluation)
if sametest == Symbol("Automatic"):
sametest = None

while count is None or index < count:
evaluation.check_stopped()
new_result = Expression(f, result).evaluate(evaluation)
if new_result == result:
result = new_result
break
if sametest:
same = Expression(sametest, result, new_result).evaluate(evaluation)
same = same.is_true()
if same:
break
else:
if new_result == result:
result = new_result
break
result = new_result
index += 1

Expand Down
19 changes: 16 additions & 3 deletions mathics/builtin/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,11 @@ class ReplaceRepeated(BinaryOperator):
"rmix": "Elements of `1` are a mixture of lists and nonlists.",
}

def apply_list(self, expr, rules, evaluation):
"ReplaceRepeated[expr_, rules_]"
options = {'MaxIterations': 'Infinity',
"Heads": "False"}

def apply_list(self, expr, rules, evaluation, options):
"ReplaceRepeated[expr_, rules_, OptionsPattern[ReplaceRepeated]]"
try:
rules, ret = create_rules(rules, expr, "ReplaceRepeated", evaluation)
except PatternError:
Expand All @@ -335,9 +338,19 @@ def apply_list(self, expr, rules, evaluation):
if ret:
return rules

heads = self.get_option(options, "Heads", evaluation).is_true()
maxit = self.get_option(options, "MaxIterations", evaluation)
if maxit.is_numeric():
maxit = maxit.get_int_value()
else:
maxit = -1

while True:
evaluation.check_stopped()
result, applied = expr.apply_rules(rules, evaluation)
if maxit == 0:
break
maxit -= 1
result, applied = expr.apply_rules(rules, evaluation, options={"heads": heads,})
if applied:
result = result.evaluate(evaluation)
if applied and not result.sameQ(expr):
Expand Down

0 comments on commit ca87528

Please sign in to comment.