def __setstate__(self, d): """ TESTS:: sage: f = Family([3,4,7], lambda i: 2*i, hidden_keys=[2]) sage: d = f.__getstate__() sage: f = Family([4,5,6], lambda i: 2*i, hidden_keys=[2]) sage: f.__setstate__(d) sage: f.keys() [3, 4, 7] sage: f[3] 6 """ hidden_function = d['hidden_function'] if isinstance(hidden_function, str): # Let's assume that hidden_function is an unpickled function. from sage.misc.fpickle import unpickle_function hidden_function = unpickle_function(hidden_function) self.__init__(d['dictionary'], d['hidden_keys'], hidden_function) self.hidden_dictionary = d['hidden_dictionary'] # Old pickles from before trac #22955 may not have a 'keys' if 'keys' in d: self._keys = d['keys'] else: self._keys = None
def _make_lazy_string(ftype, fpickle, args, kwargs): """ Used for pickling. EXAMPLES:: sage: from sage.misc.lazy_string import _make_lazy_string sage: s = _make_lazy_string(None, lambda: "laziness", (), {}) sage: s l'laziness' """ if ftype == 'func': from sage.misc.fpickle import unpickle_function f = unpickle_function(fpickle) else: f = fpickle return _LazyString(f, args, kwargs)
def __setstate__(self, d): """ EXAMPLES:: sage: from sage.sets.family import LazyFamily sage: f = LazyFamily([3,4,7], lambda i: 2*i) sage: d = f.__getstate__() sage: f = LazyFamily([4,5,6], lambda i: 2*i) sage: f.__setstate__(d) sage: f.keys() [3, 4, 7] sage: f[3] 6 """ function = d['function'] if isinstance(function, str): # Let's assume that function is an unpickled function. from sage.misc.fpickle import unpickle_function function = unpickle_function(function) self.__init__(d['set'], function)
def _construct_word(self, data=None, length=None, datatype=None, caching=True): r""" Construct a word. INPUT: - ``data`` - (default: None) list, string, tuple, iterator, None (shorthand for []), or a callable defined on [0,1,...,length]. - ``length`` - (default: None) This is dependent on the type of data. It is ignored for words defined by lists, strings, tuples, etc., because they have a naturally defined length. For callables, this defines the domain of definition, which is assumed to be [0, 1, 2, ..., length-1]. For iterators: Infinity if you know the iterator will not terminate (default); "unknown" if you do not know whether the iterator terminates; "finite" if you know that the iterator terminates, but do know know the length. - ``datatype`` - (default: None) None, "list", "str", "tuple", "iter", "callable". If None, then the function tries to guess this from the data. - ``caching`` - (default: True) True or False. Whether to keep a cache of the letters computed by an iterator or callable. .. note:: Be careful when defining words using callables and iterators. It appears that islice does not pickle correctly causing various errors when reloading. Also, most iterators do not support copying and should not support pickling by extension. EXAMPLES: Empty word:: sage: Words()._construct_word() word: Word with string:: sage: Words()._construct_word("abbabaab") word: abbabaab Word with string constructed from other types:: sage: Words()._construct_word([0,1,1,0,1,0,0,1], datatype="str") word: 01101001 sage: Words()._construct_word((0,1,1,0,1,0,0,1), datatype="str") word: 01101001 Word with list:: sage: Words()._construct_word([0,1,1,0,1,0,0,1]) word: 01101001 Word with list constructed from other types:: sage: Words()._construct_word("01101001", datatype="list") word: 01101001 sage: Words()._construct_word((0,1,1,0,1,0,0,1), datatype="list") word: 01101001 Word with tuple:: sage: Words()._construct_word((0,1,1,0,1,0,0,1)) word: 01101001 Word with tuple constructed from other types:: sage: Words()._construct_word([0,1,1,0,1,0,0,1], datatype="tuple") word: 01101001 sage: Words()._construct_word("01101001", datatype="str") word: 01101001 Word with iterator:: sage: from itertools import count sage: Words()._construct_word(count()) word: 0,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,... sage: Words()._construct_word(iter("abbabaab")) # iterators default to infinite words word: abbabaab sage: Words()._construct_word(iter("abbabaab"), length="unknown") word: abbabaab sage: Words()._construct_word(iter("abbabaab"), length="finite") word: abbabaab Word with function (a 'callable'):: sage: f = lambda n : add(Integer(n).digits(2)) % 2 sage: Words()._construct_word(f) word: 0110100110010110100101100110100110010110... sage: Words()._construct_word(f, length=8) word: 01101001 Word over a string with a parent:: sage: w = Words('abc')._construct_word("abbabaab"); w word: abbabaab sage: w.parent() Words over {'a', 'b', 'c'} The default parent is the combinatorial class of all words:: sage: w = Words()._construct_word("abbabaab"); w word: abbabaab sage: w.parent() Words Creation of a word from a word:: sage: Words([0,1,2,3])(Words([2,3])([2,2,2,3,3,2])) word: 222332 sage: _.parent() Words over {0, 1, 2, 3} :: sage: Words([3,2,1])(Words([2,3])([2,2,2,3,3,2])) word: 222332 sage: _.parent() Words over {3, 2, 1} Construction of a word from a word when the parents are the same:: sage: W = Words() sage: w = W(range(8)) sage: z = W(w) sage: w is z True Construction of a word path from a finite word:: sage: W = Words('abcd') sage: P = WordPaths('abcd') sage: w = W('aaab') sage: P(w) Path: aaab Construction of a word path from a Christoffel word:: sage: w = words.ChristoffelWord(5,8) sage: w word: 0010010100101 sage: P = WordPaths([0,1,2,3]) sage: P(w) Path: 0010010100101 Construction of a word represented by a list from a word represented by a str :: sage: w = Word('ababbbabab') sage: type(w) <class 'sage.combinat.words.word.FiniteWord_str'> sage: z = Word(w, datatype='list') sage: type(z) <class 'sage.combinat.words.word.FiniteWord_list'> sage: y = Word(w, alphabet='abc', datatype='list') sage: type(y) <class 'sage.combinat.words.word.FiniteWord_list'> Creation of a word from a concatenation of words:: sage: W = Words() sage: w = W() * W('a') sage: Z = Words('ab') sage: Z(w) word: a Creation of a word path from a FiniteWord_iter:: sage: w = words.FibonacciWord() sage: f = w[:100] sage: P = WordPaths([0,1,2,3]) sage: p = P(f); p Path: 0100101001001010010100100101001001010010... sage: p.length() 100 Creation of a word path from a FiniteWord_callable:: sage: g = Word(lambda n:n%2, length = 100) sage: P = WordPaths([0,1,2,3]) sage: p = P(g); p Path: 0101010101010101010101010101010101010101... sage: p.length() 100 Creation of a word from a pickled function:: sage: f = lambda n : n % 10 sage: from sage.misc.fpickle import pickle_function sage: s = pickle_function(f) sage: Word(s, datatype='pickled_function') word: 0123456789012345678901234567890123456789... """ from sage.combinat.words.abstract_word import Word_class from sage.combinat.words.word_infinite_datatypes import WordDatatype_callable, WordDatatype_iter from sage.combinat.words.word_datatypes import WordDatatype if isinstance(data, Word_class): #################### # If `data` is already a word and if its parent is self, # then return `data` (no matter what the parameter length, # datatype and length are). ########################### if data.parent() is self: return data ########################### # Otherwise, if self is not the parent of `data`, then we # try to recover the data, the length and the datatype of the # input `data` ########################### if isinstance(data, WordDatatype_callable): from sage.combinat.words.finite_word import CallableFromListOfWords if isinstance(data._func, CallableFromListOfWords): # The following line is important because, in this case, # data._func is also a tuple (indeed # CallableFromListOfWords inherits from tuple) datatype = "callable" if length is None: length = data._len data = data._func elif isinstance(data, WordDatatype_iter): if length is None: length = data._len data = iter(data) elif isinstance(data, WordDatatype): data = data._data else: raise TypeError, "Any instance of Word_class must be an instance of WordDatatype." if data is None: data = [] # Guess the datatype if it is not given. if datatype is None: if isinstance(data, (list, CombinatorialObject)): datatype = "list" elif isinstance(data, (str)): datatype = "str" elif isinstance(data, tuple): datatype = "tuple" elif callable(data): datatype = "callable" elif hasattr(data,"__iter__"): datatype = "iter" else: raise ValueError, "Cannot guess a datatype from data (=%s); please specify one"%data else: # type check the datatypes if datatype == "iter" and not hasattr(data, "__iter__"): raise ValueError, "Your data is not iterable" elif datatype == "callable" and not callable(data): raise ValueError, "Your data is not callable" elif datatype not in ("list", "tuple", "str", "callable", "iter", "pickled_function"): raise ValueError, "Unknown datatype (=%s)" % datatype # If `data` is a pickled_function, restore the function if datatype == 'pickled_function': from sage.misc.fpickle import unpickle_function data = unpickle_function(data) datatype = 'callable' # Construct the word class and keywords if datatype in ('list','str','tuple'): cls_str = 'FiniteWord_%s'%datatype kwds = dict(parent=self,data=data) elif datatype == 'callable': if length in (None, Infinity, 'infinite'): cls_str = 'InfiniteWord_callable' else: cls_str = 'FiniteWord_callable' if caching: cls_str += '_with_caching' kwds = dict(parent=self,callable=data,length=length) elif datatype == 'iter': if length in (None, Infinity, 'infinite'): cls_str = 'InfiniteWord_iter' elif length == 'finite': cls_str = 'FiniteWord_iter' elif length == 'unknown': cls_str = 'Word_iter' elif length in ZZ and length >= 0: cls_str = 'FiniteWord_iter' else: raise ValueError, "not a correct value for length (%s)" % length if caching: cls_str += '_with_caching' kwds = dict(parent=self,iter=data,length=length) else: raise ValueError, "Not known datatype" wordclass = self._element_classes cls = wordclass[cls_str] w = cls(**kwds) return w
def _construct_word(self, data=None, length=None, datatype=None, caching=True): r""" Construct a word. INPUT: - ``data`` - (default: None) list, string, tuple, iterator, None (shorthand for []), or a callable defined on [0,1,...,length]. - ``length`` - (default: None) This is dependent on the type of data. It is ignored for words defined by lists, strings, tuples, etc., because they have a naturally defined length. For callables, this defines the domain of definition, which is assumed to be [0, 1, 2, ..., length-1]. For iterators: Infinity if you know the iterator will not terminate (default); "unknown" if you do not know whether the iterator terminates; "finite" if you know that the iterator terminates, but do know know the length. - ``datatype`` - (default: None) None, "list", "str", "tuple", "iter", "callable". If None, then the function tries to guess this from the data. - ``caching`` - (default: True) True or False. Whether to keep a cache of the letters computed by an iterator or callable. .. note:: Be careful when defining words using callables and iterators. It appears that islice does not pickle correctly causing various errors when reloading. Also, most iterators do not support copying and should not support pickling by extension. EXAMPLES: Empty word:: sage: Words()._construct_word() word: Word with string:: sage: Words()._construct_word("abbabaab") word: abbabaab Word with string constructed from other types:: sage: Words()._construct_word([0,1,1,0,1,0,0,1], datatype="str") word: 01101001 sage: Words()._construct_word((0,1,1,0,1,0,0,1), datatype="str") word: 01101001 Word with list:: sage: Words()._construct_word([0,1,1,0,1,0,0,1]) word: 01101001 Word with list constructed from other types:: sage: Words()._construct_word("01101001", datatype="list") word: 01101001 sage: Words()._construct_word((0,1,1,0,1,0,0,1), datatype="list") word: 01101001 Word with tuple:: sage: Words()._construct_word((0,1,1,0,1,0,0,1)) word: 01101001 Word with tuple constructed from other types:: sage: Words()._construct_word([0,1,1,0,1,0,0,1], datatype="tuple") word: 01101001 sage: Words()._construct_word("01101001", datatype="str") word: 01101001 Word with iterator:: sage: from itertools import count sage: Words()._construct_word(count()) word: 0,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,... sage: Words()._construct_word(iter("abbabaab")) # iterators default to infinite words word: abbabaab sage: Words()._construct_word(iter("abbabaab"), length="unknown") word: abbabaab sage: Words()._construct_word(iter("abbabaab"), length="finite") word: abbabaab Word with function (a 'callable'):: sage: f = lambda n : add(Integer(n).digits(2)) % 2 sage: Words()._construct_word(f) word: 0110100110010110100101100110100110010110... sage: Words()._construct_word(f, length=8) word: 01101001 Word over a string with a parent:: sage: w = Words('abc')._construct_word("abbabaab"); w word: abbabaab sage: w.parent() Words over {'a', 'b', 'c'} The default parent is the combinatorial class of all words:: sage: w = Words()._construct_word("abbabaab"); w word: abbabaab sage: w.parent() Words Creation of a word from a word:: sage: Words([0,1,2,3])(Words([2,3])([2,2,2,3,3,2])) word: 222332 sage: _.parent() Words over {0, 1, 2, 3} :: sage: Words([3,2,1])(Words([2,3])([2,2,2,3,3,2])) word: 222332 sage: _.parent() Words over {3, 2, 1} Construction of a word from a word when the parents are the same:: sage: W = Words() sage: w = W(range(8)) sage: z = W(w) sage: w is z True Construction of a word path from a finite word:: sage: W = Words('abcd') sage: P = WordPaths('abcd') sage: w = W('aaab') sage: P(w) Path: aaab Construction of a word path from a Christoffel word:: sage: w = words.ChristoffelWord(5,8) sage: w word: 0010010100101 sage: P = WordPaths([0,1,2,3]) sage: P(w) Path: 0010010100101 Construction of a word represented by a list from a word represented by a str :: sage: w = Word('ababbbabab') sage: type(w) <class 'sage.combinat.words.word.FiniteWord_str'> sage: z = Word(w, datatype='list') sage: type(z) <class 'sage.combinat.words.word.FiniteWord_list'> sage: y = Word(w, alphabet='abc', datatype='list') sage: type(y) <class 'sage.combinat.words.word.FiniteWord_list'> Creation of a word from a concatenation of words:: sage: W = Words() sage: w = W() * W('a') sage: Z = Words('ab') sage: Z(w) word: a Creation of a word path from a FiniteWord_iter:: sage: w = words.FibonacciWord() sage: f = w[:100] sage: P = WordPaths([0,1,2,3]) sage: p = P(f); p Path: 0100101001001010010100100101001001010010... sage: p.length() 100 Creation of a word path from a FiniteWord_callable:: sage: g = Word(lambda n:n%2, length = 100) sage: P = WordPaths([0,1,2,3]) sage: p = P(g); p Path: 0101010101010101010101010101010101010101... sage: p.length() 100 Creation of a word from a pickled function:: sage: f = lambda n : n % 10 sage: from sage.misc.fpickle import pickle_function sage: s = pickle_function(f) sage: Word(s, datatype='pickled_function') word: 0123456789012345678901234567890123456789... """ from sage.combinat.words.abstract_word import Word_class from sage.combinat.words.word_infinite_datatypes import WordDatatype_callable, WordDatatype_iter from sage.combinat.words.word_datatypes import WordDatatype if isinstance(data, Word_class): #################### # If `data` is already a word and if its parent is self, # then return `data` (no matter what the parameter length, # datatype and length are). ########################### if data.parent() is self: return data ########################### # Otherwise, if self is not the parent of `data`, then we # try to recover the data, the length and the datatype of the # input `data` ########################### if isinstance(data, WordDatatype_callable): from sage.combinat.words.finite_word import CallableFromListOfWords if isinstance(data._func, CallableFromListOfWords): # The following line is important because, in this case, # data._func is also a tuple (indeed # CallableFromListOfWords inherits from tuple) datatype = "callable" if length is None: length = data._len data = data._func elif isinstance(data, WordDatatype_iter): if length is None: length = data._len data = iter(data) elif isinstance(data, WordDatatype): data = data._data else: raise TypeError, "Any instance of Word_class must be an instance of WordDatatype." if data is None: data = [] # Guess the datatype if it is not given. if datatype is None: if isinstance(data, (list, CombinatorialObject)): datatype = "list" elif isinstance(data, (str)): datatype = "str" elif isinstance(data, tuple): datatype = "tuple" elif callable(data): datatype = "callable" elif hasattr(data, "__iter__"): datatype = "iter" else: raise ValueError, "Cannot guess a datatype from data (=%s); please specify one" % data else: # type check the datatypes if datatype == "iter" and not hasattr(data, "__iter__"): raise ValueError, "Your data is not iterable" elif datatype == "callable" and not callable(data): raise ValueError, "Your data is not callable" elif datatype not in ("list", "tuple", "str", "callable", "iter", "pickled_function"): raise ValueError, "Unknown datatype (=%s)" % datatype # If `data` is a pickled_function, restore the function if datatype == 'pickled_function': from sage.misc.fpickle import unpickle_function data = unpickle_function(data) datatype = 'callable' # Construct the word class and keywords if datatype in ('list', 'str', 'tuple'): cls_str = 'FiniteWord_%s' % datatype kwds = dict(parent=self, data=data) elif datatype == 'callable': if length in (None, Infinity, 'infinite'): cls_str = 'InfiniteWord_callable' else: cls_str = 'FiniteWord_callable' if caching: cls_str += '_with_caching' kwds = dict(parent=self, callable=data, length=length) elif datatype == 'iter': if length in (None, Infinity, 'infinite'): cls_str = 'InfiniteWord_iter' elif length == 'finite': cls_str = 'FiniteWord_iter' elif length == 'unknown': cls_str = 'Word_iter' elif length in ZZ and length >= 0: cls_str = 'FiniteWord_iter' else: raise ValueError, "not a correct value for length (%s)" % length if caching: cls_str += '_with_caching' kwds = dict(parent=self, iter=data, length=length) else: raise ValueError, "Not known datatype" wordclass = self._element_classes cls = wordclass[cls_str] w = cls(**kwds) return w