K icddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z ddlm Z ddlmZddlmZmZmZddlmZddlmZdQd ZdRd ZdSd Zd ZdTd ZdZdZdZdUdZ dVdZ!dUdZ"dZ#dWdZ$dZ%dVdZ&dZ'dZ(dZ)dZ*dZ+dZ,dXdZ-dZ.d Z/d!Z0d"Z1d#Z2dXd$Z3dXd%Z4dRd&Z5dXd'Z6d(Z7dXd)Z8dYd*Z9dZd+Z:d,Z;d-Zd0Z?d1Z@d2ZAdZd3ZBd4ZCd5ZDdVd6ZEd7ZFd8ZGd[d9ZHefd:ZId;ZJd<ZKdXd=ZLd>ZMd?ZNd\d@ZOdAZPGdBdCZQeReSeQffdDZTdXdEZUedFdGdHIdXdJZVedKdGdHIdLZWedMdGdNIdOZXedMdGdNIdPZYy)])Counter defaultdict OrderedDict)chain combinationscombinations_with_replacementcycleislice permutationsproductgroupby)r )gt)multiset_partitions_taocp list_visitorMultisetPartitionTraverseras_int) deprecatedNctjt\}z dz}tfdt |DS)a Return True if the sequence is the same from left to right as it is from right to left in the whole sequence (default) or in the Python slice ``s[i: j]``; else False. Examples ======== >>> from sympy.utilities.iterables import is_palindromic >>> is_palindromic([1, 0, 1]) True >>> is_palindromic('abcbb') False >>> is_palindromic('abcbb', 1) False Normal Python slicing is performed in place so there is no need to create a slice of the sequence for testing: >>> is_palindromic('abcbb', 1, -1) True >>> is_palindromic('abcbb', -4, -1) True See Also ======== sympy.ntheory.digits.is_palindromic: tests integers c3FK|]}|zdz |z k(ywN).0kijss _/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/utilities/iterables.py z!is_palindromic..6s*:AqQx1QUQY<':!)sliceindiceslenallrange)rrr_ms``` r is_palindromicr*sG>Aqk!!#a&)GAq! Q A :q: ::c0ddlm}||s|S|dkDr|dz}ntd|zd}nfd}g}|D]]}||rBt|drt ||s |j }|j t||M|j|_|S) ar Recursively denest iterable containers. >>> from sympy import flatten >>> flatten([1, 2, 3]) [1, 2, 3] >>> flatten([1, 2, [3]]) [1, 2, 3] >>> flatten([1, [2, 3], [4, 5]]) [1, 2, 3, 4, 5] >>> flatten([1.0, 2, (1, None)]) [1.0, 2, 1, None] If you want to denest only a specified number of levels of nested containers, then set ``levels`` flag to the desired number of levels:: >>> ls = [[(-2, -1), (1, 2)], [(0, 0)]] >>> flatten(ls, levels=1) [(-2, -1), (1, 2), (0, 0)] If cls argument is specified, it will only flatten instances of that class, for example: >>> from sympy import Basic, S >>> class MyOp(Basic): ... pass ... >>> flatten([MyOp(S(1), MyOp(S(2), S(3)))], cls=MyOp) [1, 2, 3] adapted from https://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks r) NDimArrayrz.expected non-negative number of levels, got %sc"t|tSN) is_sequencesetxs r reduciblezflatten..reduciblehsq#& &r+ct|Sr/) isinstance)r3clss r r4zflatten..reducibleksa% %r+args)levelsr7) sympy.tensor.arrayr- ValueErrorhasattrr6r8extendflattenappend)iterabler9r7r-r4resultels ` r r>r>9sH- O aZ aKF@6IK K { ' &F R=r6":b)+DWW MM'"V= > MM"   Mr+cdkstzrtdzttfdt DS)zyGroup ``iter`` into tuples of length ``n``. Raise an error if the length of ``iter`` is not a multiple of ``n``. rz#iter length is not a multiple of %ic3.K|] }|dywr/r)rriterns r r!zunflatten..s3Qd14a4j3s)r%r;listzipr')rErFs``r unflattenrI{sA 1uD A >BCC 3%(34 55r+c tt|}tt||\}}|dks|r t dd}t |}dg|z}t t|D]}g} |D]}} t| tr| j|||| z|| z }0tt| }t | } | j| t||||z| d||z }|| ||<t ||S)aReshape the sequence according to the template in ``how``. Examples ======== >>> from sympy.utilities import reshape >>> seq = list(range(1, 9)) >>> reshape(seq, [4]) # lists of 4 [[1, 2, 3, 4], [5, 6, 7, 8]] >>> reshape(seq, (4,)) # tuples of 4 [(1, 2, 3, 4), (5, 6, 7, 8)] >>> reshape(seq, (2, 2)) # tuples of 4 [(1, 2, 3, 4), (5, 6, 7, 8)] >>> reshape(seq, (2, [2])) # (i, i, [i, i]) [(1, 2, [3, 4]), (5, 6, [7, 8])] >>> reshape(seq, ((2,), [2])) # etc.... [((1, 2), [3, 4]), ((5, 6), [7, 8])] >>> reshape(seq, (1, [2], 1)) [(1, [2, 3], 4), (5, [6, 7], 8)] >>> reshape(tuple(seq), ([[1], 1, (2,)],)) (([[1], 2, (3, 4)],), ([[5], 6, (7, 8)],)) >>> reshape(tuple(seq), ([1], 1, (2,))) (([1], 2, (3, 4)), ([5], 6, (7, 8))) >>> reshape(list(range(12)), [2, [3], {2}, (1, (3,), 1)]) [[0, 1, [2, 3, 4], {5, 6}, (7, (8, 9, 10), 11)]] rzLtemplate must sum to positive number that divides the length of the sequenceN) sumr>divmodr%r;typer'r6intr=r?reshape) seqhowr)rFremr containerrvr_rvhihi_types r rOrOsJ GCLA CHa FAs1u23 3 AS I B 3r7^  B"c" 3q!b&>*R $r( 773q!a%="#=a#@ABQ #1  49R=r+c |r't|Dcgc]\}}t|c}}St|Dcgc]\}}|tt|fc}}Scc}}wcc}}w)a Splits a sequence into a list of lists of equal, adjacent elements. Examples ======== >>> from sympy import group >>> group([1, 1, 1, 2, 2, 3]) [[1, 1, 1], [2, 2], [3]] >>> group([1, 1, 1, 2, 2, 3], multiple=False) [(1, 3), (2, 2), (3, 1)] >>> group([1, 1, 3, 2, 2, 1], multiple=False) [(1, 2), (3, 1), (2, 2), (1, 1)] See Also ======== multiset )r rGr%)rPmultipler(grs r groupr[sR,&-cl3daa33*1#, 7$!QQDG  774 7s A A"c# Kt|}t|}g}g}t fd}d}|||||||t|t|zkrkt|t|z dzt|D]}|||z ||f|dz }|||||||t|t|zkrjyyw)z4Cartesian product of two possibly infinite iterablescJt|}|ur|j|yyr/)nextr?)itelemsesentinels r r?z_iproduct2..appends' X  H  LLO r+rrN)rEobjectr%r') iterable1 iterable2it1it2elems1elems2r?rFr)rbs @r _iproduct2rjs y/C y/C F FxH A 3 3 s6{S[( (qV}QF 4 +A!A#;q * * + QsFsF s6{S[( (s CCCc'Kt|dk(rdyt|dk(r|dD]}|f yt|dk(rt|Ed{y|d|dd}}t|t|D] \}}|f|zy72w)a Cartesian product of iterables. Generator of the Cartesian product of iterables. This is analogous to itertools.product except that it works with infinite iterables and will yield any item from the infinite product eventually. Examples ======== >>> from sympy.utilities.iterables import iproduct >>> sorted(iproduct([1,2], [3,4])) [(1, 3), (1, 4), (2, 3), (2, 4)] With an infinite iterator: >>> from sympy import S >>> (3,) in iproduct(S.Integers) True >>> (3, 4) in iproduct(S.Integers, S.Integers) True .. seealso:: `itertools.product `_ rrNrr)r%rjiproduct) iterablesrafirstothersefeos r rlrls8 9~ Y1 1 A$J  Y1 y)))!! imv &(9: FB%"*   *sA B B3BcFtt|jS)a5Return the hashable sequence in multiset form with values being the multiplicity of the item in the sequence. Examples ======== >>> from sympy.utilities.iterables import multiset >>> multiset('mississippi') {'i': 4, 'm': 1, 'p': 2, 's': 4} See Also ======== group )dictritems)rPs r multisetru s"  ""$ %%r+cdkr tdt|d}nG t|}j|kDr(tdjj|sO|dk\r3t ddj |dDcgc] }|dk(rd nd c}St tdd S|dk\rt ddj |dSfd tdzDS#t$rd}YwxYwcc}w) aReturn a list of length ``bits`` corresponding to the binary value of ``n`` with small bits to the right (last). If bits is omitted, the length will be the number required to represent ``n``. If the bits are desired in reversed order, use the ``[::-1]`` slice of the returned list. If a sequence of all bits-length lists starting from ``[0, 0,..., 0]`` through ``[1, 1, ..., 1]`` are desired, pass a non-integer for bits, e.g. ``'all'``. If the bit *string* is desired pass ``str=True``. Examples ======== >>> from sympy.utilities.iterables import ibin >>> ibin(2) [1, 0] >>> ibin(2, 4) [0, 0, 1, 0] If all lists corresponding to 0 to 2**n - 1, pass a non-integer for bits: >>> bits = 2 >>> for i in ibin(2, 'all'): ... print(i) (0, 0) (0, 1) (1, 0) (1, 1) If a bit string is desired of a given length, use str=True: >>> n = 123 >>> bits = 10 >>> ibin(n, bits, str=True) '0001111011' >>> ibin(n, bits, str=True)[::-1] # small bits left '1101111000' >>> list(ibin(3, 'all', str=True)) ['000', '001', '010', '011', '100', '101', '110', '111'] rz negative numbers are not allowedNz`bits` must be >= {}r01rT) repetitionc3ZK|]"}t|ddjd$yw)rNrx)binrjust)rrrFs r r!zibin..{s(BCF12J$$Q,Bs(+)r;r bit_lengthformatr|r} variationsr')rFbitsstrrs` r ibinr6sX 1u;<<q A | C$>> from sympy import variations >>> list(variations([1, 2], 2)) [(1, 2), (2, 1)] ``variations(seq, n, True)`` will return the `N^n` permutations obtained by allowing repetition of elements: >>> list(variations([1, 2], 2, repetition=True)) [(1, 1), (1, 2), (2, 1), (2, 2)] If you ask for more items than are in the set you get the empty set unless you allow repetitions: >>> list(variations([0, 1], 3, repetition=False)) [] >>> list(variations([0, 1], 3, repetition=True))[:4] [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)] .. seealso:: `itertools.permutations `_, `itertools.product `_ rr)r)repeat)tupler%rEr r )rPrFrzs r rr~sPF Cj s8a<8OC## 6; 3q) )r+c |h|s3tjfdttdzDStjfdttdzDS|s t |St |S)a0Generates all `k`-subsets (combinations) from an `n`-element set, ``seq``. A `k`-subset of an `n`-element set is any subset of length exactly `k`. The number of `k`-subsets of an `n`-element set is given by ``binomial(n, k)``, whereas there are `2^n` subsets all together. If `k` is ``None`` then all `2^n` subsets will be returned from shortest to longest. Examples ======== >>> from sympy import subsets ``subsets(seq, k)`` will return the `\frac{n!}{k!(n - k)!}` `k`-subsets (combinations) without repetition, i.e. once an item has been removed, it can no longer be "taken": >>> list(subsets([1, 2], 2)) [(1, 2)] >>> list(subsets([1, 2])) [(), (1,), (2,), (1, 2)] >>> list(subsets([1, 2, 3], 2)) [(1, 2), (1, 3), (2, 3)] ``subsets(seq, k, repetition=True)`` will return the `\frac{(n - 1 + k)!}{k!(n - 1)!}` combinations *with* repetition: >>> list(subsets([1, 2], 2, repetition=True)) [(1, 1), (1, 2), (2, 2)] If you ask for more items than are in the set you get the empty set unless you allow repetitions: >>> list(subsets([0, 1], 3, repetition=False)) [] >>> list(subsets([0, 1], 3, repetition=True)) [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)] c36K|]}t|ywr/rrrrPs r r!zsubsets..s"(F,-)5S!(<(Frc36K|]}t|ywr/)rrs r r!zsubsets..s#(F,-)Fc1(M(Fr)r from_iterabler'r%rr)rPrrzs` r subsetsrsT y&&(F16s3x!|1D(FG G&&(F16s3x!|1D(FG GQ' '0a8 8r+c#BKt|}|D] }||vs| yw)a, Only yield elements from `iterator` that do not occur in `exclude`. Parameters ========== iterator : iterable iterator to take elements from exclude : iterable elements to exclude Returns ======= iterator : iterator filtered iterator N)r1)iteratorexcluders r filter_symbolsrs-&'lG  G Gsc/~Kt|xsg}|ddlm}|} ||}||g|i|}||vr||dz } w)a Generate an infinite stream of Symbols consisting of a prefix and increasing subscripts provided that they do not occur in ``exclude``. Parameters ========== prefix : str, optional The prefix to use. By default, this function will generate symbols of the form "x0", "x1", etc. cls : class, optional The class to use. By default, it uses ``Symbol``, but you can also use ``Wild`` or ``Dummy``. start : int, optional The start number. By default, it is 0. exclude : list, tuple, set of cls, optional Symbols to be excluded. *args, **kwargs Additional positional and keyword arguments are passed to the *cls* class. Returns ======= sym : Symbol The subscripted symbols. r)Symbolr)r1 sympy.corer) prefixr7startrr8 assumptionsrnamers r numbered_symbolsrsa>'-R G { & '  +t +{ + G G   s;=cddlm}ddl}|j}|x|_} |||_|j S#||_wxYw)aReturn the printed output of func(). ``func`` should be a function without arguments that produces output with print statements. >>> from sympy.utilities.iterables import capture >>> from sympy import pprint >>> from sympy.abc import x >>> def foo(): ... print('hello world!') ... >>> 'hello' in capture(foo) # foo, not foo() True >>> capture(lambda: pprint(2/x)) '2\n-\nx\n' r)StringION)iorsysstdoutgetvalue)funcrrrfiles r capturer+sI$ ZZF "CJ  ==? s A A c|s2tt}|D]}|||j||Sggfx}\}}|D]} |||j|||fS#ttf$r t dwxYw)a Sift the sequence, ``seq`` according to ``keyfunc``. Returns ======= When ``binary`` is ``False`` (default), the output is a dictionary where elements of ``seq`` are stored in a list keyed to the value of keyfunc for that element. If ``binary`` is True then a tuple with lists ``T`` and ``F`` are returned where ``T`` is a list containing elements of seq for which ``keyfunc`` was ``True`` and ``F`` containing those elements for which ``keyfunc`` was ``False``; a ValueError is raised if the ``keyfunc`` is not binary. Examples ======== >>> from sympy.utilities import sift >>> from sympy.abc import x, y >>> from sympy import sqrt, exp, pi, Tuple >>> sift(range(5), lambda x: x % 2) {0: [0, 2, 4], 1: [1, 3]} sift() returns a defaultdict() object, so any key that has no matches will give []. >>> sift([x], lambda x: x.is_commutative) {True: [x]} >>> _[False] [] Sometimes you will not know how many keys you will get: >>> sift([sqrt(x), exp(x), (y**x)**2], ... lambda x: x.as_base_exp()[0]) {E: [exp(x)], x: [sqrt(x)], y: [y**(2*x)]} Sometimes you expect the results to be binary; the results can be unpacked by setting ``binary`` to True: >>> sift(range(4), lambda x: x % 2, binary=True) ([1, 3], [0, 2]) >>> sift(Tuple(1, pi), lambda x: x.is_rational, binary=True) ([1], [pi]) A ValueError is raised if the predicate was not actually binary (which is a good test for the logic where sifting is used and binary results were expected): >>> unknown = exp(1) - pi # the rationality of this is unknown >>> args = Tuple(1, pi, unknown) >>> sift(args, lambda x: x.is_rational, binary=True) Traceback (most recent call last): ... ValueError: keyfunc gave non-binary output The non-binary sifting shows that there were 3 keys generated: >>> set(sift(args, lambda x: x.is_rational).keys()) {None, False, True} If you need to sort the sifted items it might be better to use ``ordered`` which can economically apply multiple sort keys to a sequence while sorting. See Also ======== ordered zkeyfunc gave non-binary output)rrGr? IndexError TypeErrorr;)rPkeyfuncbinaryr)rsiftFTs r rrIsR    $A gajM  # $b&D41a ? ?   # #A &? a4KI& ?=> > ?s A$$A?c^tt||Dcgc]\}}| c}}Scc}}w)z+Return ``n`` items from ``iter`` iterator. )rHr')rErFr(values r takers%#&uQx#6 8xq%U 88 8s )c:i}|D]}|j||S)z-Merge dictionaries into a single dictionary. )update)dictsmergedrss r dict_mergers) F d Mr+c tsgStdk(rdSdttdDD]+tfdttDr+ndz ddS)alReturn the subsequence that is a common start of sequences in ``seqs``. >>> from sympy.utilities.iterables import common_prefix >>> common_prefix(list(range(3))) [0, 1, 2] >>> common_prefix(list(range(3)), list(range(4))) [0, 1, 2] >>> common_prefix([1, 2, 3], [1, 2, 5]) [1, 2] >>> common_prefix([1, 2, 3], [1, 3, 5]) [1] rrc32K|]}t|ywr/r%rrs r r!z common_prefix..s,!s1v,c3@K|]}|dk(ywrNrrrrseqss r r!z common_prefix..&F471:a+FNr&r%r'minrrs`@r common_prefixrs~ t9 TaAw A 3,t,, -FU3t95EFF  Q 72A;r+c tsgStdk(rdSdtdtdD dz dD]+tfdttDr+ndzdk(rgSddzdS)afReturn the subsequence that is a common ending of sequences in ``seqs``. >>> from sympy.utilities.iterables import common_suffix >>> common_suffix(list(range(3))) [0, 1, 2] >>> common_suffix(list(range(3)), list(range(4))) [] >>> common_suffix([1, 2, 3], [9, 2, 3]) [2, 3] >>> common_suffix([1, 2, 3], [9, 7, 3]) [3] rrrwc32K|]}t|ywr/rrs r r!z common_suffix..s1qCF1rc3@K|]}|dk(ywrrrs r r!z common_suffix..rrNrrs`@r common_suffixrs t9 TaAw A 21D111A5r :FU3t95EFF  QBw Awq1uvr+c#VKt|}t|D] }|d|dzyw)z Generate all prefixes of a sequence. Examples ======== >>> from sympy.utilities.iterables import prefixes >>> list(prefixes([1,2,3,4])) [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]] Nrr%r'rPrFrs r prefixesrs4 CA 1X&1q5ks')c#\Kt|}t|D]}|||z dz dyw)z Generate all postfixes of a sequence. Examples ======== >>> from sympy.utilities.iterables import postfixes >>> list(postfixes([1,2,3,4])) [[4], [3, 4], [2, 3, 4], [1, 2, 3, 4]] rNrrs r postfixesrs8 CA 1X!a%!)*os*,c|\}}g}t|}t|}|jd|D|d}t||d}|r|j }|j |t|D]|\}}||k(s |j ||f|D] \} } || k(s /||} t|D]&\} } || }| |kDs|j| |k|j |~|r|r td|S)a Topological sort of graph's vertices. Parameters ========== graph : tuple[list, list[tuple[T, T]] A tuple consisting of a list of vertices and a list of edges of a graph to be sorted topologically. key : callable[T] (optional) Ordering key for vertices on the same level. By default the natural (e.g. lexicographic) ordering is used (in this case the base type must implement ordering relations). Examples ======== Consider a graph:: +---+ +---+ +---+ | 7 |\ | 5 | | 3 | +---+ \ +---+ +---+ | _\___/ ____ _/ | | / \___/ \ / | V V V V | +----+ +---+ | | 11 | | 8 | | +----+ +---+ | | | \____ ___/ _ | | \ \ / / \ | V \ V V / V V +---+ \ +---+ | +----+ | 2 | | | 9 | | | 10 | +---+ | +---+ | +----+ \________/ where vertices are integers. This graph can be encoded using elementary Python's data structures as follows:: >>> V = [2, 3, 5, 7, 8, 9, 10, 11] >>> E = [(7, 11), (7, 8), (5, 11), (3, 8), (3, 10), ... (11, 2), (11, 9), (11, 10), (8, 9)] To compute a topological sort for graph ``(V, E)`` issue:: >>> from sympy.utilities.iterables import topological_sort >>> topological_sort((V, E)) [3, 5, 7, 8, 11, 2, 9, 10] If specific tie breaking approach is needed, use ``key`` parameter:: >>> topological_sort((V, E), key=lambda v: -v) [7, 5, 11, 3, 10, 8, 9, 2] Only acyclic graphs can be sorted. If the input graph has a cycle, then ``ValueError`` will be raised:: >>> topological_sort((V, E + [(10, 7)])) Traceback (most recent call last): ... ValueError: cycle detected References ========== .. [1] https://en.wikipedia.org/wiki/Topological_sorting c3&K|] \}}| ywr/r)rvus r r!z#topological_sort..Zs(da(c|Sr/r)rs r keyztopological_sort..key]sLr+T)rreversezcycle detected) r1rGdifference_updatesortedpopr?remove enumerateinsertr;)graphrVELSnoderr_u_vkvrrkss r topological_sortr s!N DAq A AA QA(a(( {  qc4(A uuw G $DAqDy!Q  $FBBw $QB )! $1 V7HHQN! $ # $ . )**r+c|\}}|Dcic]}|g}}|D]\}}||j|t||Scc}w)a Strongly connected components of a directed graph in reverse topological order. Parameters ========== G : tuple[list, list[tuple[T, T]] A tuple consisting of a list of vertices and a list of edges of a graph whose strongly connected components are to be found. Examples ======== Consider a directed graph (in dot notation):: digraph { A -> B A -> C B -> C C -> B B -> D } .. graphviz:: digraph { A -> B A -> C B -> C C -> B B -> D } where vertices are the letters A, B, C and D. This graph can be encoded using Python's elementary data structures as follows:: >>> V = ['A', 'B', 'C', 'D'] >>> E = [('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'B'), ('B', 'D')] The strongly connected components of this graph can be computed as >>> from sympy.utilities.iterables import strongly_connected_components >>> strongly_connected_components((V, E)) [['D'], ['B', 'C'], ['A']] This also gives the components in reverse topological order. Since the subgraph containing B and C has a cycle they must be together in a strongly connected component. A and D are connected to the rest of the graph but not in a cyclic manner so they appear as their own strongly connected components. Notes ===== The vertices of the graph must be hashable for the data structures used. If the vertices are unhashable replace them with integer indices. This function uses Tarjan's algorithm to compute the strongly connected components in `O(|V|+|E|)` (linear) time. References ========== .. [1] https://en.wikipedia.org/wiki/Strongly_connected_component .. [2] https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm See Also ======== sympy.utilities.iterables.connected_components )r?_strongly_connected_components)GrrviGmapv1v2s r strongly_connected_componentsrsZd DAq rBF D B R )!T 22 s Ac0 i i t g g t} fd} fd}|D]\}| vr|| s d\}}t||}||ur ||n&| vr ||n| vrt | | |< rJ^ S)zAMore efficient internal routine for strongly_connected_componentscxt}|x|<|<d|<j|t|fyr/)r%r?rE)rindexr callstackr$lowlinkstacks r rz-_strongly_connected_components..startsBE "'' WQZa!T$q']+,r+c:||k(r\jdg}|d|ur*|jjd|d|ur*j|dddj\}}rd\}}t|||<yy)Nrrw)popitemr?rr) r componentrr(r componentsr$rrs r finishz._strongly_connected_components..finishs 2;'"+ %+,IB-r)  !34B-r)   i"o . A bMEBgbk72;7GBK r+rw)rrcr^r)rrnomorerrrrrfrrrr$rrs ` @@@@@r rrs(GG MEIJ XF-- 8 8< <  amGBc6"BV|r 7"b u!'"+wr{;  <" r+cl|\}}g}|D]\}}|j||f||fgt||fS)a Connected components of an undirected graph or weakly connected components of a directed graph. Parameters ========== G : tuple[list, list[tuple[T, T]] A tuple consisting of a list of vertices and a list of edges of a graph whose connected components are to be found. Examples ======== Given an undirected graph:: graph { A -- B C -- D } .. graphviz:: graph { A -- B C -- D } We can find the connected components using this function if we include each edge in both directions:: >>> from sympy.utilities.iterables import connected_components >>> V = ['A', 'B', 'C', 'D'] >>> E = [('A', 'B'), ('B', 'A'), ('C', 'D'), ('D', 'C')] >>> connected_components((V, E)) [['A', 'B'], ['C', 'D']] The weakly connected components of a directed graph can found the same way. Notes ===== The vertices of the graph must be hashable for the data structures used. If the vertices are unhashable replace them with integer indices. This function uses Tarjan's algorithm to compute the connected components in `O(|V|+|E|)` (linear) time. References ========== .. [1] https://en.wikipedia.org/wiki/Component_%28graph_theory%29 .. [2] https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm See Also ======== sympy.utilities.iterables.strongly_connected_components )r=r)rrr E_undirectedrrs r connected_componentsrsQN DAqL2Bb"XBx012 (!\): ;;r+cTt|dk(rgS|t|z}||d|d|zS)z Left rotates a list x by the number of steps specified in y. Examples ======== >>> from sympy.utilities.iterables import rotate_left >>> a = [0, 1, 2] >>> rotate_left(a, 1) [1, 2, 0] rNrr3ys r rotate_leftrgs7 1v{  CF A QR51Ra5=r+clt|dk(rgSt||t|zz }||d|d|zS)z Right rotates a list x by the number of steps specified in y. Examples ======== >>> from sympy.utilities.iterables import rotate_right >>> a = [0, 1, 2] >>> rotate_right(a, 1) [2, 0, 1] rNrrs r rotate_rightrzs@ 1v{  ASVA QR51Ra5=r+cddlm}||}||z}dgt|z}d}tdt|D]}||}|||z dz }|dk7rI||||zdzk7r;||||||zdzkr||z dz }||}|dk7r||||zdzk7r;||||zdzk7r|||||kr|}d|||z <|dz|||z <|S)a Returns the number of steps of left rotation required to obtain lexicographically minimal string/list/tuple, etc. Examples ======== >>> from sympy.utilities.iterables import least_rotation, rotate_left >>> a = [3, 1, 5, 1, 2] >>> least_rotation(a) 3 >>> rotate_left(a, _) [1, 2, 3, 1, 5] References ========== .. [1] https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation rIdrwr)(sympy.functions.elementary.miscellaneousrr%r') r3rrrfrrsjrs r least_rotationr s*< {"C AA s1v A A 1SV_  qT ac!eH2g"!A#a%.2wQqs1uX&aCE!A2g"!A#a%. 1Q3q5>2wQqT"AacFqSAacF  Hr+c #fKddlm}|t|tret d|j Dr t dt|j }||kDry||Dcgc] }|||g }}nBt|}t|}||kDry t|}||Dcgc] }|||f }}~ntd|D}||kDs|sgyt|D]m\}\}}||k\r |g|z|d z }tt||dd D]9}t!d||z ||d zdD]}|g|z|z} t| |k(s|  ;oycc}wcc}w#t$r=t||}t|dDcgc] }t|ncc}w}}YwxYww) a Return the unique combinations of size ``n`` from multiset ``m``. Examples ======== >>> from sympy.utilities.iterables import multiset_combinations >>> from itertools import combinations >>> [''.join(i) for i in multiset_combinations('baby', 3)] ['abb', 'aby', 'bby'] >>> def count(f, s): return len(list(f(s, 3))) The number of combinations depends on the number of letters; the number of unique combinations depends on how the letters are repeated. >>> s1 = 'abracadabra' >>> s2 = 'banana tree' >>> count(combinations, s1), count(multiset_combinations, s1) (165, 23) >>> count(combinations, s2), count(multiset_combinations, s2) (165, 54) rorderedNc38K|]}t|dkywrrrrs r r!z(multiset_combinations..5Q6!9q=5counts cannot be negativeFrYc3&K|] \}}| ywr/rrrrs r r!z(multiset_combinations..s da rrrw)sympy.core.sortingr r6rsanyvaluesr;rKrGr%rurr[rr'rmultiset_combinations) r)rFrZr NrrrrrTs r rrs4+y a 5!((*55 !<==AHHJA1u$+AJ/q!QqT/A/QAAA1u @QK(/ 31a1Y33   a 1uA"1 !IAv1Avc!e E3q!9a, !.tQUAa!efIF!AQB2w!| ! !  !'04 @$&+A&>?T!W??? @s[A-F1/E=F1E(2E#E(BF1F1#E(()F.F$#F.+F1-F..F1c#Kddlm}|t|trFt d|j Dr t d||Dcgc] }|||g }}n4t||}t|dDcgc] }t|}}~|Dcgc] }|ddkDs |}}td |D}|r |||kDs|dkr|s||dk(rgy|dk(r|D] \}} |g yt|dk(r1|d\}} || n|| kr|nd} t| Dcgc]}|c}ytd |Dr2t|D cgc]\}} | c} }|D]} t| y||n|}t|D]H\}\}} ||dxxdzcc<td|dz |D] } | s|g| z||dxxdz cc<Jycc}wcc}wcc}wcc}wcc} }ww) aw Return the unique permutations of multiset ``m``. Examples ======== >>> from sympy.utilities.iterables import multiset_permutations >>> from sympy import factorial >>> [''.join(i) for i in multiset_permutations('aab')] ['aab', 'aba', 'baa'] >>> factorial(len('banana')) 720 >>> len(list(multiset_permutations('banana'))) 60 rr Nc38K|]}t|dkywrrrs r r!z(multiset_permutations.. rrrFrrc3&K|] }|d ywrr)rgis r r!z(multiset_permutations..s !be !rc3,K|] \}}|dk(ywrrrs r r!z(multiset_permutations..s #1Q!V #)rr r6rsrrr;rGr[rKr%r'r&r rmultiset_permutations) r)sizerZr rrrdoSUMrprs r r r s +y a 5!((*55 !<==$+AJ/q!QqT/A/WQZ A"'E":;Qa;A;  &BqEAI" &B & !b ! !C !tczTAXdldaiH  DAq#I  RA!u1ADAID1(#Qq## # # #R0TQq0$7 Aq'M 'tS"2 IAv1 qE!HMH*42> "#'M " qE!HMH  /0< &$0sPAG+G#G+GG+ G(G,A5G+! G *"G+ G% AG+47G+c|t|dz}nt|tr||}}t|Dcgc]}g}}t |D]\}}||j |||Scc}w)a Return the partition of seq as specified by the partition vector. Examples ======== >>> from sympy.utilities.iterables import _partition >>> _partition('abcde', [1, 0, 1, 2, 0]) [['b', 'e'], ['a', 'c'], ['d']] Specifying the number of bins in the partition is optional: >>> _partition('abcde', [1, 0, 1, 2, 0], 3) [['b', 'e'], ['a', 'c'], ['d']] The output of _set_partitions can be passed as follows: >>> output = (3, [1, 0, 1, 2, 0]) >>> _partition('abcde', *output) [['b', 'e'], ['a', 'c'], ['d']] See Also ======== combinatorics.partitions.Partition.from_rgs r)maxr6rNr'rr?)rPvectorr)rr$rs r _partitionr(*sv8 y K!O FC v1XA&!1 ! CF H s A*c#6Kdg|z}dg|z}d}||f||k7r||} |dz}||}||dk7rnd||<|dz }|||<|dz }|||z z }|dxx||z z cc<||k(r d||<|dz }||dz xxdzcc<||xxdz cc<||f||k7r{yyw)a Cycle through all partitions of n elements, yielding the current number of partitions, ``m``, and a mutable list, ``q`` such that ``element[i]`` is in part ``q[i]`` of the partition. NOTE: ``q`` is modified in place and generally should not be changed between function calls. Examples ======== >>> from sympy.utilities.iterables import _set_partitions, _partition >>> for m, q in _set_partitions(3): ... print('%s %s %s' % (m, q, _partition('abc', q, m))) 1 [0, 0, 0] [['a', 'b', 'c']] 2 [0, 0, 1] [['a', 'b'], ['c']] 2 [0, 1, 0] [['a', 'c'], ['b']] 2 [0, 1, 1] [['a'], ['b', 'c']] 3 [0, 1, 2] [['a'], ['b'], ['c']] Notes ===== This algorithm is similar to, and solves the same problem as, Algorithm 7.2.1.5H, from volume 4A of Knuth's The Art of Computer Programming. Knuth uses the term "restricted growth string" where this code refers to a "partition vector". In each case, the meaning is the same: the value in the ith element of the vector specifies to which part the ith set element is to be assigned. At the lowest level, this code implements an n-digit big-endian counter (stored in the array q) which is incremented (with carries) to get the next partition in the sequence. A special twist is that a digit is constrained to be at most one greater than the maximum of all the digits to the left of it. The array p maintains this maximum, so that the code can efficiently decide when a digit can be incremented in place or whether it needs to be reset to 0 and trigger a carry to the next digit. The enumeration starts with all the digits 0 (which corresponds to all the set elements being assigned to the same 0th part), and ends with 0123...n, which corresponds to each set element being assigned to a different, singleton, part. This routine was rewritten to use 0-based lists while trying to preserve the beauty and efficiency of the original algorithm. References ========== .. [1] Nijenhuis, Albert and Wilf, Herbert. (1978) Combinatorial Algorithms, 2nd Ed, p 91, algorithm "nexequ". Available online from https://www.math.upenn.edu/~wilf/website/CombAlgDownld.html (viewed November 17, 2012). rrNr)rFr$qncr)rs r _set_partitionsr,Psl AA AA B a%K '  FA!AtqyAaD  Q! Q a!e  !A  7AbE !GB !a%A  ! !e % 's BBBc #&Kt|tr|}|r||kDrytt|}|dk(r |ddgyt |D]S\}}|||k(st|Dcgc]}g}}t|D]}|||j |||Uyt |dk(rt|tr|g}t|svt |}|r||kDry|dk(r |ddgy|dd}t||dD]>\}} |||k(sg}t| D]} |j|| zg| | z|@yddl m } t| |}t |}|r||kDry|dk(r |ddgytt|d\} } t | t |krU|r4t!}|j#| |dz |D]}t%|| yt'| D]}t%|| yt |D]q\}}|||k(st|Dcgc]}g}}t|D]}|||j ||Dcgc]}|Dcgc]}|| c}c}}sycc}wcc}wcc}wcc}}ww)a Return unique partitions of the given multiset (in list form). If ``m`` is None, all multisets will be returned, otherwise only partitions with ``m`` parts will be returned. If ``multiset`` is an integer, a range [0, 1, ..., multiset - 1] will be supplied. Examples ======== >>> from sympy.utilities.iterables import multiset_partitions >>> list(multiset_partitions([1, 2, 3, 4], 2)) [[[1, 2, 3], [4]], [[1, 2, 4], [3]], [[1, 2], [3, 4]], [[1, 3, 4], [2]], [[1, 3], [2, 4]], [[1, 4], [2, 3]], [[1], [2, 3, 4]]] >>> list(multiset_partitions([1, 2, 3, 4], 1)) [[[1, 2, 3, 4]]] Only unique partitions are returned and these will be returned in a canonical order regardless of the order of the input: >>> a = [1, 2, 2, 1] >>> ans = list(multiset_partitions(a, 2)) >>> a.sort() >>> list(multiset_partitions(a, 2)) == ans True >>> a = range(3, 1, -1) >>> (list(multiset_partitions(a)) == ... list(multiset_partitions(sorted(a)))) True If m is omitted then all partitions will be returned: >>> list(multiset_partitions([1, 1, 2])) [[[1, 1, 2]], [[1, 1], [2]], [[1, 2], [1]], [[1], [1], [2]]] >>> list(multiset_partitions([1]*3)) [[[1, 1, 1]], [[1], [1, 1]], [[1], [1], [1]]] Counting ======== The number of partitions of a set is given by the bell number: >>> from sympy import bell >>> len(list(multiset_partitions(5))) == bell(5) == 52 True The number of partitions of length k from a set of size n is given by the Stirling Number of the 2nd kind: >>> from sympy.functions.combinatorial.numbers import stirling >>> stirling(5, 2) == len(list(multiset_partitions(5, 2))) == 15 True These comments on counting apply to *sets*, not multisets. Notes ===== When all the elements are the same in the multiset, the order of the returned partitions is determined by the ``partitions`` routine. If one is counting partitions then it is better to use the ``nT`` function. See Also ======== partitions sympy.combinatorics.partitions.Partition sympy.combinatorics.partitions.IntegerPartition sympy.functions.combinatorial.numbers.nT NrTr!rr F)r6rNrGr'r,r?r%r has_variety partitionsrr=rr rHr[r enum_rangerr)rur)rFr+r*rrTr3r!r$rr elementsmultiplicitiesmptstaters r multiset_partitionsr6sZ(C  Q a> 6A;-  %Q' EByB!G"'),Qb,,q1AqtHOOHQK01    8}j37: x  M Q  6A;-   RaL!!QT2 GD!yDAI*AIIqseAaDj)*   /)* M Q  6A;-   $'h(>#? . x=3x= (02 ^^NAaCC8E&uh7787~F8E&uh778)+ AA9a&+Bi0"0B0"1X+1Q4*+=?@3AHQK3@@  Ao-r14@sVAJ J% I<.B JDJ J" J+.J J " J.J 3JJ  Jc#K|dks||dks||dks |r|r||z|kr|rdifyiy||}n t||}t|xs||}t|t|t|}}}t||\}}||i}|g}|rd||<|j|||z t |z }|r,t |j |jfn|j|dgk7r|ddk(r|d=|jd} || z }nd} |d} || dz x} || <| | z } | dk(r|d=|| =|dz }| dz} t| | \}}|t |z} | |kDr|syS||| <|j| |rd||<|j| || z}|r,t |j |jfn|j|dgk7ryyw)aGenerate all partitions of positive integer, n. Each partition is represented as a dictionary, mapping an integer to the number of copies of that integer in the partition. For example, the first partition of 4 returned is {4: 1}, "4: one of them". Parameters ========== n : int m : int, optional limits number of parts in partition (mnemonic: m, maximum parts) k : int, optional limits the numbers that are kept in the partition (mnemonic: k, keys) size : bool, default: False If ``True``, (M, P) is returned where M is the sum of the multiplicities and P is the generated partition. If ``False``, only the generated partition is returned. Examples ======== >>> from sympy.utilities.iterables import partitions The numbers appearing in the partition (the key of the returned dict) are limited with k: >>> for p in partitions(6, k=2): # doctest: +SKIP ... print(p) {2: 3} {1: 2, 2: 2} {1: 4, 2: 1} {1: 6} The maximum number of parts in the partition (the sum of the values in the returned dict) are limited with m (default value, None, gives partitions from 1 through n): >>> for p in partitions(6, m=2): # doctest: +SKIP ... print(p) ... {6: 1} {1: 1, 5: 1} {2: 1, 4: 1} {3: 2} References ========== .. [1] modified from Tim Peter's version to allow for k and m values: https://code.activestate.com/recipes/218332-generator-for-integer-partitions/ See Also ======== sympy.combinatorics.partitions.Partition sympy.combinatorics.partitions.IntegerPartition rNrrw) rrrLr?boolrKrcopyr) rFr)rr!r*rmskeysroomreusernewcountneeds r r0r0=s%v Q !a% !a% aAaC!G R%K Hy  1I AFAAQiF1I!qA !Q>> from sympy.utilities.iterables import ordered_partitions All partitions of 5 in ascending lexicographical: >>> for p in ordered_partitions(5): ... print(p) [1, 1, 1, 1, 1] [1, 1, 1, 2] [1, 1, 3] [1, 2, 2] [1, 4] [2, 3] [5] Only partitions of 5 with two parts: >>> for p in ordered_partitions(5, 2): ... print(p) [1, 4] [2, 3] When ``m`` is given, a given list objects will be used more than once for speed reasons so you will not see the correct partitions unless you make a copy of each as it is generated: >>> [p for p in ordered_partitions(7, 3)] [[1, 1, 1], [1, 1, 1], [1, 1, 1], [2, 2, 2]] >>> [list(p) for p in ordered_partitions(7, 3)] [[1, 1, 5], [1, 2, 4], [1, 3, 3], [2, 2, 3]] When ``n`` is a multiple of ``m``, the elements are still sorted but the partitions themselves will be *unordered* if sort is False; the default is to return them in ascending lexicographical order. >>> for p in ordered_partitions(6, 2): ... print(p) [1, 5] [2, 4] [3, 3] But if speed is more important than ordering, sort can be set to False: >>> for p in ordered_partitions(6, 2, sort=False): ... print(p) [1, 5] [3, 3] [2, 4] References ========== .. [1] Generating Integer Partitions, [online], Available: https://jeromekelleher.net/generating-integer-partitions.html .. [2] Jerome Kelleher and Barry O'Sullivan, "Generating All Partitions: A Comparison Of Two Encodings", [online], Available: https://arxiv.org/pdf/0909.2331v2.pdf rNrwrrF)sortT)r'ordered_partitionsr%) rFr)rBarrr3wbaxmirs r rCrCs<\ 1u !a%y CE  !e FA!qAq1u*!QQq1u*AAq&!!QiQQ q& q5AaD!qABQ%K!!e" ac ac!e q!Q$(# )AAAAaCAGa1f,QU;%BRB.01q1u1ArcdGG c"fArcdG %  1+)B0BTB)24"5Q1q5"52#$#$#b&2#$)) )2 #6s7AF-FFAF +F E;>> from sympy.utilities.iterables import binary_partitions >>> for i in binary_partitions(5): ... print(i) ... [4, 1] [2, 2, 1] [2, 1, 1, 1] [1, 1, 1, 1, 1] References ========== .. [1] TAOCP 4, section 7.2.1.5, problem 64 r)ceillog2rrN)mathrJrKrNr?r%)rFrJrKpoweracc partitionlast_numr3s r binary_partitionsrQIs]4 DaM" #E CI  ;!    U # 5LC !   9~!QU+H a- X ! #"#Ih    Q  MH (!&/&99Ihl #A !eC NX-11qb1fg&A &' (#a !e a-$ #a%KsAD B(D :D  D c ddlm}ddlm}t |t t ||fryt  tfd|DS#t$r,t|ttt|k7cYSwxYw)a'Return True if there are any duplicate elements in ``seq``. Examples ======== >>> from sympy import has_dups, Dict, Set >>> has_dups((1, 2, 1)) True >>> has_dups(range(3)) False >>> all(has_dups(c) is False for c in (set(), Set(), dict(), Dict())) True r)Dict)SetFc3NK|]}|vsj|sdywTN)add)rruniques r r!zhas_dups..s!EAV vzz!}4Es%%) sympy.core.containersrSsympy.sets.setsrTr6rsr1rrr%rGuniq)rPrSrTrXs @r has_dupsr\si+##c4-. UF0EEEE 03x3tDI///0sA2A;:A;cHt|D]\}}|dk(r|}|k7syy)zReturn True if there are any different elements in ``seq``. Examples ======== >>> from sympy import has_variety >>> has_variety((1, 2, 1)) True >>> has_variety((1, 1, 1)) False rTF)r)rPrrrbs r r/r/s6#1 6HH}  r+c#K tfd} t}|xsg}tD]'\}}||vr |j |r||)y#t$rdYZwxYw#t$ra|vr|||j |t drtdzd|Ed{7Yyt|Ed{7YywxYww)a Yield unique elements from ``seq`` as an iterator. The second parameter ``result`` is used internally; it is not necessary to pass anything for this. Note: changing the sequence during iteration will raise a RuntimeError if the size of the sequence is known; if you pass an iterator and advance the iterator you will change the output of this routine but there will be no warning. Examples ======== >>> from sympy.utilities.iterables import uniq >>> dat = [1, 4, 1, 5, 4, 2, 1, 2] >>> type(uniq(dat)) in (list, tuple) False >>> list(uniq(dat)) [1, 4, 5, 2] >>> list(uniq(x for x in dat)) [1, 4, 5, 2] >>> list(uniq([[1], [2, 1], [1]])) [[1], [2, 1]] Nc>tk7r tdyy)Nz&sequence changed size during iteration)r% RuntimeError)rFrPsr checkzuniq..checks' =SX]GH H+=r+ __getitem__r)r%rr1rrWr?r<r[)rPrAraseenrrrFs` @r r[r[s4 HI )u2cN DAqI!    ) F?G G MM!  3 &CAK0 0 0C( ( ()szC AC%A/A/ A/C A,)C+A,,C/A C9B<:C?CCCCCCCc#Kt|}|dkr td|dk(rdy |dk(r ddy |dk(r gdEd {y |dz }d gd g|zz}tt|} t |d }t|D]}||s |||dkDs|||f}|\}}|y |||z}||||c||<||<||||c||<||<|d k(s||k(s||||z||kDrd ||<t|D]}||||kDsd||<t|dz|D]}||||kDsd ||<7w) a7 Return permutations of [0, 1, ..., n - 1] such that each permutation differs from the last by the exchange of a single pair of neighbors. The ``n!`` permutations are returned as an iterator. In order to obtain the next permutation from a random starting permutation, use the ``next_trotterjohnson`` method of the Permutation class (which generates the same sequence in a different manner). Examples ======== >>> from itertools import permutations >>> from sympy.utilities.iterables import generate_bell >>> from sympy import zeros, Matrix This is the sort of permutation used in the ringing of physical bells, and does not produce permutations in lexicographical order. Rather, the permutations differ from each other by exactly one inversion, and the position at which the swapping occurs varies periodically in a simple fashion. Consider the first few permutations of 4 elements generated by ``permutations`` and ``generate_bell``: >>> list(permutations(range(4)))[:5] [(0, 1, 2, 3), (0, 1, 3, 2), (0, 2, 1, 3), (0, 2, 3, 1), (0, 3, 1, 2)] >>> list(generate_bell(4))[:5] [(0, 1, 2, 3), (0, 1, 3, 2), (0, 3, 1, 2), (3, 0, 1, 2), (3, 0, 2, 1)] Notice how the 2nd and 3rd lexicographical permutations have 3 elements out of place whereas each "bell" permutation always has only two elements out of place relative to the previous permutation (and so the signature (+/-1) of a permutation is opposite of the signature of the previous permutation). How the position of inversion varies across the elements can be seen by tracing out where the largest number appears in the permutations: >>> m = zeros(4, 24) >>> for i, p in enumerate(generate_bell(4)): ... m[:, i] = Matrix([j - 3 for j in list(p)]) # make largest zero >>> m.print_nonzero('X') [XXX XXXXXX XXXXXX XXX] [XX XX XXXX XX XXXX XX XX] [X XXXX XX XXXX XX XXXX X] [ XXXXXX XXXXXX XXXXXX ] See Also ======== sympy.combinatorics.permutations.Permutation.next_trotterjohnson References ========== .. [1] https://en.wikipedia.org/wiki/Method_ringing .. [2] https://stackoverflow.com/questions/4856615/recursive-permutation/4857018 .. [3] https://web.archive.org/web/20160313023044/http://programminggeeks.com/bell-algorithm-for-permutation/ .. [4] https://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm .. [5] Generating involutions, derangements, and relatives by ECO Vincent Vajnovszki, DMTCS vol 1 issue 12, 2010 rzn must be a positive integer)rr)rr)rr))rrr)rrr)rrr)rrr)rrr)rrrNrrwNrw)rr;rGr'r)rFr)oplbigrr(rs r generate_bellrjsB q A1u788Av a  aUUU ESB46\ qN(NC1X "a5QqTCF]QqT'C "DAqyBqE A1qtJAaD!A$a5"Q%LBqE2a5Ava1QAY>> from sympy.utilities.iterables import generate_involutions >>> list(generate_involutions(3)) [(0, 1, 2), (0, 2, 1), (1, 0, 2), (2, 1, 0)] >>> len(list(generate_involutions(4))) 10 References ========== .. [1] https://mathworld.wolfram.com/PermutationInvolution.html N)rGr'r )rFidxr$rs r generate_involutionsrmSsQ8 uQx.C #  A1w!| G s 3A Ac #Kddlm} t}t|j} t| dzkDryt|k(rtEd{y|D] } || | k(s ntDcgc] }| k7s |} }tDcgc] }| k(s |} }dgzd| zk(rT| D]} |< t| Dcgc]}| c}D]} t| | D] \}}||< !dgzddyd| zz dk(rt|j| z dzk(rt | D]\}}| d|| |dzdz}|D]} |< t!|Dcgc]}| c}D]C} ||<t| | D] \}}||< |}| D]}||c|<|<|}Edgzddyfdfdfdt#|j%d tdz Ed{dgzddy#t$r|t t |t }g}D]$}|D]}|||k(s |j|$&t|D]}|Dcgc]}|| ncc}wc}YywxYw7bcc}wcc}wcc}wcc}w7w) aGenerate derangements of the elements of s *in place*. Examples ======== >>> from sympy.utilities.iterables import multiset_derangements, uniq Because the derangements of multisets (not sets) are generated in place, copies of the return value must be made if a collection of derangements is desired or else all values will be the same: >>> list(uniq([i for i in multiset_derangements('1233')])) [[None, None, None, None]] >>> [i.copy() for i in multiset_derangements('1233')] [['3', '3', '1', '2'], ['3', '3', '2', '1']] >>> [''.join(i) for i in multiset_derangements('1233')] ['3312', '3321'] rr Nrrc3RK dd} dd} dd} dd}g}g}g}tt D]M} | ||k(r|j|# ||k(r|j|=|j|Ot||kDst||kDry|D]}| |< |D]}| |< t||t|z D]0}|D]} | | < |D] } | | |< |D]}d |< 2|D]}d |< |D]}d |< yw)zmPlace the last two elements into the partially completed derangement, and yield the results. rrN)r'r%r?r) rDa_ctrFb_ctforced_aforced_b open_freera_placea_posrTrrs r finish_derangementsz2multiset_derangements..finish_derangementss GAJAwqz GAJAwqz s1v (A!u}Q419OOA&qTQYOOA&$$Q' ( x=4 3x=4#7  ABqE  ABqE #Itc(m/CD G  5   a5=BqE H 1   ABqE  ABqE sAD'B-D'52D'c^tDcgc]}| ||k7s|c}Scc}wr/)r')rrrFrTrs r iopenz$multiset_derangements..iopen s/!8Car!u}1CCCs ***c3K|dk(rEd{y |\}}t||D]-}|D]}||< |dz Ed{|D]}d|< /y7P7wNrr) rMmxriir"rwryrTrs r r"z!multiset_derangements..do s 6+, , ,GEAr!%(B/ "BBrFa!e9$$"B!BrF" " -%s!A(A$z'multiset_derangements..0 sAaD!A$<r+r)rr rurrsrr[r?multiset_derangementsr&rr%_set_derangementsr'r rHr rrt)rr r;rhsirrrr}r|inonMiMr$pii1ifillr"rwryrFrTrs` @@@@@@r rrxsn&+  a[ RYY[ B AA  !tax 2w!|$Q'''  a5B; a .1AaDAIQ .E .1X +1! +B + B tqy ABqE 'e'<!'<= AR 21 H  q1  1R4x1}RYY[)QVaZ7u% EAr"1Iacd +E 1 !"7A1Q4"78 22 QZEArBqEA#%a5"Q%LBqE2a5HA   q1/bD ""* "((*"7 8D#d)a-   F1HBqEE  9WT!W-./  B q6R<HHQK   'q) &A#$%a3q6%% % & 2 ( / +(="#8D!sK  H?A K %K&K 9K  K K K * K8K<%K ! K-BK  K B#K 0K1K ?AK(K( J54 KK KK  K cTddl}|jfdfd}t|}t|}t |j d}|d\}}t|} d|z|z } | dkDr|r t d t|D cgc]\} } | |ddk(s| } } } || | t | d| }t|}t|D]} |j| t|}|D]} |j| |ddt|turd j|S|S| t|k(r4t|} |t!d t#||Dr |S(dg| z} d}|t| kDr|d z}||\}} t%| D cgc]} ||  || |k7s| } } t| | krt%| D]} d|| < n3|| | t%| D] } ||| | < |t| kDr|Scc} } wcc} w) a|Return a list of elements in which none are in the same positions as they were originally. If an element fills more than half of the positions then an error will be raised since no derangement is possible. To obtain a derangement of as many items as possible--with some of the most numerous remaining in their original positions--pass `strict=False`. To produce a pseudorandom derangment, pass a pseudorandom selector like `choice` (see below). Examples ======== >>> from sympy.utilities.iterables import random_derangement >>> t = 'SymPy: a CAS in pure Python' >>> d = random_derangement(t) >>> all(i != j for i, j in zip(d, t)) True A predictable result can be obtained by using a pseudorandom generator for the choice: >>> from sympy.core.random import seed, choice as c >>> seed(1) >>> d = [''.join(random_derangement(t, c)) for i in range(5)] >>> assert len(set(d)) != 1 # we got different values By reseeding, the same sequence can be obtained: >>> seed(1) >>> d2 = [''.join(random_derangement(t, c)) for i in range(5)] >>> assert d == d2 Nrctt|dz ddD]2}|d|dz}|j|}||||c||<||<4y)z Knuth shufflerrrwN)r'r%r)rTrr3rchoices r shufflez#random_derangement..shuffleX s_s2w{Ar* (Ar&1q5z"A Aa5"Q%LBqE2a5 (r+c||d|S)z1shuffle rv and return the first n values Nr)rTrFrs r pickz random_derangement..pick^ s  "1v r+c |dSr{rr2s r rz$random_derangement..e s !A$r+rrwrzno derangement possiblec3,K|] \}}||k7ywr/rrrrs r r!z%random_derangement.. s0ca160rr)secretsrrur%rrtr;rrGreversedrrandom_derangementrrMrjoinr&rHr')trstrictrrr;totr|r}rFxsrcoptsstayrTrrars ` @r rr5 sU@~(  !B a&C   /B rFEAr AA 2B Av 67 7 )! ?fq!RVAY?? T2d3Bi  !W$ A FF1I  F + $A IIaB # $"1gnrwwr{4"4CG| !W BK0SQZ00& I- VAXAs2wh,Q!u1#(8Kar!u}1KKt9q="1X% $1%T1 q$A"#BtAwK$s2wh, +@4Ls H H- H%8H%H%c#2Kt|dkryt|dk(r |d|dgyt|dk(r!|d|d|dg|d|d|dgyt|D],}tdt||Dr t |.yw)zd yield derangements of items in ``s`` which are assumed to contain no repeated elements rNrrrec3,K|] \}}||k(ywr/rrs r r!z$_set_derangements.. s0da160r)r%r rrHrGrr$s r rr s  1vz 1v{tQqTl 1v{tQqT1Q4  tQqT1Q4   !_0c!Qi00q'Ms BBBc#Kt|st|Ed{yt|D]}t|y7#w)a Return unique derangements of the elements of iterable ``s``. Examples ======== >>> from sympy.utilities.iterables import generate_derangements >>> list(generate_derangements([0, 1, 2])) [[1, 2, 0], [2, 0, 1]] >>> list(generate_derangements([0, 1, 2, 2])) [[2, 2, 0, 1], [2, 2, 1, 0]] >>> list(generate_derangements([0, 1, 1])) [] See Also ======== sympy.functions.combinatorial.factorials.subfactorial N)r\rrrGrs r generate_derangementsr s?* A;$Q'''&q) Aq'M  (sAA$Ac#|K|dk(r|dkDrydg|zt|dk(ry |dz }||dz k(r|dz}|dk(ry||dz k(r|xxdz cc<t||z dz D]}|||zdz<||dzzdk(r/|r tfdt|dz Dr tw)a  A routine to generate necklaces that may (free=True) or may not (free=False) be turned over to be viewed. The "necklaces" returned are comprised of ``n`` integers (beads) with ``k`` different values (colors). Only unique necklaces are returned. Examples ======== >>> from sympy.utilities.iterables import necklaces, bracelets >>> def show(s, i): ... return ''.join(s[j] for j in i) The "unrestricted necklace" is sometimes also referred to as a "bracelet" (an object that can be turned over, a sequence that can be reversed) and the term "necklace" is used to imply a sequence that cannot be reversed. So ACB == ABC for a bracelet (rotate and reverse) while the two are different for a necklace since rotation alone cannot make the two sequences the same. (mnemonic: Bracelets can be viewed Backwards, but Not Necklaces.) >>> B = [show('ABC', i) for i in bracelets(3, 3)] >>> N = [show('ABC', i) for i in necklaces(3, 3)] >>> set(N) - set(B) {'ACB'} >>> list(necklaces(4, 2)) [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 1), (0, 1, 0, 1), (0, 1, 1, 1), (1, 1, 1, 1)] >>> [show('.o', i) for i in bracelets(4, 2)] ['....', '...o', '..oo', '.o.o', '.ooo', 'oooo'] References ========== .. [1] https://mathworld.wolfram.com/Necklace.html .. [2] Frank Ruskey, Carla Savage, and Terry Min Yih Wang, Generating necklaces, Journal of Algorithms 13 (1992), 414-430; https://doi.org/10.1016/0196-6774(92)90047-G rNrrwc3FK|]}|ddd|dzkywrfr)rrrDs r r!znecklaces.. s00bPQa2h2a76K1K0br")rr'r&)rFrfreerrrDs @r necklacesr s\ Av!a% AA (NAv  Eda!em FABwda!em ! q1uqy! AQ4Aa!eaiL A;! TS0bUZ[\_`[`Ua0b-b(N s A B<A,B<ct||dS)z>Wrapper to necklaces to return a free (unrestricted) necklace.T)r)r)rFrs r braceletsr s Q %%r+c#DKttd|} |dd||dkDr |||||<nkt|dz ddD]W}||dk7s ||dz }t|dz ddD] }|||k(s n|z }t||dzD] }|||z ||<nyw)a This algorithm generates oriented forests. An oriented graph is a directed graph having no symmetric pair of directed edges. A forest is an acyclic graph, i.e., it has no cycles. A forest can also be described as a disjoint union of trees, which are graphs in which any two vertices are connected by exactly one simple path. Examples ======== >>> from sympy.utilities.iterables import generate_oriented_forest >>> list(generate_oriented_forest(4)) [[0, 1, 2, 3], [0, 1, 2, 2], [0, 1, 2, 1], [0, 1, 2, 0], [0, 1, 1, 1], [0, 1, 1, 0], [0, 1, 0, 1], [0, 1, 0, 0], [0, 0, 0, 0]] References ========== .. [1] T. Beyer and S.M. Hedetniemi: constant time generation of rooted trees, SIAM J. Computing Vol. 9, No. 4, November 1980 .. [2] https://stackoverflow.com/questions/1633833/oriented-forest-taocp-algorithm-in-python rwrNr)rGr')rFPr$targetr*offsetrs r generate_oriented_forestr s4 U2q\A e Q4!8QqT7AaD1q5!R( Q419qTAXF"1q5!R0"Q46>!"UF"1a!e_- V}!- ! sA B #B 4,B cddlm}||}t|t||}|s-|ddd}t|t||}t |||}t |t s t|S|S)a Return the rotation of the sequence in which the lexically smallest elements appear first, e.g. `cba \rightarrow acb`. The sequence returned is a tuple, unless the input sequence is a string in which case a string is returned. If ``directed`` is False then the smaller of the sequence and the reversed sequence is returned, e.g. `cba \rightarrow abc`. If ``key`` is not None then it is used to extract a comparison key from each element in iterable. Examples ======== >>> from sympy.combinatorics.polyhedron import minlex >>> minlex((1, 2, 0)) (0, 1, 2) >>> minlex((1, 0, 2)) (0, 2, 1) >>> minlex((1, 0, 2), directed=False) (0, 1, 2) >>> minlex('11010011000', directed=True) '00011010011' >>> minlex('11010011000', directed=False) '00011001011' >>> minlex(('bb', 'aaa', 'c', 'a')) ('a', 'bb', 'aaa', 'c') >>> minlex(('bb', 'aaa', 'c', 'a'), key=len) ('c', 'a', 'bb', 'aaa') rrNrrw)rrrr rr6rr)rPdirectedrrbestrseqrbests r minlexr: soF< {"C sN3C8 9D 4R4yD.3"?@4C()c25;<>> from sympy.utilities.iterables import runs >>> from operator import ge >>> runs([0, 1, 2, 2, 1, 4, 3, 2, 2]) [[0, 1, 2], [2], [1, 4], [3], [2], [2]] >>> runs([0, 1, 2, 2, 1, 4, 3, 2, 2], op=ge) [[0, 1, 2, 2], [1, 4], [3], [2, 2]] rw)rEr^ StopIterationr?)rPrgcyclesruneis r runsri sF s)CCyk  cB b#b'? JJrN  MM# $C         c Ms" A A, A)(A), A87A8c#K|dk(r|r|gytdt|D]$}t||d|dz D] }|d|g|z&yw)azReturns the partition of sequence $l$ into $n$ bins Explanation =========== Given the sequence $l_1 \cdots l_m \in V^+$ where $V^+$ is the Kleene plus of $V$ The set of $n$ partitions of $l$ is defined as: .. math:: \{(s_1, \cdots, s_n) | s_1 \in V^+, \cdots, s_n \in V^+, s_1 \cdots s_n = l_1 \cdots l_m\} Parameters ========== l : Sequence[T] A nonempty sequence of any Python objects n : int A positive integer Yields ====== out : list[Sequence[T]] A list of sequences with concatenation equals $l$. This should conform with the type of $l$. Examples ======== >>> from sympy.utilities.iterables import sequence_partitions >>> for out in sequence_partitions([1, 2, 3, 4], 2): ... print(out) [[1], [2, 3, 4]] [[1, 2], [3, 4]] [[1, 2, 3], [4]] Notes ===== This is modified version of EnricoGiampieri's partition generator from https://stackoverflow.com/questions/13131491/partition-n-items-into-k-bins-in-python-lazily See Also ======== sequence_partitions_empty rN)r'r%sequence_partitionsrhrFrparts r rr shj Av!c  1c!f !'!"q1u5 !DRa5'D.  !!sA A c#K|dkry|dk(r|gytdt|dzD]$}t||d|dz D] }|d|g|z&yw)aReturns the partition of sequence $l$ into $n$ bins with empty sequence Explanation =========== Given the sequence $l_1 \cdots l_m \in V^*$ where $V^*$ is the Kleene star of $V$ The set of $n$ partitions of $l$ is defined as: .. math:: \{(s_1, \cdots, s_n) | s_1 \in V^*, \cdots, s_n \in V^*, s_1 \cdots s_n = l_1 \cdots l_m\} There are more combinations than :func:`sequence_partitions` because empty sequence can fill everywhere, so we try to provide different utility for this. Parameters ========== l : Sequence[T] A sequence of any Python objects (can be possibly empty) n : int A positive integer Yields ====== out : list[Sequence[T]] A list of sequences with concatenation equals $l$. This should conform with the type of $l$. Examples ======== >>> from sympy.utilities.iterables import sequence_partitions_empty >>> for out in sequence_partitions_empty([1, 2, 3, 4], 2): ... print(out) [[], [1, 2, 3, 4]] [[1], [2, 3, 4]] [[1, 2], [3, 4]] [[1, 2, 3], [4]] [[1, 2, 3, 4], []] See Also ======== sequence_partitions rNr)r'r%sequence_partitions_emptyrs r rr stj 1uAvc  1c!fqj !!-aeQU; !DRa5'D.  !!sAAc #K|t||Ed{y|dk(r0t|D]!}t|}t||Ed{#y|dk(rt||Ed{y|dk(r/t||D]}t |D]}t|!y|dk(rt t ||dD]|\}}||k7r t|D]c}g}dx} } t|}t|jD]0\} } t| D]} | | z} |j|| | | } 2|e~ytd|z7377w) a Return sequence ``l`` partitioned into ``k`` bins. Examples ======== The default is to give the items in the same order, but grouped into k partitions without any reordering: >>> from sympy.utilities.iterables import kbins >>> for p in kbins(list(range(5)), 2): ... print(p) ... [[0], [1, 2, 3, 4]] [[0, 1], [2, 3, 4]] [[0, 1, 2], [3, 4]] [[0, 1, 2, 3], [4]] The ``ordered`` flag is either None (to give the simple partition of the elements) or is a 2 digit integer indicating whether the order of the bins and the order of the items in the bins matters. Given:: A = [[0], [1, 2]] B = [[1, 2], [0]] C = [[2, 1], [0]] D = [[0], [2, 1]] the following values for ``ordered`` have the shown meanings:: 00 means A == B == C == D 01 means A == B 10 means A == D 11 means A == A >>> for ordered_flag in [None, 0, 1, 10, 11]: ... print('ordered = %s' % ordered_flag) ... for p in kbins(list(range(3)), 2, ordered=ordered_flag): ... print(' %s' % p) ... ordered = None [[0], [1, 2]] [[0, 1], [2]] ordered = 0 [[0, 1], [2]] [[0, 2], [1]] [[0], [1, 2]] ordered = 1 [[0], [1, 2]] [[0], [2, 1]] [[1], [0, 2]] [[1], [2, 0]] [[2], [0, 1]] [[2], [1, 0]] ordered = 10 [[0, 1], [2]] [[2], [0, 1]] [[0, 2], [1]] [[1], [0, 2]] [[0], [1, 2]] [[1, 2], [0]] ordered = 11 [[0], [1, 2]] [[0, 1], [2]] [[0], [2, 1]] [[0, 2], [1]] [[1], [0, 2]] [[1, 0], [2]] [[1], [2, 0]] [[1, 2], [0]] [[2], [0, 1]] [[2, 0], [1]] [[2], [1, 0]] [[2, 1], [0]] See Also ======== partitions, multiset_partitions N r rTr.z/ordered must be one of 00, 01, 10 or 11, not %s) rr rGr6r r0r%rrtr'r?r;)rhrr plr$permkgotlirTrrr! multiplicityr)s r kbinsr sb&q!,,, B'* 2BbB*2q1 1 1 2 B&q!,,, B$Q* !A$Q !4j  ! ! A!#a&!$7 GD!qy+A.  A"X*0*;&D,"<0H "Q(+    = GI I5 - 2,s4EE2EE E#E $C$E E Ec #Ktdgt||jdz zD]C}t|}t ||Dcgc]}|r||j zn|c}Eycc}ww)aReturn iterator in which the signs of non-zero elements of t are permuted. Examples ======== >>> from sympy.utilities.iterables import permute_signs >>> list(permute_signs((0, 1, 2))) [(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2)] )rrwrN)r r%countrGrMr)rsignsrs r permute_signsrz sm7)SVaggaj%89:>U d1g!>> from sympy.utilities.iterables import signed_permutations >>> list(signed_permutations((0, 1, 2))) [(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2), (0, 2, 1), (0, -2, 1), (0, 2, -1), (0, -2, -1), (1, 0, 2), (-1, 0, 2), (1, 0, -2), (-1, 0, -2), (1, 2, 0), (-1, 2, 0), (1, -2, 0), (-1, -2, 0), (2, 0, 1), (-2, 0, 1), (2, 0, -1), (-2, 0, -1), (2, 1, 0), (-2, 1, 0), (2, -1, 0), (-2, -1, 0)] c3`K|]%}t|D]}t|'ywr/)rrM)rrrrs r r!z&signed_permutations.. s9 #1q! #  DGAJ #J #s+.)r )rs`r signed_permutationsr s  # 5a 8 ##r+c#tKt|}tt|D]}|t||}yw)aReturn a generator giving the items in s as list where each subsequent list has the items rotated to the left (default) or right (``dir=-1``) relative to the previous list. Examples ======== >>> from sympy import rotations >>> list(rotations([1,2,3])) [[1, 2, 3], [2, 3, 1], [3, 1, 2]] >>> list(rotations([1,2,3], -1)) [[1, 2, 3], [3, 1, 2], [2, 3, 1]] N)rGr'r%r)rdirrPrs r rotationsr s9 q'C 3s8_$ #s#$s68c'Ktd|D}t|}|r |D] }|  |ryy#t$r|dz}tt||}Y*wxYww)zroundrobin recipe taken from itertools documentation: https://docs.python.org/3/library/itertools.html#itertools-recipes roundrobin('ABC', 'D', 'EF') --> A D E B F C Recipe credited to George Sakkis c3FK|]}t|jywr/)rE__next__)rr_s r r!zroundrobin.. s8$r(##8s!rN)r r%rr )rmnextspendingnxts r roundrobinr sn 8i8 8E)nG  2 e    2 qLG&01E 2s* A"9A"A"#AA"AA"ceZdZdZy) NotIterablez Use this as mixin when creating a class which is not supposed to return true when iterable() is called on its instances because calling list() on the instance, for example, would result in an infinite loop. N)__name__ __module__ __qualname____doc__rr+r rr s   r+rct|dr |jS t||r t || Sy#t$rYywxYw)aY Return a boolean indicating whether ``i`` is SymPy iterable. True also indicates that the iterator is finite, e.g. you can call list(...) on the instance. When SymPy is working with iterables, it is almost always assuming that the iterable is not a string or a mapping, so those are excluded by default. If you want a pure Python definition, make exclude=None. To exclude multiple items, pass them as a tuple. You can also set the _iterable attribute to True or False on your class, which will override the checks here, including the exclude test. As a rule of thumb, some SymPy functions use this to check if they should recursively map over an object. If an object is technically iterable in the Python sense but does not desire this behavior (e.g., because its iteration is not finite, or because iteration might induce an unwanted computation), it should disable it by setting the _iterable attribute to False. See also: is_sequence Examples ======== >>> from sympy.utilities.iterables import iterable >>> from sympy import Tuple >>> things = [[1], (1,), set([1]), Tuple(1), (j for j in [1, 2]), {1:2}, '1', 1] >>> for i in things: ... print('%s %s' % (iterable(i), type(i))) True <... 'list'> True <... 'tuple'> True <... 'set'> True True <... 'generator'> False <... 'dict'> False <... 'str'> False <... 'int'> >>> iterable({}, exclude=None) True >>> iterable({}, exclude=str) True >>> iterable("no", exclude=str) False _iterableFT)r<rrErr6)rrs r r@r@ sQ^q+{{ Qa)))  s 5 AAcjt|dxr t|xst|xr t||S)a Return a boolean indicating whether ``i`` is a sequence in the SymPy sense. If anything that fails the test below should be included as being a sequence for your application, set 'include' to that object's type; multiple types should be passed as a tuple of types. Note: although generators can generate a sequence, they often need special handling to make sure their elements are captured before the generator is exhausted, so these are not included by default in the definition of a sequence. See also: iterable Examples ======== >>> from sympy.utilities.iterables import is_sequence >>> from types import GeneratorType >>> is_sequence([]) True >>> is_sequence(set()) False >>> is_sequence('abc') False >>> is_sequence('abc', include=str) True >>> generator = (c for c in 'abc') >>> is_sequence(generator) False >>> is_sequence(generator, include=(str, GeneratorType)) True rb)r<r@r8r6)rincludes r r0r0 s;D A} %  QK # M # q' "$r+z Using postorder_traversal from the sympy.utilities.iterables submodule is deprecated. Instead, use postorder_traversal from the top-level sympy namespace, like sympy.postorder_traversal z1.10z$deprecated-traversal-functions-moved)deprecated_since_versionactive_deprecations_targetc"ddlm}|||S)Nr)postorder_traversal)r<)sympy.core.traversalr)rr<_postorder_traversals r rr3 sQ 4 00r+z Using interactive_traversal from the sympy.utilities.iterables submodule is deprecated. Instead, use interactive_traversal from the top-level sympy namespace, like sympy.interactive_traversal cddlm}||S)Nr)interactive_traversal)sympy.interactive.traversalr)expr_interactive_traversals r rrC s\ !$ ''r+z Importing default_sort_key from sympy.utilities.iterables is deprecated. Use from sympy import default_sort_key instead. z#deprecated-sympy-core-compatibilitycddlm}||i|S)Nr)default_sort_key)sympyr)r8kwargs_default_sort_keys r rrT s< d -f --r+cddlm}||i|S)Nrr )rr )r8r_ordereds r r r a s* T $V $$r+r)NN)r)T)NF)F)r3Nrrr/)NNF)NTrV)r)Z collectionsrrr itertoolsrrrr r r r r cartesoperatorrsympy.utilities.enumerativerrrsympy.utilities.miscrsympy.utilities.decoratorrr*r>rIrOr[rjrlrurrrrrrrrrrrrrrrrrrrr rr r(r,r6r0rCrQr\r/r[rjrmrrrrrrrrrrrrrrrrrrrsr@r0rrrr rr+r rsH99 ( II(0";J?D69x866'T&,ECP,*^59p0+\BK<\&&' T=!~1h# LL^[A|AHE)P7t02,3)lhV"Jzz^B&8?D& +\,=^"J:!z<!~mI` > #($(2*  dK07t%$P $E G1 G1  $E G( G(  $@ ..  $@ %%r+