{"id":19268395,"url":"https://github.com/permutatriangle/motzkin","last_synced_at":"2025-02-23T19:46:07.038Z","repository":{"id":145994468,"uuid":"345663814","full_name":"PermutaTriangle/motzkin","owner":"PermutaTriangle","description":"A library for counting and sampling sets of Motzkin paths avoiding patterns.","archived":false,"fork":false,"pushed_at":"2022-04-15T16:57:52.000Z","size":40,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-05T12:30:44.588Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PermutaTriangle.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-08T13:22:59.000Z","updated_at":"2022-12-31T14:06:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"409c399d-3fdc-4ae2-8730-5671f6842e26","html_url":"https://github.com/PermutaTriangle/motzkin","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PermutaTriangle%2Fmotzkin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PermutaTriangle%2Fmotzkin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PermutaTriangle%2Fmotzkin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PermutaTriangle%2Fmotzkin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PermutaTriangle","download_url":"https://codeload.github.com/PermutaTriangle/motzkin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240371742,"owners_count":19790888,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T20:16:08.958Z","updated_at":"2025-02-23T19:46:06.980Z","avatar_url":"https://github.com/PermutaTriangle.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"#######\nmotzkin\n#######\n\nMotzkin is a Python library for counting and sampling sets of Motzkin paths defined by pattern avoidance.\n\nIf you need support, you can join us in our `Discord support server`_.\n\n.. _Discord support server: https://discord.gg/ngPZVT5\n\nInstalling\n==========\n\nTo install Motzkin on your system, run the following after cloning the repository:\n\n.. code-block:: bash\n\n    ./setup.py\n\nIt is also possible to install Motzkin in development mode to work on the\nsource code, in which case you run the following after cloning the repository:\n\n.. code-block:: bash\n\n    ./setup.py develop\n    \n\nUsing Motzkin\n#############\n\nThe motzkin library is built on top of the comb_spec_searcher module. To find a specification for a set of pattern avoiding Motzkin paths we first create a MotzkinSpecificationFinder.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from motzkin import MotzkinSpecificationFinder\n\nWe initialise the MotzkinSpecificationFinder with the patterns.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e patterns = [\"UUHD\", \"DDHU\"]\n    \u003e\u003e\u003e msf = MotzkinSpecificationFinder(patterns)\n\nThe MotzkinSpecificationFinder is a CombinatorialSpecificationFinder from the comb_spec_searcher module and as such we can use those underlying methods. To find the specification call the auto_search method.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e specification = msf.auto_search()\n    [I 210316 10:15:17 comb_spec_searcher:585] Auto search started Tue, 16 Mar 2021 10:15:17\n        Initialising CombSpecSearcher for the combinatorial class:\n        Av(UDUHD, UUDHD, UUHDD)\n        Looking for recursive combinatorial specification with the strategies:\n        Inferral: \n        Initial: Remove known letters.\n        Verification: verify atoms\n        Set 1: A path is empty, starts with H, or starts with U, pattern insertions\n        \n    [I 210316 10:15:19 base:235] Specification detected.\n    [I 210316 10:15:19 base:241] Minimizing for 0 seconds.\n    [I 210316 10:15:19 base:247] Found specification with 22 rules.\n    [I 210316 10:15:19 comb_spec_searcher:698] Creating a specification.\n    [I 210316 10:15:19 comb_spec_searcher:524] Specification built Tue, 16 Mar 2021 10:15:19\n        Time taken: 0:00:01\n        CSS status:\n            Total time accounted for: 0:00:01\n                                                                Number of\n                                                                applications    Time spent    Percentage\n            ------------------------------------------------  --------------  ------------  ------------\n            is empty                                                     205       0:00:01           90%\n            verify atoms                                                  96       0:00:00            0%\n            Remove known letters.                                         87       0:00:00            0%\n            get specification                                             16       0:00:00            4%\n            A path is empty, starts with H, or starts with U              39       0:00:00            0%\n            pattern insertions                                            39       0:00:00            3%\n        ClassDB status:\n            Total number of combinatorial classes found is 116\n        Queue status (currently on level 5):\n            Queue              Size\n            ---------------  ------\n            working               8\n            current (set 1)      10\n            next                 11\n            The size of the current queues at each level: 1, 3, 14, 29, 25\n        RuleDB status:\n                                                    Total number\n            ---------------------------------------  --------------\n            Combinatorial rules                                 107\n            Equivalence rules                                    28\n            Combintorial rules up to equivalence                 95\n            Strategy verified combinatorial classes               3\n            Verified combinatorial classes                       60\n            combinatorial classes up to equivalence              73\n            Called find equiv path 16 times, for total time of 0.0 seconds.\n        \n        Memory Status:\n            ------------  --------\n            OS Allocated  55.9 MiB\n            CSS            442 KiB\n            ClassDB        327 KiB\n            ClassQueue      20 KiB\n            RuleDB          91 KiB\n            ------------  --------\n        Specification found has 29 rules\n\nThe specification returned is a CombinatorialSpecification from the comb_spec_searcher module. To view these you can either print specification for a string representation or use the show method to visualise the specification in a proof tree format. \n\n.. code-block:: python\n\n    \u003e\u003e\u003e print(specification)\n    A combinatorial specification with 29 rules.\n    --------------\n    0 -\u003e (1, 2, 3)\n    A path is empty, starts with H, or starts with U\n    Av(UDUHD, UUDHD, UUHDD)  =  {λ}  +  AvH(UDUHD, UUDHD, UUHDD)∩Co(H)  +  AvU(λ-UHD, UDUD-HUD, UUDD-HUD, UDUDH-UD, UDUHD-λ, UUDDH-UD, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)\n    -------\n    1 -\u003e ()\n    is atom\n    {λ}\n    -----------\n    2 -\u003e (4, 0)\n    Remove known letters.\n    AvH(UDUHD, UUDHD, UUHDD)∩Co(H)  =  {H}  x  Av(UDUHD, UUDHD, UUHDD)\n    -------\n    4 -\u003e ()\n    is atom\n    {H}\n    -----\n    3 = 5\n    The paths avoid or contain UDUDH-λ but only the child at index 0 is non-empty, then The paths avoid or contain UUDDH-λ but only the child at index 0 is non-empty\n    AvU(λ-UHD, UDUD-HUD, UUDD-HUD, UDUDH-UD, UDUHD-λ, UUDDH-UD, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)  =  AvU(λ-UHD, UDUD-HUD, UUDD-HUD, UDUDH-λ, UDUHD-λ, UUDDH-UD, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)  =  AvU(λ-UHD, UDUD-HUD, UUDD-HUD, UDUDH-λ, UDUHD-λ, UUDDH-λ, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)\n    -----------\n    5 -\u003e (6, 7)\n    The paths avoid or contain λ-HUD\n    AvU(λ-UHD, UDUD-HUD, UUDD-HUD, UDUDH-λ, UDUHD-λ, UUDDH-λ, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)  =  AvU(λ-HUD, λ-UHD, UDUDH-λ, UDUHD-λ, UUDDH-λ, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)  +  AvU(λ-UHD, UDUD-λ, UUDD-λ)∩Co(λ-HUD)∩Co(UD-λ)\n    ---------------\n    6 -\u003e (8, 9, 10)\n    Remove known letters.\n    AvU(λ-HUD, λ-UHD, UDUDH-λ, UDUHD-λ, UUDDH-λ, UUDHD-λ, UUHDD-λ)∩Co(UD-λ)  =  {UD}  x  Av(UDH, UHD)  x  Av(HUD, UHD)\n    -------\n    8 -\u003e ()\n    is atom\n    {UD}\n    ----------------\n    9 -\u003e (1, 11, 12)\n    A path is empty, starts with H, or starts with U\n    Av(UDH, UHD)  =  {λ}  +  AvH(UDH, UHD)∩Co(H)  +  AvU(λ-H, UDH-λ, UHD-λ)∩Co(UD-λ)\n    ------------\n    11 -\u003e (4, 9)\n    Remove known letters.\n    AvH(UDH, UHD)∩Co(H)  =  {H}  x  Av(UDH, UHD)\n    -----------------\n    12 -\u003e (8, 13, 13)\n    Remove known letters.\n    AvU(λ-H, UDH-λ, UHD-λ)∩Co(UD-λ)  =  {UD}  x  Av(H)  x  Av(H)\n    -----------------\n    13 -\u003e (1, 14, 15)\n    A path is empty, starts with H, or starts with U\n    Av(H)  =  {λ}  +  ∅  +  AvU(λ-H, H-λ)∩Co(UD-λ)\n    --------\n    14 -\u003e ()\n    is empty\n    ∅\n    -----------------\n    15 -\u003e (8, 13, 13)\n    Remove known letters.\n    AvU(λ-H, H-λ)∩Co(UD-λ)  =  {UD}  x  Av(H)  x  Av(H)\n    -----------------\n    10 -\u003e (1, 16, 17)\n    A path is empty, starts with H, or starts with U\n    Av(HUD, UHD)  =  {λ}  +  AvH(HUD, UHD)∩Co(H)  +  AvU(λ-HUD, λ-UHD, H-UD, HUD-λ, UHD-λ)∩Co(UD-λ)\n    -------------\n    16 -\u003e (4, 18)\n    Remove known letters.\n    AvH(HUD, UHD)∩Co(H)  =  {H}  x  Av(UD)\n    -----------------\n    18 -\u003e (1, 19, 20)\n    A path is empty, starts with H, or starts with U\n    Av(UD)  =  {λ}  +  AvH(UD)∩Co(H)  +  ∅\n    -------------\n    19 -\u003e (4, 18)\n    Remove known letters.\n    AvH(UD)∩Co(H)  =  {H}  x  Av(UD)\n    --------\n    20 -\u003e ()\n    is empty\n    ∅\n    -------\n    17 = 21\n    The paths avoid or contain H-λ but only the child at index 0 is non-empty\n    AvU(λ-HUD, λ-UHD, H-UD, HUD-λ, UHD-λ)∩Co(UD-λ)  =  AvU(λ-HUD, λ-UHD, H-λ)∩Co(UD-λ)\n    -----------------\n    21 -\u003e (8, 13, 10)\n    Remove known letters.\n    AvU(λ-HUD, λ-UHD, H-λ)∩Co(UD-λ)  =  {UD}  x  Av(H)  x  Av(HUD, UHD)\n    ----------------\n    7 -\u003e (8, 18, 22)\n    Remove known letters.\n    AvU(λ-UHD, UDUD-λ, UUDD-λ)∩Co(λ-HUD)∩Co(UD-λ)  =  {UD}  x  Av(UD)  x  Av(UHD)∩Co(HUD)\n    -------\n    22 = 23\n    A path is empty, starts with H, or starts with U but only the child at index 1 is non-empty\n    Av(UHD)∩Co(HUD)  =  AvH(UHD)∩Co(HUD)\n    -------------\n    23 -\u003e (4, 24)\n    Remove known letters.\n    AvH(UHD)∩Co(HUD)  =  {H}  x  Av(UHD)∩Co(UD)\n    ------------------\n    24 -\u003e (25, 26, 27)\n    A path is empty, starts with H, or starts with U\n    Av(UHD)∩Co(UD)  =  ∅  +  AvH(UHD)∩Co(H)∩Co(UD)  +  AvU(λ-HUD, λ-UHD, UDH-UD, UHD-λ)∩Co(UD-λ)\n    --------\n    25 -\u003e ()\n    is empty\n    ∅\n    -------------\n    26 -\u003e (4, 24)\n    Remove known letters.\n    AvH(UHD)∩Co(H)∩Co(UD)  =  {H}  x  Av(UHD)∩Co(UD)\n    -------\n    27 = 28\n    The paths avoid or contain UDH-λ but only the child at index 0 is non-empty\n    AvU(λ-HUD, λ-UHD, UDH-UD, UHD-λ)∩Co(UD-λ)  =  AvU(λ-HUD, λ-UHD, UDH-λ, UHD-λ)∩Co(UD-λ)\n    -----------------\n    28 -\u003e (8, 13, 10)\n    Remove known letters.\n    AvU(λ-HUD, λ-UHD, UDH-λ, UHD-λ)∩Co(UD-λ)  =  {UD}  x  Av(H)  x  Av(HUD, UHD)\n\n    \u003e\u003e\u003e specification.show()\n    [I 210316 10:15:19 specification_drawer:520] Opening specification in browser\n    [I 210316 10:15:23 specification_drawer:506] specification html file removed\n\nAs we now have a CombinatorialSpecification we can utilise the underlying methods for counting and randomly sampling this set of Motzkin paths. \n\nTo count we could either find the generating function or use the specification as a recurrence.\n\n.. code-block:: python\n\n    \u003e\u003e\u003e specification.get_genf()\n    [I 210316 10:15:19 specification:351] Computing initial conditions\n    [I 210316 10:15:19 specification:325] Computing initial conditions\n    [I 210316 10:15:19 specification:353] The system of 29 equations\n        root_func := F_0:\n        eqs := [\n        F_0 = F_1 + F_2 + F_3,\n        F_1 = 1,\n        F_2 = F_0*F_4,\n        F_3 = F_5,\n        F_4 = x,\n        F_5 = F_6 + F_7,\n        F_6 = F_10*F_8*F_9,\n        F_7 = F_18*F_22*F_8,\n        F_8 = x**2,\n        F_9 = F_1 + F_11 + F_12,\n        F_10 = F_1 + F_16 + F_17,\n        F_11 = F_4*F_9,\n        F_12 = F_13**2*F_8,\n        F_13 = F_1 + F_14 + F_15,\n        F_14 = 0,\n        F_15 = F_13**2*F_8,\n        F_16 = F_18*F_4,\n        F_17 = F_21,\n        F_18 = F_1 + F_19 + F_20,\n        F_19 = F_18*F_4,\n        F_20 = 0,\n        F_21 = F_10*F_13*F_8,\n        F_22 = F_23,\n        F_23 = F_24*F_4,\n        F_24 = F_25 + F_26 + F_27,\n        F_25 = 0,\n        F_26 = F_24*F_4,\n        F_27 = F_28,\n        F_28 = F_10*F_13*F_8\n        ]:\n        count := [1, 1, 2, 4, 9, 18, 37]:\n    [I 210316 10:15:19 specification:354] Solving...\n    [I 210316 10:15:27 specification:365] Checking initial conditions for: (-4*x**5 + 6*x**4 - x**3*sqrt(1 - 4*x**2) - 3*x**3 + x*sqrt(1 - 4*x**2) - x - sqrt(1 - 4*x**2) + 1)/(2*x**2*(x**4 - 4*x**3 + 6*x**2 - 4*x + 1))\n    (-4*x**5 + 6*x**4 - x**3*sqrt(1 - 4*x**2) - 3*x**3 + x*sqrt(1 - 4*x**2) - x - sqrt(1 - 4*x**2) + 1)/(2*x**2*(x**4 - 4*x**3 + 6*x**2 - 4*x + 1))\n\n    \u003e\u003e\u003e print([specification.count_objects_of_size(i) for i in range(10)])\n    [1, 1, 2, 4, 9, 18, 37, 69, 131, 231]\n\nWe can also generate the paths in the set. These can be visualised using the ascii_plot method.\n\n.. code-block:: python \n\n    \u003e\u003e\u003e for path in specification.generate_objects_of_size(5):\n            print(path.ascii_plot())\n            print(path)\n    _____\n    HHHHH\n    ___/\\\n    HHHUD\n    __/\\_\n    HHUDH\n       _ \n    __/ \\\n    HHUHD\n    _/\\__\n    HUDHH\n    _/\\/\\\n    HUDUD\n      _  \n    _/ \\_\n    HUHDH\n      __ \n    _/  \\\n    HUHHD\n      /\\ \n    _/  \\\n    HUUDD\n    /\\___\n    UDHHH\n    /\\/\\_\n    UDUDH\n     _   \n    / \\__\n    UHDHH\n     _   \n    / \\/\\\n    UHDUD\n     __  \n    /  \\_\n    UHHDH\n     /\\  \n    /  \\_\n    UUDDH\n     ___ \n    /   \\\n    UHHHD\n     _/\\ \n    /   \\\n    UHUDD\n    /\\_/\\\n    UDHUD\n\nTo randomly sample we simply use the random_sample_object_of_size method.\n\n.. code-block:: python \n\n    \u003e\u003e\u003e path = specification.random_sample_object_of_size(10)\n    \u003e\u003e\u003e print(path.ascii_plot())\n       /\\     \n     _/  \\/\\  \n    /       \\_\n    \u003e\u003e\u003e print(path)\n    UHUUDDUDDH\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermutatriangle%2Fmotzkin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpermutatriangle%2Fmotzkin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpermutatriangle%2Fmotzkin/lists"}