/usr/lib/python2.7/dist-packages/ufl/exprequals.py is in python-ufl 1.3.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | from ufl.operatorbase import Operator
from ufl.terminal import Terminal
from ufl.common import fast_pre_traversal
def _expr_equals0(a, b): # TODO: Which is faster?
# Cutoff for different type
if type(a) != type(b):
return False
# Cutoff for same object
if a is b:
return True
# Iterate over pairs of potentially matching subexpressions
input = [(a, b)]
while input:
a, b = input.pop()
# Cutoff for different type
if type(a) != type(b):
return False
# Get operands
aops = a.operands()
bops = b.operands()
if aops:
if len(aops) != len(bops):
return False
# Add children for checking
input.extend(izip(aops, bops))
else:
# Compare terminals
if not a == b:
return False
# Everything checked out fine, expressions must be equal
return True
def _expr_equals1(a, b): # TODO: Which is faster?
# Cutoff for different type
if type(a) != type(b):
return False
# Cutoff for same object
if a is b:
return True
# Compare entire expression structure
for x,y in izip(fast_pre_traversal(a), fast_pre_traversal(b)):
if type(x) != type(y):
return False
#if isinstance(Terminal, x) and not x == y:
if x.operands() == () and not x == y:
return False
# Equal terminals and types, a and b must be equal
return True
def _expr_equals2(a, b):
# Cutoff for different type
if type(a) != type(b):
return False
# Cutoff for same object
if a is b:
return True
from ufl.algorithms.traversal import traverse_terminals, traverse_operands
# Check for equal terminals
for x,y in izip(traverse_terminals(a), traverse_terminals(b)):
if x != y:
return False
# Check for matching operator types
for x,y in izip(traverse_operands(a), traverse_operands(b)):
if type(x) != type(y):
return False
# Equal terminals and operands, a and b must be equal
return True
equalsrecursed = {}
equalscalls = {}
collisions = {}
def print_collisions():
print
print "Collision statistics:"
keys = sorted(equalscalls.keys(), key=lambda x: collisions.get(x,0))
for k in keys:
co = collisions.get(k,0)
ca = equalscalls[k]
print k, co, ca, int(100.0*co/ca)
print "Recursion statistics:"
keys = sorted(keys, key=lambda x: equalsrecursed.get(x,0))
for k in keys:
r = equalsrecursed.get(k,0)
ca = equalscalls[k]
print k, r, ca, int(100.0*r/ca)
print
def _expr_equals3(self, other): # Much faster than the more complex algorithms above!
"""Checks whether the two expressions are represented the
exact same way. This does not check if the expressions are
mathematically equal or equivalent! Used by sets and dicts."""
# Code for counting number of equals calls:
#equalscalls[type(self)] = equalscalls.get(type(self),0) + 1
# Fast cutoff for common case
if type(self) != type(other):
return False
# TODO: Test how this affects the run time:
# Compare hashes if hash is cached
# (NB! never access _hash directly, it may be computed on demand in __hash__)
if (hasattr(self, "_hash") and hash(self) != hash(other)):
return False
# Large objects are costly to compare with themselves
if self is other:
return True
if isinstance(self, Operator):
# Just let python handle the recursion
#equal = self.operands() == other.operands()
# Recurse manually to call _expr_equals3 directly without the class EQ overhead!
equal = all(_expr_equals3(a, b) for (a,b) in zip(self.operands(), other.operands()))
else:
# Compare terminal representations to include all terminal data
#equal = repr(self) == repr(other)
# Compare terminals with custom == to capture subclass overloading of __eq__
equal = self == other
# At this point, self and other has the same hash, and equal _should_ be True...
# Code for measuring amount of collisions:
#if not equal:
# collisions[type(self)] = collisions.get(type(self), 0) + 1
# Code for counting number of recursive calls:
#equalsrecursed[type(self)] = equalsrecursed.get(type(self),0) + 1
# Debugging check: (has been enabled for a long while without any fails as of nov. 30th 2012
#req = repr(self) == repr(other)
#if req != equal: # This may legally fail for test/trial functions from PyDOLFIN
# print '\n'*3
# print self
# print other
# print '\n'*3
# ufl_error("INVALID COMPARISON!")
return equal
expr_equals = _expr_equals3
|