提交 b4181fcb authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Remove more support for python < 2.6

上级 7540e33a
...@@ -4,15 +4,15 @@ from theano.compat import cmp, defaultdict ...@@ -4,15 +4,15 @@ from theano.compat import cmp, defaultdict
# {{{ http://code.activestate.com/recipes/578231/ (r1) # {{{ http://code.activestate.com/recipes/578231/ (r1)
# Copyright (c) Oren Tirosh 2012 # Copyright (c) Oren Tirosh 2012
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of # Permission is hereby granted, free of charge, to any person obtaining a copy
# this software and associated documentation files (the "Software"), to deal in # of this software and associated documentation files (the "Software"), to deal
# the Software without restriction, including without limitation the rights to # in the Software without restriction, including without limitation the rights
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# of the Software, and to permit persons to whom the Software is furnished to do # copies of the Software, and to permit persons to whom the Software is
# so, subject to the following conditions: # furnished to do so, subject to the following conditions:
# #
# The above copyright notice and this permission notice shall be included in all # The above copyright notice and this permission notice shall be included in
# copies or substantial portions of the Software. # all copies or substantial portions of the Software.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
...@@ -30,6 +30,7 @@ def memodict(f): ...@@ -30,6 +30,7 @@ def memodict(f):
ret = self[key] = f(key) ret = self[key] = f(key)
return ret return ret
return memodict().__getitem__ return memodict().__getitem__
# end of http://code.activestate.com/recipes/578231/ }}} # end of http://code.activestate.com/recipes/578231/ }}}
......
...@@ -14,248 +14,176 @@ def check_deterministic(iterable): ...@@ -14,248 +14,176 @@ def check_deterministic(iterable):
assert isinstance(iterable, ( assert isinstance(iterable, (
list, tuple, OrderedSet, types.GeneratorType, basestring)) list, tuple, OrderedSet, types.GeneratorType, basestring))
if MutableSet is not None: # Copyright (C) 2009 Raymond Hettinger
# Copyright (C) 2009 Raymond Hettinger # Permission is hereby granted, free of charge, to any person obtaining a
# Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the
# copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including
# "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish,
# without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to permit
# distribute, sublicense, and/or sell copies of the Software, and to permit # persons to whom the Software is furnished to do so, subject to the
# persons to whom the Software is furnished to do so, subject to the # following conditions:
# following conditions:
# The above copyright notice and this permission notice shall be included
# The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software.
# in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # {{{ http://code.activestate.com/recipes/576696/ (r5)
# {{{ http://code.activestate.com/recipes/576696/ (r5) import weakref
import collections
import weakref class Link(object):
# This make that we need to use a different pickle protocol
class Link(object): # then the default. Othewise, there is pickling errors
# This make that we need to use a different pickle protocol __slots__ = 'prev', 'next', 'key', '__weakref__'
# then the default. Othewise, there is pickling errors
__slots__ = 'prev', 'next', 'key', '__weakref__' def __getstate__(self):
# weakref.proxy don't pickle well, so we use weakref.ref
def __getstate__(self): # manually and don't pickle the weakref.
# weakref.proxy don't pickle well, so we use weakref.ref # We restore the weakref when we unpickle.
# manually and don't pickle the weakref. ret = [self.prev(), self.next()]
# We restore the weakref when we unpickle. try:
ret = [self.prev(), self.next()] ret.append(self.key)
try: except AttributeError:
ret.append(self.key) pass
except AttributeError: return ret
pass
return ret def __setstate__(self, state):
self.prev = weakref.ref(state[0])
def __setstate__(self, state): self.next = weakref.ref(state[1])
self.prev = weakref.ref(state[0]) if len(state) == 3:
self.next = weakref.ref(state[1]) self.key = state[2]
if len(state) == 3:
self.key = state[2] class OrderedSet(MutableSet):
'Set the remembers the order elements were added'
class OrderedSet(collections.MutableSet): # Big-O running times for all methods are the same as for regular sets.
'Set the remembers the order elements were added' # The internal self.__map dictionary maps keys to links in a doubly linked list.
# Big-O running times for all methods are the same as for regular sets. # The circular doubly linked list starts and ends with a sentinel element.
# The internal self.__map dictionary maps keys to links in a doubly linked list. # The sentinel element never gets deleted (this simplifies the algorithm).
# The circular doubly linked list starts and ends with a sentinel element. # The prev/next links are weakref proxies (to prevent circular references).
# The sentinel element never gets deleted (this simplifies the algorithm). # Individual links are kept alive by the hard reference in self.__map.
# The prev/next links are weakref proxies (to prevent circular references). # Those hard references disappear when a key is deleted from an OrderedSet.
# Individual links are kept alive by the hard reference in self.__map.
# Those hard references disappear when a key is deleted from an OrderedSet. # Added by IG-- pre-existing theano code expected sets
# to have this method
# Added by IG-- pre-existing theano code expected sets def update(self, iterable):
# to have this method check_deterministic(iterable)
def update(self, iterable): self |= iterable
check_deterministic(iterable)
def __init__(self, iterable=None):
# Checks added by IG
check_deterministic(iterable)
self.__root = root = Link() # sentinel node for doubly linked list
root.prev = root.next = weakref.ref(root)
self.__map = {} # key --> link
if iterable is not None:
self |= iterable self |= iterable
def __init__(self, iterable=None): def __len__(self):
# Checks added by IG return len(self.__map)
check_deterministic(iterable)
self.__root = root = Link() # sentinel node for doubly linked list
root.prev = root.next = weakref.ref(root)
self.__map = {} # key --> link
if iterable is not None:
self |= iterable
def __len__(self):
return len(self.__map)
def __contains__(self, key):
return key in self.__map
def add(self, key): def __contains__(self, key):
# Store new key in a new link at the end of the linked list return key in self.__map
if key not in self.__map:
self.__map[key] = link = Link()
root = self.__root
last = root.prev
link.prev, link.next, link.key = last, weakref.ref(root), key
last().next = root.prev = weakref.ref(link)
def union(self, s): def add(self, key):
check_deterministic(s) # Store new key in a new link at the end of the linked list
n = self.copy() if key not in self.__map:
for elem in s: self.__map[key] = link = Link()
if elem not in n:
n.add(elem)
return n
def intersection_update(self, s):
l = []
for elem in self:
if elem not in s:
l.append(elem)
for elem in l:
self.remove(elem)
return self
def difference_update(self, s):
check_deterministic(s)
for elem in s:
if elem in self:
self.remove(elem)
return self
def copy(self):
n = OrderedSet()
n.update(self)
return n
def discard(self, key):
# Remove an existing item using self.__map to find the link which is
# then removed by updating the links in the predecessor and successors.
if key in self.__map:
link = self.__map.pop(key)
link.prev().next = link.next
link.next().prev = link.prev
def __iter__(self):
# Traverse the linked list in order.
root = self.__root
curr = root.next()
while curr is not root:
yield curr.key
curr = curr.next()
def __reversed__(self):
# Traverse the linked list in reverse order.
root = self.__root root = self.__root
curr = root.prev() last = root.prev
while curr is not root: link.prev, link.next, link.key = last, weakref.ref(root), key
yield curr.key last().next = root.prev = weakref.ref(link)
curr = curr.prev()
def union(self, s):
def pop(self, last=True): check_deterministic(s)
if not self: n = self.copy()
raise KeyError('set is empty') for elem in s:
if last: if elem not in n:
key = next(reversed(self)) n.add(elem)
else: return n
key = next(iter(self))
self.discard(key) def intersection_update(self, s):
return key l = []
for elem in self:
def __repr__(self): if elem not in s:
if not self: l.append(elem)
return '%s()' % (self.__class__.__name__,) for elem in l:
return '%s(%r)' % (self.__class__.__name__, list(self)) self.remove(elem)
return self
def __eq__(self, other):
# Note that we implement only the comparison to another def difference_update(self, s):
# `OrderedSet`, and not to a regular `set`, because otherwise we check_deterministic(s)
# could have a non-symmetric equality relation like: for elem in s:
# my_ordered_set == my_set and my_set != my_ordered_set if elem in self:
if isinstance(other, OrderedSet): self.remove(elem)
return len(self) == len(other) and list(self) == list(other) return self
elif isinstance(other, set):
# Raise exception to avoid confusion. def copy(self):
raise TypeError( n = OrderedSet()
'Cannot compare an `OrderedSet` to a `set` because ' n.update(self)
'this comparison cannot be made symmetric: please ' return n
'manually cast your `OrderedSet` into `set` before '
'performing this comparison.') def discard(self, key):
else: # Remove an existing item using self.__map to find the link which is
return NotImplemented # then removed by updating the links in the predecessor and successors.
if key in self.__map:
# end of http://code.activestate.com/recipes/576696/ }}} link = self.__map.pop(key)
link.prev().next = link.next
else: link.next().prev = link.prev
# Python 2.4
class OrderedSet(object): def __iter__(self):
""" # Traverse the linked list in order.
An implementation of OrderedSet based on the keys of root = self.__root
an OrderedDict. curr = root.next()
""" while curr is not root:
def __init__(self, iterable=None): yield curr.key
self.data = OrderedDict() curr = curr.next()
if iterable is not None:
self.update(iterable) def __reversed__(self):
# Traverse the linked list in reverse order.
def update(self, container): root = self.__root
check_deterministic(container) curr = root.prev()
for elem in container: while curr is not root:
self.add(elem) yield curr.key
curr = curr.prev()
def add(self, key):
self.data[key] = None def pop(self, last=True):
if not self:
def __len__(self): raise KeyError('set is empty')
return len(self.data) if last:
key = next(reversed(self))
def __contains__(self, key): else:
return key in self.data key = next(iter(self))
self.discard(key)
def discard(self, key): return key
if key in self.data:
del self.data[key] def __repr__(self):
if not self:
def remove(self, key): return '%s()' % (self.__class__.__name__,)
if key in self.data: return '%s(%r)' % (self.__class__.__name__, list(self))
del self.data[key]
else: def __eq__(self, other):
raise KeyError(key) # Note that we implement only the comparison to another
# `OrderedSet`, and not to a regular `set`, because otherwise we
def __iter__(self): # could have a non-symmetric equality relation like:
return self.data.__iter__() # my_ordered_set == my_set and my_set != my_ordered_set
if isinstance(other, OrderedSet):
def __reversed__(self): return len(self) == len(other) and list(self) == list(other)
return self.data.__reversed__() elif isinstance(other, set):
# Raise exception to avoid confusion.
def pop(self, last=True): raise TypeError(
raise NotImplementedError() 'Cannot compare an `OrderedSet` to a `set` because '
'this comparison cannot be made symmetric: please '
def __eq__(self, other): 'manually cast your `OrderedSet` into `set` before '
# Note that we implement only the comparison to another 'performing this comparison.')
# `OrderedSet`, and not to a regular `set`, because otherwise we else:
# could have a non-symmetric equality relation like: return NotImplemented
# my_ordered_set == my_set and my_set != my_ordered_set
if isinstance(other, OrderedSet): # end of http://code.activestate.com/recipes/576696/ }}}
return len(self) == len(other) and list(self) == list(other)
elif isinstance(other, set):
# Raise exception to avoid confusion.
raise TypeError(
'Cannot compare an `OrderedSet` to a `set` because '
'this comparison cannot be made symmetric: please '
'manually cast your `OrderedSet` into `set` before '
'performing this comparison.')
else:
return NotImplemented
# NB: Contrary to the other implementation above, we do not override
# the `__del__` method. On one hand, this is not needed since this
# implementation does not add circular references. Moreover, one should
# not clear the underlying dictionary holding the data as soon as the
# ordered set is cleared from memory, because there may still be
# pointers to this dictionary.
if __name__ == '__main__': if __name__ == '__main__':
print list(OrderedSet('abracadaba')) print list(OrderedSet('abracadaba'))
......
""" """
This file implement specialization optimization that break the canonization form of the graph. This file implement specialization optimization that break the
canonization form of the graph.
Currently there is problem with the order of optimization and the definition of definition of
canonized graph. Currently there is problem with the order of optimization and the
definition of definition of canonized graph.
Right now there is a canonization optimization phase that try to make all equivalent graph
identical. This is not always the case, but it do many of the basic stuff canonical. We Right now there is a canonization optimization phase that try to make
need to extend the definition of canonization to make this true more often. all equivalent graph identical. This is not always the case, but it do
many of the basic stuff canonical. We need to extend the definition of
The problem this file indent to fix in the future is that in the "Equilibrium" specialization canonization to make this true more often.
optimization phase, there is optimization that request that the graph is canonical, some other
request that this is not true, and some other that break the canonicalization for The problem this file indent to fix in the future is that in the
some optimization. As we can't control the order of those optimization, there is case that some "Equilibrium" specialization optimization phase, there is optimization
optimization requesting a canonical graph won't be applied as optimization that break the that request that the graph is canonical, some other request that this
canonicalization form of the graph executed before. is not true, and some other that break the canonicalization for some
optimization. As we can't control the order of those optimization, there
To fix this, we need to split the specialization phase into a phase where optimization can't break the canonicalization form and one where this is allowed. This is also needed for the stabilized optimization phase, but as it happen before the specialization phase, this cause less problem. is case that some optimization requesting a canonical graph won't be
applied as optimization that break the canonicalization form of the
Also, we should make the fgraph refuse optimization that break the canonization of the graph in the optimizations phases where the graph is supposed to be canonical. graph executed before.
To fix this, we need to split the specialization phase into a phase
where optimization can't break the canonicalization form and one where
this is allowed. This is also needed for the stabilized optimization
phase, but as it happen before the specialization phase, this cause less
problem.
Also, we should make the fgraph refuse optimization that break the
canonization of the graph in the optimizations phases where the graph is
supposed to be canonical.
""" """
# TODO: intelligent merge for mul/add # TODO: intelligent merge for mul/add
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论