Skip to content

Commit 69d8e4f

Browse files
authored
Optimise index replacement (#227)
1 parent 8586472 commit 69d8e4f

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

gem/optimise.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -308,21 +308,25 @@ def select_expression(expressions, index):
308308
return ComponentTensor(selected, alpha)
309309

310310

311-
def delta_elimination(sum_indices, factors):
311+
def delta_elimination(sum_indices, factors, index_replacer=None):
312312
"""IndexSum-Delta cancellation.
313313
314314
:arg sum_indices: free indices for contractions
315315
:arg factors: product factors
316+
:kwarg index_replacer: MemoizerArg(filtered_replace_indices)
317+
316318
:returns: optimised (sum_indices, factors)
317319
"""
320+
if index_replacer is None:
321+
index_replacer = MemoizerArg(filtered_replace_indices)
322+
318323
sum_indices = list(sum_indices) # copy for modification
319324

320325
def substitute(expression, from_, to_):
321326
if from_ not in expression.free_indices:
322327
return expression
323328
elif isinstance(expression, Delta):
324-
mapper = MemoizerArg(filtered_replace_indices)
325-
return mapper(expression, ((from_, to_),))
329+
return index_replacer(expression, ((from_, to_),))
326330
else:
327331
return Indexed(ComponentTensor(expression, (from_,)), (to_,))
328332

@@ -490,9 +494,9 @@ def applier(expr):
490494
return partial(_renamer, rename_map, set())
491495

492496

493-
def traverse_product(expression, stop_at=None, rename_map=None):
497+
def traverse_product(expression, stop_at=None, rename_map=None, index_replacer=None):
494498
"""Traverses a product tree and collects factors, also descending into
495-
tensor contractions (IndexSum). The nominators of divisions are
499+
tensor contractions (IndexSum). The numerators of divisions are
496500
also broken up, but not the denominators.
497501
498502
:arg expression: a GEM expression
@@ -501,13 +505,17 @@ def traverse_product(expression, stop_at=None, rename_map=None):
501505
subexpression is not broken into further factors
502506
even if it is a product-like expression.
503507
:arg rename_map: an rename map for consistent index renaming
508+
:kwarg index_replacer: MemoizerArg(filtered_replace_indices)
509+
504510
:returns: (sum_indices, terms)
505511
- sum_indices: list of indices to sum over
506512
- terms: list of product terms
507513
"""
508514
if rename_map is None:
509515
rename_map = make_rename_map()
510516
renamer = make_renamer(rename_map)
517+
if index_replacer is None:
518+
index_replacer = MemoizerArg(filtered_replace_indices)
511519

512520
sum_indices = []
513521
terms = []
@@ -520,7 +528,7 @@ def traverse_product(expression, stop_at=None, rename_map=None):
520528
elif isinstance(expr, IndexSum):
521529
indices, applier = renamer(expr.multiindex)
522530
sum_indices.extend(indices)
523-
stack.extend(remove_componenttensors(map(applier, expr.children)))
531+
stack.extend(index_replacer(applier(c), ()) for c in expr.children)
524532
elif isinstance(expr, Product):
525533
stack.extend(reversed(expr.children))
526534
elif isinstance(expr, Division):
@@ -575,13 +583,18 @@ def contraction(expression, ignore=None):
575583
This routine was designed with finite element coefficient
576584
evaluation in mind.
577585
"""
586+
587+
# Common memoizer to remove ComponentTensors
588+
index_replacer = MemoizerArg(filtered_replace_indices)
589+
578590
# Eliminate annoying ComponentTensors
579-
expression, = remove_componenttensors([expression])
591+
expression = index_replacer(expression, ())
580592

581593
# Flatten product tree, eliminate deltas, sum factorise
582594
def rebuild(expression):
583-
sum_indices, factors = delta_elimination(*traverse_product(expression))
584-
factors = remove_componenttensors(factors)
595+
sum_indices, factors = traverse_product(expression, index_replacer=index_replacer)
596+
sum_indices, factors = delta_elimination(sum_indices, factors, index_replacer=index_replacer)
597+
factors = [index_replacer(f, ()) for f in factors]
585598
if ignore is not None:
586599
# TODO: This is a really blunt instrument and one might
587600
# plausibly want the ignored indices to be contracted on
@@ -610,7 +623,7 @@ def rebuild(expression):
610623
# Rebuild each split component
611624
tensor = ComponentTensor(expression, lt_fis)
612625
entries = [Indexed(tensor, zeta) for zeta in numpy.ndindex(tensor.shape)]
613-
entries = remove_componenttensors(entries)
626+
entries = [index_replacer(e, ()) for e in entries]
614627
return Indexed(ListTensor(
615628
numpy.array(list(map(rebuild, entries))).reshape(tensor.shape)
616629
), lt_fis)

0 commit comments

Comments
 (0)