def permutation_matrix(orig_vec, per_vec): """Compute the permutation matrix to change order of orig_vec into order of per_vec. Parameters ---------- orig_vec : array_like Symbols in original ordering. per_vec : array_like Symbols in new ordering. Returns ------- p_matrix : Matrix Permutation matrix such that orig_vec == (p_matrix * per_vec). """ if not isinstance(orig_vec, (list, tuple)): orig_vec = flatten(orig_vec) if not isinstance(per_vec, (list, tuple)): per_vec = flatten(per_vec) if set(orig_vec) != set(per_vec): raise ValueError("orig_vec and per_vec must be the same length, " + "and contain the same symbols.") ind_list = [orig_vec.index(i) for i in per_vec] p_matrix = zeros(len(orig_vec)) for i, j in enumerate(ind_list): p_matrix[i, j] = 1 return p_matrix
def get_transformation_function(segments, fixed_endpoint=None, fixed_basepoint=None, use_dict=True): if fixed_endpoint: coordinate_labels = [] else: coordinate_labels = ['x','y','z'] if fixed_basepoint: inverse_coordinate_labels = [] else: inverse_coordinate_labels = ['base_x','base_y','base_z'] trans_mat, inv_trans_mat, var_names = get_sympy_reduction(segments, fixed_endpoint, fixed_basepoint, coordinate_labels, inverse_coordinate_labels) # Bake into a lambda func base_func = lambdify(flatten((coordinate_labels, var_names)), trans_mat) base_inv_func = lambdify(flatten((inverse_coordinate_labels, var_names)), inv_trans_mat) if use_dict: if fixed_endpoint: func = lambda var_dict: base_func(*flatten([var_dict[var_name] for var_name in var_names])).A else: func = lambda coords, var_dict: base_func(*flatten((coords, [var_dict[var_name] for var_name in var_names]))).A if fixed_basepoint: inv_func = lambda var_dict: base_inv_func(*flatten([var_dict[var_name] for var_name in var_names])).A else: inv_func = lambda coords, var_dict: base_inv_func(*flatten((coords, [var_dict[var_name] for var_name in var_names]))).A else: if fixed_endpoint: func = lambda var_vals: base_func(*flatten(var_vals)).A else: func = lambda coords, var_vals: base_func(*flatten((coords, var_vals))).A if fixed_basepoint: inv_func = lambda var_vals: base_inv_func(*flatten(var_vals)).A else: inv_func = lambda coords, var_vals: base_inv_func(*flatten((coords, var_vals))).A return func, inv_func
def test_flatten(): assert flatten( (1,(1,)) ) == [1,1] assert flatten( (x,(x,)) ) == [x,x] from sympy.core.basic import Basic class MyOp(Basic): pass assert flatten( [MyOp(x, y), z]) == [MyOp(x, y), z] assert flatten( [MyOp(x, y), z], cls=MyOp) == [x, y, z]
def __new__(cls, iterable=None, shape=None, **kwargs): from sympy.utilities.iterables import flatten shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else 0 # Sparse array: if isinstance(flat_list, (dict, Dict)): sparse_array = Dict(flat_list) else: sparse_array = {} for i, el in enumerate(flatten(flat_list)): if el != 0: sparse_array[i] = _sympify(el) sparse_array = Dict(sparse_array) self = Basic.__new__(cls, sparse_array, shape, **kwargs) self._shape = shape self._rank = len(shape) self._loop_size = loop_size self._sparse_array = sparse_array return self
def has(self, *patterns): """ Return True if self has any of the patterns. Example: >>> from sympy.abc import x >>> (2*x).has(x) True >>> (2*x/x).has(x) False """ from sympy.utilities.iterables import flatten from sympy.core.symbol import Wild if len(patterns)>1: for p in patterns: if self.has(p): return True return False elif not patterns: raise TypeError("has() requires at least 1 argument (got none)") p = sympify(patterns[0]) if isinstance(p, BasicType): return bool(self.atoms(p)) if p.is_Atom and not isinstance(p, Wild): return p in self.atoms(p.func) if p.matches(self) is not None: return True for e in flatten(self.args): if isinstance(e, Basic) and e.has(p): return True return False
def _pgroup_of_double(polyh, ordered_faces, pgroup): n = len(ordered_faces[0]) # the vertices of the double which sits inside a give polyhedron # can be found by tracking the faces of the outer polyhedron. # A map between face and the vertex of the double is made so that # after rotation the position of the vertices can be located fmap = dict(zip(ordered_faces, range(len(ordered_faces)))) flat_faces = flatten(ordered_faces) new_pgroup = [] for i, p in enumerate(pgroup): h = polyh.copy() h.rotate(p) c = h.corners # reorder corners in the order they should appear when # enumerating the faces reorder = unflatten([c[j] for j in flat_faces], n) # make them canonical reorder = [tuple(map(as_int, minlex(f, directed=False, is_set=True))) for f in reorder] # map face to vertex: the resulting list of vertices are the # permutation that we seek for the double new_pgroup.append(Perm([fmap[f] for f in reorder])) return new_pgroup
def __new__(cls, iterable=None, shape=None, **kwargs): from sympy.utilities.iterables import flatten shape, flat_list = cls._handle_ndarray_creation_inputs( iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) cls._check_special_bounds(flat_list, shape) loop_size = functools.reduce(lambda x, y: x * y, shape) if shape else len(flat_list) # Sparse array: if isinstance(flat_list, (dict, Dict)): sparse_array = Dict(flat_list) else: sparse_array = {} for i, el in enumerate(flatten(flat_list)): if el != 0: sparse_array[i] = _sympify(el) sparse_array = Dict(sparse_array) self = Basic.__new__(cls, sparse_array, shape, **kwargs) self._shape = shape self._rank = len(shape) self._loop_size = loop_size self._sparse_array = sparse_array return self
def letter_form(self): """ The letter representation of a ``FreeGroupElement`` is a tuple of generator symbols, with each entry corresponding to a group generator. Inverses of the generators are represented by negative generator symbols. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b, c, d = free_group("a b c d") >>> (a**3).letter_form (a, a, a) >>> (a**2*d**-2*a*b**-4).letter_form (a, a, -d, -d, a, -b, -b, -b, -b) >>> (a**-2*b**3*d).letter_form (-a, -a, b, b, b, d) See Also ======== array_form """ return tuple( flatten([(i, ) * j if j > 0 else (-i, ) * (-j) for i, j in self.array_form]))
def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies if a != None) else: #Sub in dummy variables for functions or symbols if isinstance(args, (Function, Symbol)): dummies = Dummy() dummies_dict.update({args: dummies}) return str(dummies) elif isinstance(args, Derivative): dummies = Dummy() dummies_dict.update({args: dummies}) return str(dummies) else: return str(args)
def _pgroup_of_double(polyh, ordered_faces, pgroup): n = len(ordered_faces[0]) # the vertices of the double which sits inside a give polyhedron # can be found by tracking the faces of the outer polyhedron. # A map between face and the vertex of the double is made so that # after rotation the position of the vertices can be located fmap = dict(zip(ordered_faces, range(len(ordered_faces)))) flat_faces = flatten(ordered_faces) new_pgroup = [] for i, p in enumerate(pgroup): h = polyh.copy() h.rotate(p) c = h.corners # reorder corners in the order they should appear when # enumerating the faces reorder = unflatten([c[j] for j in flat_faces], n) # make them canonical reorder = [ tuple(map(as_int, minlex(f, directed=False, is_set=True))) for f in reorder ] # map face to vertex: the resulting list of vertices are the # permutation that we seek for the double new_pgroup.append(Perm([fmap[f] for f in reorder])) return new_pgroup
def _preprocess(self, args, expr): """Preprocess args, expr to replace arguments that do not map to valid Python identifiers. Returns string form of args, and updated expr. """ from sympy import Dummy, Function, flatten, Derivative, ordered, Basic from sympy.matrices import DeferredVector # Args of type Dummy can cause name collisions with args # of type Symbol. Force dummify of everything in this # situation. dummify = self._dummify or any( isinstance(arg, Dummy) for arg in flatten(args)) argstrs = [None]*len(args) for arg, i in reversed(list(ordered(zip(args, range(len(args)))))): if iterable(arg): s, expr = self._preprocess(arg, expr) elif isinstance(arg, DeferredVector): s = str(arg) elif isinstance(arg, Basic) and arg.is_symbol: s = self._argrepr(arg) if dummify or not self._is_safe_ident(s): dummy = Dummy() s = self._argrepr(dummy) expr = self._subexpr(expr, {arg: dummy}) elif dummify or isinstance(arg, (Function, Derivative)): dummy = Dummy() s = self._argrepr(dummy) expr = self._subexpr(expr, {arg: dummy}) else: s = str(arg) argstrs[i] = s return argstrs, expr
def __new__(cls, *args, **kw_args): """ Constructor for the Permutation object. Examples ======== >>> from sympy.combinatorics.permutations import Permutation >>> p = Permutation([0,1,2]) >>> p Permutation([0, 1, 2]) >>> q = Permutation([[0,1],[2]]) >>> q Permutation([[0, 1], [2]]) """ if not args or not is_sequence(args[0]) or len(args) > 1 or \ len(set(is_sequence(a) for a in args[0])) > 1: raise ValueError( 'Permutation argument must be a list of ints or a list of lists.' ) # 0, 1, ..., n-1 should all be present temp = [int(i) for i in flatten(args[0])] if set(range(len(temp))) != set(temp): raise ValueError("Integers 0 through %s must be present." % len(temp)) cform = aform = None if args[0] and is_sequence(args[0][0]): cform = [list(a) for a in args[0]] else: aform = list(args[0]) ret_obj = Basic.__new__(cls, (cform or aform), **kw_args) ret_obj._cyclic_form, ret_obj._array_form = cform, aform return ret_obj
def decipher_hill(ct, key, symbols="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): """ Deciphering is the same as enciphering but using the inverse of the key matrix. Examples ======== >>> from sympy.crypto.crypto import decipher_hill >>> from sympy import Matrix >>> ct = "UEQDUEODOCTCWQ" >>> key = Matrix([[1, 2], [3, 5]]) >>> decipher_hill(ct, key) 'MEETMEONMONDAY' >>> ct = "UEQDUEODHBOYDJYU" >>> decipher_hill(ct, key) 'MEETMEONTUESDAYA' """ symbols = "".join(symbols) A = alphabet_of_cipher(symbols) N = len(A) # normally, 26 k = key.cols ct0 = [x.capitalize() for x in ct if x.isalnum()] C = [A.index(x) for x in ct0] n = len(C) m = n//k if n > m*k: C = C + [0]*(n - m*k) m = m + 1 key_inv = key.inv_mod(N) P = [list(key_inv*Matrix(k, 1, [C[i] for i in range(k*j, k*(j + 1))])) for j in range(m)] P = flatten(P) return "".join([A[i % N] for i in P])
def __new__(cls, periodical, limits=None): x, start, stop = None, None, None if limits is None: x, start, stop = Dummy("k"), 0, S.Infinity if is_sequence(limits, Tuple): if len(limits) == 3: x, start, stop = limits elif len(limits) == 2: x = Dummy("k") start, stop = limits if not isinstance(x, Symbol) or start is None or stop is None: raise ValueError("Invalid limits given: %s" % str(limits)) if start is S.NegativeInfinity and stop is S.Infinity: raise ValueError("Both the start and end value" " cannot be unbounded") limits = sympify((x, start, stop)) if is_sequence(periodical, Tuple): periodical = sympify(tuple(flatten(periodical))) else: raise ValueError("invalid period %s should be something " "like e.g (1, 2) " % periodical) if Interval(limits[1], limits[2]) is S.EmptySet: return S.EmptySequence return Basic.__new__(cls, periodical, limits)
def letter_form(self): """ The letter representation of an `FreeGroupElement` is as a tuple of generator symbols, each entry corresponding to a group generator. Inverses of the generators are represented by negative generator symbols. Examples ======== >>> from sympy.combinatorics.free_group import free_group >>> f, a, b, c, d = free_group("a b c d") >>> (a**3).letter_form (a, a, a) >>> (a**2*d**-2*a*b**-4).letter_form (a, a, -d, -d, a, -b, -b, -b, -b) >>> (a**-2*b**3*d).letter_form (-a, -a, b, b, b, d) See Also ======== array_form """ return tuple(flatten([(i,)*j if j > 0 else (-i,)*(-j) for i, j in self.array_form]))
def __new__(cls, *args, **kw_args): """ Constructor for the Permutation object. Examples ======== >>> from sympy.combinatorics.permutations import Permutation >>> p = Permutation([0,1,2]) >>> p Permutation([0, 1, 2]) >>> q = Permutation([[0,1],[2]]) >>> q Permutation([[0, 1], [2]]) """ if not args or not is_sequence(args[0]) or len(args) > 1 or \ len(set(is_sequence(a) for a in args[0])) > 1: raise ValueError('Permutation argument must be a list of ints or a list of lists.') # 0, 1, ..., n-1 should all be present temp = [int(i) for i in flatten(args[0])] if set(range(len(temp))) != set(temp): raise ValueError("Integers 0 through %s must be present." % len(temp)) cform = aform = None if args[0] and is_sequence(args[0][0]): cform = [list(a) for a in args[0]] else: aform = list(args[0]) ret_obj = Basic.__new__(cls, (cform or aform), **kw_args) ret_obj._cyclic_form, ret_obj._array_form = cform, aform return ret_obj
def get_transformation_function(segments, fixed_endpoint=None, fixed_basepoint=None, use_dict=True): if fixed_endpoint: coordinate_labels = [] else: coordinate_labels = ['x', 'y', 'z'] if fixed_basepoint: inverse_coordinate_labels = [] else: inverse_coordinate_labels = ['base_x', 'base_y', 'base_z'] trans_mat, inv_trans_mat, var_names = get_sympy_reduction( segments, fixed_endpoint, fixed_basepoint, coordinate_labels, inverse_coordinate_labels) # Bake into a lambda func base_func = lambdify(flatten((coordinate_labels, var_names)), trans_mat) base_inv_func = lambdify(flatten((inverse_coordinate_labels, var_names)), inv_trans_mat) if use_dict: if fixed_endpoint: func = lambda var_dict: base_func(*flatten( [var_dict[var_name] for var_name in var_names])).A else: func = lambda coords, var_dict: base_func(*flatten( (coords, [var_dict[var_name] for var_name in var_names]))).A if fixed_basepoint: inv_func = lambda var_dict: base_inv_func(*flatten( [var_dict[var_name] for var_name in var_names])).A else: inv_func = lambda coords, var_dict: base_inv_func(*flatten( (coords, [var_dict[var_name] for var_name in var_names]))).A else: if fixed_endpoint: func = lambda var_vals: base_func(*flatten(var_vals)).A else: func = lambda coords, var_vals: base_func(*flatten( (coords, var_vals))).A if fixed_basepoint: inv_func = lambda var_vals: base_inv_func(*flatten(var_vals)).A else: inv_func = lambda coords, var_vals: base_inv_func(*flatten( (coords, var_vals))).A return func, inv_func
def decipher_bifid6(ct, key): r""" Performs the Bifid cipher decryption on ciphertext ``ct``, and returns the plaintext. This is the version of the Bifid cipher that uses the `6 \times 6` Polybius square. Assumes alphabet of symbols is "A", ..., "Z", "0", ..., "9". INPUT: ``ct``: ciphertext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: plaintext from Bifid cipher (all caps, no spaces) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid6, decipher_bifid6 >>> key = "encrypt" >>> pt = "meet me on monday at 8am" >>> encipher_bifid6(pt, key) 'HNHOKNTA5MEPEGNQZYG' >>> ct = "HNHOKNTA5MEPEGNQZYG" >>> decipher_bifid6(ct, key) 'MEETMEONMONDAYAT8AM' """ A = alphabet_of_cipher() + [str(a) for a in range(10)] # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] ct0 = [x.capitalize() for x in ct if x.isalnum()] # create long key long_key = key0 + [x for x in A if not (x in key0)] n = len(ct0) # the fractionalization pairs = flatten([[long_key.index(x) // 6, long_key.index(x) % 6] for x in ct0]) tmp_plain = flatten([[pairs[i], pairs[n + i]] for i in range(n)]) pt = "".join([ long_key[6 * tmp_plain[2 * i] + tmp_plain[2 * i + 1]] for i in range(n) ]) return pt
def decipher_bifid5(ct, key): r""" Performs the Bifid cipher decryption on ciphertext ``ct``, and returns the plaintext. This is the version of the Bifid cipher that uses the `5 \times 5` Polybius square. INPUT: ``ct``: ciphertext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: plaintext from Bifid5 cipher (all caps, no spaces, no "J"s) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid5, decipher_bifid5 >>> key = "encrypt" >>> pt = "meet me on monday" >>> encipher_bifid5(pt, key) 'LNLLQNPPNPGADK' >>> ct = 'LNLLQNPPNPGADK' >>> decipher_bifid5(ct, key) 'MEETMEONMONDAY' """ A = alphabet_of_cipher() # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] ct0 = [x.capitalize() for x in ct if x.isalnum()] # create long key long_key = key0 + [x for x in A if (not (x in key0) and x != "J")] n = len(ct0) # the fractionalization pairs = flatten([[long_key.index(x) // 5, long_key.index(x) % 5] for x in ct0 if x != "J"]) tmp_plain = flatten([[pairs[i], pairs[n + i]] for i in range(n)]) pt = "".join([ long_key[5 * tmp_plain[2 * i] + tmp_plain[2 * i + 1]] for i in range(n) ]) return pt
def _new(cls, iterable, shape, **kwargs): shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) flat_list = flatten(flat_list) self = object.__new__(cls) self._shape = shape self._array = list(flat_list) self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else len(flat_list) return self
def decipher_bifid6(ct, key): r""" Performs the Bifid cipher decryption on ciphertext ``ct``, and returns the plaintext. This is the version of the Bifid cipher that uses the `6 \times 6` Polybius square. Assumes alphabet of symbols is "A", ..., "Z", "0", ..., "9". INPUT: ``ct``: ciphertext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: plaintext from Bifid cipher (all caps, no spaces) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid6, decipher_bifid6 >>> key = "encrypt" >>> pt = "meet me on monday at 8am" >>> encipher_bifid6(pt, key) 'HNHOKNTA5MEPEGNQZYG' >>> ct = "HNHOKNTA5MEPEGNQZYG" >>> decipher_bifid6(ct, key) 'MEETMEONMONDAYAT8AM' """ A = alphabet_of_cipher() + [str(a) for a in range(10)] # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] ct0 = [x.capitalize() for x in ct if x.isalnum()] # create long key long_key = key0 + [x for x in A if not(x in key0)] n = len(ct0) # the fractionalization pairs = flatten([[long_key.index(x)//6, long_key.index(x) % 6] for x in ct0]) tmp_plain = flatten([[pairs[i], pairs[n + i]] for i in range(n)]) pt = "".join([long_key[6*tmp_plain[2*i] + tmp_plain[2*i + 1]] for i in range(n)]) return pt
def decipher_bifid5(ct, key): r""" Performs the Bifid cipher decryption on ciphertext ``ct``, and returns the plaintext. This is the version of the Bifid cipher that uses the `5 \times 5` Polybius square. INPUT: ``ct``: ciphertext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: plaintext from Bifid5 cipher (all caps, no spaces, no "J"s) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid5, decipher_bifid5 >>> key = "encrypt" >>> pt = "meet me on monday" >>> encipher_bifid5(pt, key) 'LNLLQNPPNPGADK' >>> ct = 'LNLLQNPPNPGADK' >>> decipher_bifid5(ct, key) 'MEETMEONMONDAY' """ A = alphabet_of_cipher() # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] ct0 = [x.capitalize() for x in ct if x.isalnum()] # create long key long_key = key0 + [x for x in A if (not(x in key0) and x != "J")] n = len(ct0) # the fractionalization pairs = flatten([[long_key.index(x)//5, long_key.index(x) % 5] for x in ct0 if x != "J"]) tmp_plain = flatten([[pairs[i], pairs[n + i]] for i in range(n)]) pt = "".join([long_key[5*tmp_plain[2*i] + tmp_plain[2*i + 1]] for i in range(n)]) return pt
def test_flatten(): assert flatten((1, (1,))) == [1, 1] assert flatten((x, (x,))) == [x, x] ls = [[(-2, -1), (1, 2)], [(0, 0)]] assert flatten(ls, levels=0) == ls assert flatten(ls, levels=1) == [(-2, -1), (1, 2), (0, 0)] assert flatten(ls, levels=2) == [-2, -1, 1, 2, 0, 0] assert flatten(ls, levels=3) == [-2, -1, 1, 2, 0, 0] raises(ValueError, lambda: flatten(ls, levels=-1)) class MyOp(Basic): pass assert flatten([MyOp(x, y), z]) == [MyOp(x, y), z] assert flatten([MyOp(x, y), z], cls=MyOp) == [x, y, z] assert flatten(set([1, 11, 2])) == list(set([1, 11, 2]))
def test_flatten(): assert flatten((1, (1, ))) == [1, 1] assert flatten((x, (x, ))) == [x, x] ls = [[(-2, -1), (1, 2)], [(0, 0)]] assert flatten(ls, levels=0) == ls assert flatten(ls, levels=1) == [(-2, -1), (1, 2), (0, 0)] assert flatten(ls, levels=2) == [-2, -1, 1, 2, 0, 0] assert flatten(ls, levels=3) == [-2, -1, 1, 2, 0, 0] raises(ValueError, lambda: flatten(ls, levels=-1)) class MyOp(Basic): pass assert flatten([MyOp(x, y), z]) == [MyOp(x, y), z] assert flatten([MyOp(x, y), z], cls=MyOp) == [x, y, z] assert flatten({1, 11, 2}) == list({1, 11, 2})
def _new(cls, iterable, shape, **kwargs): from sympy.utilities.iterables import flatten shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) flat_list = flatten(flat_list) self = object.__new__(cls) self._shape = shape self._array = list(flat_list) self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else 0 return self
def __new__(cls, *args, **kw_args): """The constructor for the Prufer object. Examples ======== >>> from sympy.combinatorics.prufer import Prufer A Prufer object can be constructed from a list of edges: >>> a = Prufer([[0, 1], [0, 2], [0, 3]]) >>> a.prufer_repr [0, 0] If the number of nodes is given, no checking of the nodes will be performed; it will be assumed that nodes 0 through n - 1 are present: >>> Prufer([[0, 1], [0, 2], [0, 3]], 4) Prufer([[0, 1], [0, 2], [0, 3]], 4) A Prufer object can be constructed from a Prufer sequence: >>> b = Prufer([1, 3]) >>> b.tree_repr [[0, 1], [1, 3], [2, 3]] """ arg0 = Array(args[0]) if args[0] else Tuple() args = (arg0,) + tuple(_sympify(arg) for arg in args[1:]) ret_obj = Basic.__new__(cls, *args, **kw_args) args = [list(args[0])] if args[0] and iterable(args[0][0]): if not args[0][0]: raise ValueError( 'Prufer expects at least one edge in the tree.') if len(args) > 1: nnodes = args[1] else: nodes = set(flatten(args[0])) nnodes = max(nodes) + 1 if nnodes != len(nodes): missing = set(range(nnodes)) - nodes if len(missing) == 1: msg = 'Node %s is missing.' % missing.pop() else: msg = 'Nodes %s are missing.' % list(sorted(missing)) raise ValueError(msg) ret_obj._tree_repr = [list(i) for i in args[0]] ret_obj._nodes = nnodes else: ret_obj._prufer_repr = args[0] ret_obj._nodes = len(ret_obj._prufer_repr) + 2 return ret_obj
def _new(cls, iterable, shape, **kwargs): shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) cls._check_special_bounds(flat_list, shape) flat_list = flatten(flat_list) flat_list = Tuple(*flat_list) self = Basic.__new__(cls, flat_list, shape, **kwargs) self._shape = shape self._array = list(flat_list) self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape, 1) return self
def __new__(cls, *args, **kw_args): """The constructor for the Prufer object. Examples ======== >>> from sympy.combinatorics.prufer import Prufer A Prufer object can be constructed from a list of edges: >>> a = Prufer([[0, 1], [0, 2], [0, 3]]) >>> a.prufer_repr [0, 0] If the number of nodes is given, no checking of the nodes will be performed; it will be assumed that nodes 0 through n - 1 are present: >>> Prufer([[0, 1], [0, 2], [0, 3]], 4) Prufer([[0, 1], [0, 2], [0, 3]], 4) A Prufer object can be constructed from a Prufer sequence: >>> b = Prufer([1, 3]) >>> b.tree_repr [[0, 1], [1, 3], [2, 3]] """ ret_obj = Basic.__new__(cls, *args, **kw_args) args = [list(args[0])] if args[0] and iterable(args[0][0]): if not args[0][0]: raise ValueError( 'Prufer expects at least one edge in the tree.') if len(args) > 1: nnodes = args[1] else: nodes = set(flatten(args[0])) nnodes = max(nodes) + 1 if nnodes != len(nodes): missing = set(range(nnodes)) - nodes if len(missing) == 1: msg = 'Node %s is missing.' % missing.pop() else: msg = 'Nodes %s are missing.' % list(sorted(missing)) raise ValueError(msg) ret_obj._tree_repr = [list(i) for i in args[0]] ret_obj._nodes = nnodes else: ret_obj._prufer_repr = args[0] ret_obj._nodes = len(ret_obj._prufer_repr) + 2 return ret_obj
def _new(cls, iterable, shape, **kwargs): from sympy.utilities.iterables import flatten shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) flat_list = flatten(flat_list) flat_list = Tuple(*flat_list) self = Basic.__new__(cls, flat_list, shape, **kwargs) self._shape = shape self._array = list(flat_list) self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape, 1) return self
def _new(cls, iterable, shape, **kwargs): from sympy.utilities.iterables import flatten shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) shape = Tuple(*map(_sympify, shape)) flat_list = flatten(flat_list) flat_list = Tuple(*flat_list) self = Basic.__new__(cls, flat_list, shape, **kwargs) self._shape = shape self._array = list(flat_list) self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else 0 return self
def test_col_insert(): c4 = Matrix([4, 4, 4]) for i in range(-4, 5): l = [0, 0, 0] l.insert(i, 4) assert flatten(zeros_Shaping(3).col_insert(i, c4).row(0).tolist()) == l # issue 13643 assert eye_Shaping(6).col_insert(3, Matrix([[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]])) == \ Matrix([[1, 0, 0, 2, 2, 0, 0, 0], [0, 1, 0, 2, 2, 0, 0, 0], [0, 0, 1, 2, 2, 0, 0, 0], [0, 0, 0, 2, 2, 1, 0, 0], [0, 0, 0, 2, 2, 0, 1, 0], [0, 0, 0, 2, 2, 0, 0, 1]])
def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: if isinstance(args, Function): dummies = Dummy() dummies_dict.update({args : dummies}) return str(dummies) else: return str(args)
def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: if isinstance(args, Function): dummies = Dummy() dummies_dict.update({args: dummies}) return str(dummies) else: return str(args)
def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: # replace these with Dummy symbols if isinstance(args, (Function, Symbol, Derivative)): dummies = Dummy() dummies_dict.update({args : dummies}) return str(dummies) else: return str(args)
def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: #Sub in dummy variables for functions or symbols if isinstance(args, (Function, Symbol)): dummies = Dummy() dummies_dict.update({args : dummies}) return str(dummies) else: return str(args)
def encipher_bifid7(pt, key): r""" Performs the Bifid cipher encryption on plaintext ``pt``, and returns the ciphertext. This is the version of the Bifid cipher that uses the `7 \times 7` Polybius square. Assumes alphabet of symbols is "A", ..., "Z", "0", ..., "22". (Also, assumes you have some way of distinguishing "22" from "2", "2" juxtaposed together for deciphering...) INPUT: ``pt``: plaintext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: ciphertext from Bifid7 cipher (all caps, no spaces) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid7 >>> key = "encrypt" >>> pt = "meet me on monday at 8am" >>> encipher_bifid7(pt, key) 'JEJJLNAA3ME19YF3J222R' """ A = alphabet_of_cipher() + [str(a) for a in range(23)] # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] pt0 = [x.capitalize() for x in pt if x.isalnum()] # create long key long_key = key0 + [x for x in A if not (x in key0)] n = len(pt0) # the fractionalization pairs = [[long_key.index(x) // 7, long_key.index(x) % 7] for x in pt0] tmp_cipher = flatten([x[0] for x in pairs] + [x[1] for x in pairs]) ct = "".join([ long_key[7 * tmp_cipher[2 * i] + tmp_cipher[2 * i + 1]] for i in range(n) ]) return ct
def _preprocess(self, args, expr): """Preprocess args, expr to replace arguments that do not map to valid Python identifiers. Returns string form of args, and updated expr. """ from sympy import Dummy, Symbol, MatrixSymbol, Function, flatten from sympy.matrices import DeferredVector dummify = self._dummify # Args of type Dummy can cause name collisions with args # of type Symbol. Force dummify of everything in this # situation. if not dummify: dummify = any(isinstance(arg, Dummy) for arg in flatten(args)) argstrs = [] for arg in args: if iterable(arg): nested_argstrs, expr = self._preprocess(arg, expr) argstrs.append(nested_argstrs) elif isinstance(arg, DeferredVector): argstrs.append(str(arg)) elif isinstance(arg, Symbol) or isinstance(arg, MatrixSymbol): argrep = self._argrepr(arg) if dummify or not self._is_safe_ident(argrep): dummy = Dummy() argstrs.append(self._argrepr(dummy)) expr = self._subexpr(expr, {arg: dummy}) else: argstrs.append(argrep) elif isinstance(arg, Function): dummy = Dummy() argstrs.append(self._argrepr(dummy)) expr = self._subexpr(expr, {arg: dummy}) elif dummify: dummy = Dummy() argstrs.append(self._argrepr(dummy)) expr = self._subexpr(expr, {arg: dummy}) else: argstrs.append(str(arg)) return argstrs, expr
def encipher_bifid7(pt, key): r""" Performs the Bifid cipher encryption on plaintext ``pt``, and returns the ciphertext. This is the version of the Bifid cipher that uses the `7 \times 7` Polybius square. Assumes alphabet of symbols is "A", ..., "Z", "0", ..., "22". (Also, assumes you have some way of distinguishing "22" from "2", "2" juxtaposed together for deciphering...) INPUT: ``pt``: plaintext string (digits okay) ``key``: short string for key (no repetitions, digits okay) OUTPUT: ciphertext from Bifid7 cipher (all caps, no spaces) Examples ======== >>> from sympy.crypto.crypto import encipher_bifid7 >>> key = "encrypt" >>> pt = "meet me on monday at 8am" >>> encipher_bifid7(pt, key) 'JEJJLNAA3ME19YF3J222R' """ A = alphabet_of_cipher() + [str(a) for a in range(23)] # first make sure the letters are capitalized # and text has no spaces key = uniq(key) key0 = [x.capitalize() for x in key if x.isalnum()] pt0 = [x.capitalize() for x in pt if x.isalnum()] # create long key long_key = key0 + [x for x in A if not(x in key0)] n = len(pt0) # the fractionalization pairs = [[long_key.index(x)//7, long_key.index(x) % 7] for x in pt0] tmp_cipher = flatten([x[0] for x in pairs] + [x[1] for x in pairs]) ct = "".join([long_key[7*tmp_cipher[2*i] + tmp_cipher[2*i + 1]] for i in range(n)]) return ct
def __new__(cls, iterable=None, shape=None, **kwargs): shape, flat_list = cls._handle_ndarray_creation_inputs(iterable, shape, **kwargs) self = object.__new__(cls) self._shape = shape self._rank = len(shape) self._loop_size = functools.reduce(lambda x,y: x*y, shape) if shape else len(flat_list) # Sparse array: if isinstance(flat_list, (dict, Dict)): self._sparse_array = dict(flat_list) return self self._sparse_array = {} for i, el in enumerate(flatten(flat_list)): if el != 0: self._sparse_array[i] = _sympify(el) return self
def eval_sum(f, limits): from sympy.concrete.delta import deltasummation, _has_simple_delta from sympy.functions import KroneckerDelta (i, a, b) = limits if f is S.Zero: return S.Zero if i not in f.free_symbols: return f*(b - a + 1) if a == b: return f.subs(i, a) if isinstance(f, Piecewise): from sympy.utilities.iterables import flatten if i not in flatten([arg.args[1].free_symbols for arg in f.args]): # Piecewise conditions do not depend on the dummy summation variable, # therefore we can fold: Sum(Piecewise((e, c), ...), limits) # --> Piecewise((Sum(e, limits), c), ...) newargs = [] for arg in f.args: newexpr = eval_sum(arg.expr, limits) if newexpr is None: return None newargs.append((newexpr, arg.cond)) return f.func(*newargs) if f.has(KroneckerDelta) and _has_simple_delta(f, limits[0]): return deltasummation(f, limits) dif = b - a definite = dif.is_Integer # Doing it directly may be faster if there are very few terms. if definite and (dif < 100): return eval_sum_direct(f, (i, a, b)) # Try to do it symbolically. Even when the number of terms is known, # this can save time when b-a is big. # We should try to transform to partial fractions value = eval_sum_symbolic(f.expand(), (i, a, b)) if value is not None: return value # Do it directly if definite: return eval_sum_direct(f, (i, a, b))
def mc_compute_stationary_sympy(P, tol=1e-10): """ Computes the stationary distribution(s) of Markov matrix P. Parameters ---------- P : array_like(float, ndim=2) A discrete Markov transition matrix tol : scalar(float) optional Tolerance level Find eigenvectors for eigenvalues > 1 - tol Returns ------- vals : list of sympy.core.numbers.Float A list of eigenvalues of P > 1 - tol ndarray_vects : list of numpy.arrays of sympy.core.numbers.Float A list of the corresponding eigenvectors of P """ P = Matrix(P) # type(P): sympy.matrices.dense.MutableDenseMatrix outputs = P.transpose().eigenvects() # TODO: Raise exception when empty vals = [] vecs = [] # output = (eigenvalue, algebraic multiplicity, [eigenvectors]) for output in outputs: if output[0] > 1 - tol: vals.append(output[0]) vecs.extend(output[2]) # type(vec): sympy.matrices.dense.MutableDenseMatrix vecs_flattened = \ np.array([flatten(vec) for vec in vecs]) return vals, [vec/sum(vec) for vec in vecs_flattened]
def mc_compute_stationary_sympy(P, tol=1e-10): """ Computes the stationary distribution(s) of Markov matrix P. Parameters ---------- P : array_like(float, ndim=2) A discrete Markov transition matrix tol : scalar(float) optional Tolerance level Find eigenvectors for eigenvalues > 1 - tol Returns ------- vals : list of sympy.core.numbers.Float A list of eigenvalues of P > 1 - tol ndarray_vects : list of numpy.arrays of sympy.core.numbers.Float A list of the corresponding eigenvectors of P """ P = Matrix(P) # type(P): sympy.matrices.dense.MutableDenseMatrix outputs = P.transpose().eigenvects() # TODO: Raise exception when empty vals = [] vecs = [] # output = (eigenvalue, algebraic multiplicity, [eigenvectors]) for output in outputs: if output[0] > 1 - tol: vals.append(output[0]) vecs.extend(output[2]) # type(vec): sympy.matrices.dense.MutableDenseMatrix vecs_flattened = \ np.array([flatten(vec) for vec in vecs]) return vals, [vec / sum(vec) for vec in vecs_flattened]
def __new__(cls, periodical, limits=None): periodical = sympify(periodical) def _find_x(periodical): free = periodical.free_symbols if len(periodical.free_symbols) == 1: return free.pop() else: return Dummy('k') x, start, stop = None, None, None if limits is None: x, start, stop = _find_x(periodical), 0, S.Infinity if is_sequence(limits, Tuple): if len(limits) == 3: x, start, stop = limits elif len(limits) == 2: x = _find_x(periodical) start, stop = limits if not isinstance(x, (Symbol, Idx)) or start is None or stop is None: raise ValueError('Invalid limits given: %s' % str(limits)) if start is S.NegativeInfinity and stop is S.Infinity: raise ValueError("Both the start and end value" "cannot be unbounded") limits = sympify((x, start, stop)) if is_sequence(periodical, Tuple): periodical = sympify(tuple(flatten(periodical))) else: raise ValueError("invalid period %s should be something " "like e.g (1, 2) " % periodical) if Interval(limits[1], limits[2]) is S.EmptySet: return S.EmptySequence return Basic.__new__(cls, periodical, limits)
def _print_unpacking(self, lvalues, rvalue): """Generate argument unpacking code. This method is used when the input value is not interable, but can be indexed (see issue #14655). """ def flat_indexes(elems): n = 0 for el in elems: if iterable(el): for ndeep in flat_indexes(el): yield (n,) + ndeep else: yield (n,) n += 1 indexed = ', '.join('{}[{}]'.format(rvalue, ']['.join(map(str, ind))) for ind in flat_indexes(lvalues)) return ['[{}] = [{}]'.format(', '.join(flatten(lvalues)), indexed)]
def random_integer_partition(n, seed=None): """ Generates a random integer partition summing to ``n`` as a list of reverse-sorted integers. Examples ======== >>> from sympy.combinatorics.partitions import random_integer_partition For the following, a seed is given so a known value can be shown; in practice, the seed would not be given. >>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1]) [85, 12, 2, 1] >>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1]) [5, 3, 1, 1] >>> random_integer_partition(1) [1] """ from sympy.utilities.randtest import _randint n = as_int(n) if n < 1: raise ValueError('n must be a positive integer') randint = _randint(seed) partition = [] while (n > 0): k = randint(1, n) mult = randint(1, n//k) partition.append((k, mult)) n -= k*mult partition.sort(reverse=True) partition = flatten([[k]*m for k, m in partition]) return partition
def random_integer_partition(n, seed=None): """ Generates a random integer partition summing to ``n`` as a list of reverse-sorted integers. Examples ======== >>> from sympy.combinatorics.partitions import random_integer_partition For the following, a seed is given so a known value can be shown; in practice, the seed would not be given. >>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1]) [85, 12, 2, 1] >>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1]) [5, 3, 1, 1] >>> random_integer_partition(1) [1] """ from sympy.testing.randtest import _randint n = as_int(n) if n < 1: raise ValueError("n must be a positive integer") randint = _randint(seed) partition = [] while n > 0: k = randint(1, n) mult = randint(1, n // k) partition.append((k, mult)) n -= k * mult partition.sort(reverse=True) partition = flatten([[k] * m for k, m in partition]) return partition
def _generate_unpack_indexable(lvalues, rvalue): """Generate argument unpacking code for _lambdastrimpl. This method is used when the input value is not interable, but can be indexed. """ from sympy import flatten def flat_indexes(elems): n = 0 for el in elems: if iterable(el): for ndeep in flat_indexes(el): yield (n, ) + ndeep else: yield (n, ) n += 1 indexed = ', '.join('{}[{}]'.format(rvalue, ']['.join(map(str, ind))) for ind in flat_indexes(lvalues)) return ['[{}] = [{}]'.format(', '.join(flatten(lvalues)), indexed)]
def decipher_hill(ct, key, symbols="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): """ Deciphering is the same as ciphering but using the inverse of the key matrix. Examples ======== >>> from sympy.crypto.crypto import decipher_hill >>> from sympy import Matrix >>> ct = "UEQDUEODOCTCWQ" >>> key = Matrix([[1, 2], [3, 5]]) >>> decipher_hill(ct, key) 'MEETMEONMONDAY' >>> ct = "UEQDUEODHBOYDJYU" >>> decipher_hill(ct, key) 'MEETMEONTUESDAYA' """ symbols = "".join(symbols) A = alphabet_of_cipher(symbols) N = len(A) # normally, 26 k = key.cols ct0 = [x.capitalize() for x in ct if x.isalnum()] C = [A.index(x) for x in ct0] n = len(C) m = n // k if n > m * k: C = C + [0] * (n - m * k) m = m + 1 key_inv = key.inv_mod(N) P = [ list(key_inv * Matrix(k, 1, [C[i] for i in range(k * j, k * (j + 1))])) for j in range(m) ] P = flatten(P) return "".join([A[i % N] for i in P])
def _print_unpacking(self, lvalues, rvalue): """Generate argument unpacking code. This method is used when the input value is not interable, but can be indexed (see issue #14655). """ from sympy import flatten def flat_indexes(elems): n = 0 for el in elems: if iterable(el): for ndeep in flat_indexes(el): yield (n,) + ndeep else: yield (n,) n += 1 indexed = ', '.join('{}[{}]'.format(rvalue, ']['.join(map(str, ind))) for ind in flat_indexes(lvalues)) return ['[{}] = [{}]'.format(', '.join(flatten(lvalues)), indexed)]
def find_linear_recurrence(self, n, d=None, gfvar=None): r""" Finds the shortest linear recurrence that satisfies the first n terms of sequence of order `\leq` ``n/2`` if possible. If ``d`` is specified, find shortest linear recurrence of order `\leq` min(d, n/2) if possible. Returns list of coefficients ``[b(1), b(2), ...]`` corresponding to the recurrence relation ``x(n) = b(1)*x(n-1) + b(2)*x(n-2) + ...`` Returns ``[]`` if no recurrence is found. If gfvar is specified, also returns ordinary generating function as a function of gfvar. Examples ======== >>> from sympy import sequence, sqrt, oo, lucas >>> from sympy.abc import n, x, y >>> sequence(n**2).find_linear_recurrence(10, 2) [] >>> sequence(n**2).find_linear_recurrence(10) [3, -3, 1] >>> sequence(2**n).find_linear_recurrence(10) [2] >>> sequence(23*n**4+91*n**2).find_linear_recurrence(10) [5, -10, 10, -5, 1] >>> sequence(sqrt(5)*(((1 + sqrt(5))/2)**n - (-(1 + sqrt(5))/2)**(-n))/5).find_linear_recurrence(10) [1, 1] >>> sequence(x+y*(-2)**(-n), (n, 0, oo)).find_linear_recurrence(30) [1/2, 1/2] >>> sequence(3*5**n + 12).find_linear_recurrence(20,gfvar=x) ([6, -5], 3*(5 - 21*x)/((x - 1)*(5*x - 1))) >>> sequence(lucas(n)).find_linear_recurrence(15,gfvar=x) ([1, 1], (x - 2)/(x**2 + x - 1)) """ from sympy.matrices import Matrix x = [simplify(expand(t)) for t in self[:n]] lx = len(x) if d is None: r = lx // 2 else: r = min(d, lx // 2) coeffs = [] for l in range(1, r + 1): l2 = 2 * l mlist = [] for k in range(l): mlist.append(x[k:k + l]) m = Matrix(mlist) if m.det() != 0: y = simplify(m.LUsolve(Matrix(x[l:l2]))) if lx == l2: coeffs = flatten(y[::-1]) break mlist = [] for k in range(l, lx - l): mlist.append(x[k:k + l]) m = Matrix(mlist) if m * y == Matrix(x[l2:]): coeffs = flatten(y[::-1]) break if gfvar is None: return coeffs else: l = len(coeffs) if l == 0: return [], None else: n, d = x[l - 1] * gfvar**(l - 1), 1 - coeffs[l - 1] * gfvar**l for i in range(l - 1): n += x[i] * gfvar**i for j in range(l - i - 1): n -= coeffs[i] * x[j] * gfvar**(i + j + 1) d -= coeffs[i] * gfvar**(i + 1) return coeffs, simplify(factor(n) / factor(d))
def variables(self): """Cumulative of all the bound variables""" return tuple(flatten([a.variables for a in self.args]))
t = MatrixSymbol('t', 3,1) f, c1, c2, k1 = symbols("f, c1, c2, k1") u, v = symbols("u, v") Rp = (dR*R).T tp = -Rp*t P = Matrix(Rp*X + tp) p = Matrix([P[0]/P[2], P[1]/P[2]]) p_norm2 = p[0]**2 + p[1]**2 p_prime = f * (1 + k1 * p_norm2) * p e = Matrix([u - (p_prime[0] + c1), v - (p_prime[1] + c2)]) JdR = e.jacobian(flatten(Matrix(dR))) JdR = JdR.subs({'dR_00':1, 'dR_01':0, 'dR_02':0, 'dR_10':0, 'dR_11':1, 'dR_12':0, 'dR_20':0, 'dR_21':0, 'dR_22':1}) Jr = JdR*Jrod e = e.subs({'dR_00':1, 'dR_01':0, 'dR_02':0, 'dR_10':0, 'dR_11':1, 'dR_12':0, 'dR_20':0, 'dR_21':0, 'dR_22':1}) Jt = e.jacobian(flatten(Matrix(t))) JX = e.jacobian(flatten(Matrix(X))) Ji = e.jacobian([f, c1, c2, k1]) print """ from cython.view cimport array import numpy as np def compute_error_and_jacobian(R, t, intrinsics, X, coord):
def test_col_insert(): c4 = Matrix([4, 4, 4]) for i in range(-4, 5): l = [0, 0, 0] l.insert(i, 4) assert flatten(zeros_Shaping(3).col_insert(i, c4).row(0).tolist()) == l
def lambdastr(args, expr, printer=None, dummify=False): """ Returns a string that can be evaluated to a lambda function. Examples ======== >>> from sympy.abc import x, y, z >>> from sympy.utilities.lambdify import lambdastr >>> lambdastr(x, x**2) 'lambda x: (x**2)' >>> lambdastr((x,y,z), [z,y,x]) 'lambda x,y,z: ([z, y, x])' Although tuples may not appear as arguments to lambda in Python 3, lambdastr will create a lambda function that will unpack the original arguments so that nested arguments can be handled: >>> lambdastr((x, (y, z)), x + y) 'lambda _0,_1: (lambda x,y,z: (x + y))(*list(__flatten_args__([_0,_1])))' """ # Transforming everything to strings. from sympy.matrices import DeferredVector from sympy import Dummy, sympify, Symbol, Function, flatten if printer is not None: if inspect.isfunction(printer): lambdarepr = printer else: if inspect.isclass(printer): lambdarepr = lambda expr: printer().doprint(expr) else: lambdarepr = lambda expr: printer.doprint(expr) else: #XXX: This has to be done here because of circular imports from sympy.printing.lambdarepr import lambdarepr def sub_args(args, dummies_dict): if isinstance(args, str): return args elif isinstance(args, DeferredVector): return str(args) elif iterable(args): dummies = flatten([sub_args(a, dummies_dict) for a in args]) return ",".join(str(a) for a in dummies) else: #Sub in dummy variables for functions or symbols if isinstance(args, (Function, Symbol)): dummies = Dummy() dummies_dict.update({args : dummies}) return str(dummies) else: return str(args) def sub_expr(expr, dummies_dict): try: expr = sympify(expr).xreplace(dummies_dict) except Exception: if isinstance(expr, DeferredVector): pass elif isinstance(expr, dict): k = [sub_expr(sympify(a), dummies_dict) for a in expr.keys()] v = [sub_expr(sympify(a), dummies_dict) for a in expr.values()] expr = dict(zip(k, v)) elif isinstance(expr, tuple): expr = tuple(sub_expr(sympify(a), dummies_dict) for a in expr) elif isinstance(expr, list): expr = [sub_expr(sympify(a), dummies_dict) for a in expr] return expr # Transform args def isiter(l): return iterable(l, exclude=(str, DeferredVector)) if isiter(args) and any(isiter(i) for i in args): from sympy.utilities.iterables import flatten import re dum_args = [str(Dummy(str(i))) for i in range(len(args))] iter_args = ','.join([i if isiter(a) else i for i, a in zip(dum_args, args)]) lstr = lambdastr(flatten(args), expr, printer=printer, dummify=dummify) flat = '__flatten_args__' rv = 'lambda %s: (%s)(*list(%s([%s])))' % ( ','.join(dum_args), lstr, flat, iter_args) if len(re.findall(r'\b%s\b' % flat, rv)) > 1: raise ValueError('the name %s is reserved by lambdastr' % flat) return rv dummies_dict = {} if dummify: args = sub_args(args, dummies_dict) else: if isinstance(args, str): pass elif iterable(args, exclude=DeferredVector): args = ",".join(str(a) for a in args) # Transform expr if dummify: if isinstance(expr, str): pass else: expr = sub_expr(expr, dummies_dict) expr = lambdarepr(expr) return "lambda %s: (%s)" % (args, expr)
from sympy import * from sympy.utilities.iterables import flatten dR = MatrixSymbol("dR", 4, 4) wx, wy, wz, vx, vy, vz = symbols("wx, wy, wz, vx, vy, vz") M_prime = Matrix([[0, -wz, wy, vx], [wz, 0, -wx, vy], [-wy, wx, 0, vz], [0, 0, 0, 0]]) x, y, z, w = symbols("x, y, z, w") dx, dy, dz = symbols("dx, dy, dz") M = Matrix([x, y, z, 1]) dX = Matrix([dx, dy, dz]) X = dR * M X = Matrix(X[0:3]) Jm = Matrix(flatten(X)).jacobian(flatten(Matrix(dR))) Jm.simplify() Jmp = Matrix(flatten(M_prime)).jacobian([wx, wy, wz, vx, vy, vz]) Jmp.simplify() Jx = Matrix([x / w, y / w, z / w]).jacobian([x, y, z, w]) print dX.T * Jm * Jmp # x = A*M*dM*X # X = dM.inv()*M.inv()*A.inv()*x