{ "info": { "author": "Braid Generator Team", "author_email": "mmnasrollahi@ucdavis.edu", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Intended Audience :: Education", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# Braid Generator\n\nBraid Generator is a project from the Department of Mathematics in the University of California, Davis. Braid Generator implements a Markov chain algorithm to generate an ensemble of braid representatives (``braidreps\") from a given braid representative of a fixed knot or link type. The project was born when we attempted to use Machine Learning techniques to study braids but found the existing data sets of braid representatives to be too small. The hope is that this program will help others generate data to help better understand braids, knot invariants, and the topology of the space of knots. For more information on\nmathematical braid groups, please refer to this [resource](https://en.wikipedia.org/wiki/Braid_group).\n\n## Getting Started\n\nThese instructions will get you a copy of the project up and running on your local machine for development and testing purposes.\n\n### Prerequisites\n\nDue to the formatting styles used in this package, `braidgenerator` is compatible with Python 3.6 or 3.7.\n\nThe only required dependency for this package is _pandas_. If installing with a local clone, make sure to have _pandas_ installed in the desired environment.\n\n```\n.\n\u251c\u2500\u2500 CONTRIBUTING.md\n\u251c\u2500\u2500 LICENSE.md\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 ThirdPartyLicenses\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 Pandas\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 LICENSE.md\n\u251c\u2500\u2500 braidgenerator\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 __init__.py\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 braidword.py\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 decorators\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 __init__.py\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 braidword.py\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 markovchain.py\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 markovchain.py\n\u251c\u2500\u2500 docs\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 braidword.html\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 contact.html\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 index.html\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 markovchain.html\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 style.css\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 van.js\n\u251c\u2500\u2500 setup.py\n\u2514\u2500\u2500 tests\n \u251c\u2500\u2500 test_braidword.py\n \u2514\u2500\u2500 test_markovchain.py\n```\n\n> The tree represents the hierarchy of the github repository.\n\n### Installation\n\n#### Install BraidGenerator from PyPI\n\nTo install via pip, use the following\n\n```\n$ python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps moore_braidgenerator\n```\n\n> Please note the actual project has not been put up on PyPi yet. Please\n> follow installation by repository. Package will be uploaded to PyPi in the\n> coming few days.\n\n#### Install BraidGenerator from the GitHub source\n\nFirst, clone the Knots repository onto your local machine using `git`. For more information on `git` cloning, visit this [resource](https://www.git-tower.com/learn/git/commands/git-clone).\n\n```\ngit clone https://github.com/Algebra8/Knots\n```\n\nThen, `cd` to the Knots folder and run the install command:\n\n```\ncd Knots\npython setup.py install\n```\n\n### Setup and Examples\n\n#### A quick example for the impatient user\n\nWithin Python try the following example snippet, which takes as its input a braid representative for the trefoil knot (`[1, 1, 1]`), and returns three randomized braid representatives.\n\n```\nfrom braidgenerator import MarkovChain\nimport pandas as pd\n\n# Create markov chain\nmc = MarkovChain(braidword=[1, 1, 1], maxgen=9, maxlen=10)\n\n# Model markov chain\nmc.model(num_braidreps=3, msteps=500)\n\n# Get braid representatives as words (i.e. as lists)\nbraidreps = mc.braidreps(as_word = True)\n\n```\n\nExplanations and definitions are given in detail in the sections below.\n\n#### Setting up the Braid Generator\n\nTo create a Markov Chain, simply call `MarkovChain` with at least the `braidword` argument given. The `MarkovChain` initializor has default values of\nnine and ten for the `maxgen` and `maxlen` parameters, respectively. The speficied argument of `braidword` is the initial state of the Markov process; the state space consists of other braid words representating the same knot as the (closed) initial braid.\n\n```\nfrom braidgenerator import MarkovChain\nimport pandas as pd\n\nmc = MarkovChain(braidword=[1, 2, 3], maxgen=9, maxlen=10)\n\n```\n\nAlternatively, the Markov Chain can be initialized with a `BraidWord` instead of a list. The BraidWord is wrapped around a list (the _word_).\n\n```\nfrom braidgenerator import MarkovChain\nfrom braidgenerator import BraidWord\nimport pandas as pd\n\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n```\n\n> Note that if the Markov Chain is initialized with a list instead of a BraidWord, it will be processed into a BraidWord behind the scenes.\n\nTo create new braidreps it suffices to call the `model` method. The method `model` takes two parameters, `num_braidreps` and `msteps`, where `num_braidreps` is the number of braidreps that are to be generated and `msteps` is the number of Markov steps taken in each random walk that produces such a braidrep. Default values are one and 100, respectively. Markov chain steps are comprised of braid relations and ``Markov moves\" (in the sense of moves on closed braids).\n\n```\nmc.model(num_braidreps=10, msteps=50)\n```\n\nOnce the modelling is complete, the braidreps and/or logs can be accessed via the following getter methods:\n\n- `MarkovChain.aggregate`\n- `MarkovChain.logs`\n- `MarkovChain.braidreps`\n- `MarkovChain.topandas`\n- `MarkovChain.tocsv`\n- `MarkovChain.totxt`\n\n#### `MarkovChain.aggregate`\n\nThe `aggregate` method will return a dictionary with two keys: _braidreps_ and _logs_, whereby _braidreps_ is a list that contains the generated braidreps and _logs_ is a list that contains the relevant Markov steps per iteration and if they were successful or not.\n\n> This aggregate dictionary is mainly a container for the relevant data and while this getter method is available, it is not recommended for retrieving the data. Better alternative methods exist for this.\n\n```\nagg = mc.aggregate()\n\nagg\n\n> {'braidreps': [], 'logs': []}\n```\n\n#### `MarkovChain.logs`\n\nThe `logs` method returns only the logs in the list format. Each element of the log is itself a dictionary that represents all the Markov steps for each braidrep created. Thus, the size of _braidreps_ and _logs_ will be the same, but each entry will contain a larger set of logs. The example below shows a MarkovChain's logs with `num_braidreps=1` and `msteps=5`\n\n```\nlogs = mc.logs()\n\nlogs[0]\n\n> {0: 'MoveType: 5, Attempted stabilize: stabilize Succeeded.',\n1: 'MoveType: 0, Attempted conjugate: conjugate Succeeded.',\n2: 'MoveType: 6, Attempted destabilize: destabilize Failed.',\n3: 'MoveType: 3, Attempted transpose: transpose Failed.',\n4: 'MoveType: 4, Attempted flip: flip Failed.'}\n```\n\n#### `MarkovChain.braidreps`\n\nThe `braidreps` method will return the list with the generated braidreps. This method takes an optional parameter `as_word` which is set to `False` by default. If left as `False` then it will return a list of BraidWords, otherwise it will return a list of words (i.e. of type list).\n\n```\n# As BraidWords with as_word set to False (default)\n\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\nbraidreps_asBraidWord = mc.braidreps()\n\nbraidreps_asBraidWord\n\n> [,\n ,\n ]\n```\n\n```\n# As words with as_word set to True\n\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\nbraidreps_asword = mc.braidreps(as_word=True)\n\nbraidreps_asword\n\n> [[1, 2, 3], [2, 3, 1], [1, 2]]\n```\n\n> Note that the braid that was fed into the model is not included. The first word of the second example above is a coincidence resulting from one successful destabilize and one successful stabilize.\n\n#### `MarkovChain.topandas`\n\nThe logs and braidreps can be most easily accessed via the `topandas` method. To use it, simply import _pandas_ into the script and call the `topandas` method. The method takes one optional argument, `only_braidreps`, which is set to `False` by defualt. If set to `True` then the resulting dataframe will only include the braidreps in word form. Otherwise, each entry will comprise of both the braidrep and the logs associated with it.\n\n```\n# only_braidreps set to False (default)\nimport pandas as pd\n\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\ndf = mc.topandas()\ndf.columns\n\n> Index(['braidreps', 'Logs'], dtype='object')\n```\n\n```\n# only_braidreps set to True\nimport pandas as pd\n\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\ndf = mc.topandas(only_braidreps=True)\ndf.columns\n\n> Index(['braidreps'], dtype='object')\n```\n\n#### `MarkovChain.tocsv`\n\nThe `tocsv` method exports the dataframe to a .csv file. The parameters include `path_or_filename` and `only_braidreps`, respectively. Similar to the `topandas` method, `only_braidreps` is set to `False` by default. The `path_or_filename` parameter is more interesting. If a path is not specified, the method will export the requested information to the current directory with either the name _braidreps.csv_\nor _braidreps_and_Logs.csv_, which it will implicitly interpret from the argument passed to `only_braidreps`.\n\n```\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\npath = 'some/path/onyourpc.csv'\nmc.tocsv(path_or_filename=path, only_braidreps=False)\n```\n\n#### `MarkovChain.totxt`\n\nThe `totxt` method is similar to the `topandas` and `tocsv` difference being that it exports the data to a _.txt_ file in the following format:\n\n```\nbraidrep[1]\n.\n.\n.\nbraidrep[n]\n\nlog[1]\n.\n.\n.\nlog[n]\n```\n\nAs is with to `tocsv`, the `totxt` has the two parameters\n`path_or_filename` and `only_braidreps`, respectively.\n\n### Clearing the model and setting a new BraidWord\n\nIf it is desired to use the same model to create a new set of isomoprhs, the `clear_model` method is required. This method clears the _braidagg_ container.\n\n```\nmc = MarkovChain(braidword=BraidWord([1, 2, 3]), maxgen=9, maxlen=10)\n\nmc.model(num_braidreps=3, msteps=5)\n\nmc.clear_model()\n\nmc.aggregate()\n\n> {'braidreps': [], 'logs': []}\n```\n\n> Note that if not changed, the subsequent BraidWord will have been mutated. This functionality is left in as it may seem desirable for some situations and is simple enough to undo (i.e. replace the BraidWord with the `new_braidword` method).\n\nIn the event that it is desirable to set a new _BraidWord_ into an already existing method, the `new_braidword` method can be used. A list or `BraidWord` object can be passed as an argument.\n\n```\nmc.new_braidword([1, 1, 2])\n```\n\n```\nmc.new_braidword(BraidWord([1, 2, 3]))\n```\n\n> As is the case with the initializor, if a list is passed in as an argument it will be converted to a BraidWord behind the scenes.\n\n### Bonus BraidWord functionality\n\n#### `crossing_change`\n\nThe `crossing_change` method performs a crossing change on a BraidWord. That is, it returns a new BraidWord whereby\nthe generator at a specified index is inverted.\n\nThe resulting index can be set randomly with `random_index` set to `True`, or it can be set manually by setting `random_index=False` and assigning `index` with an integer value between zero and the length of the word of the BraidWord.\n\n```\nfrom braidgenerator import BraidWord\n\nbraidword = BraidWord([1, 2, 3])\n\n# Randomly set generator to be inverted\nrandom_newbraidword = braidword.crossing_change(random_index=True)\n\n# Manually set generator to be inverted\nmanual_newbraidword = braidword.crossing_change(random_index=False, index=1)\n\nrandom_newbraidword.word\n>>> [1, 2, -3]\n\nmanual_newbraidword.word\n>>> [1, -2, 3]\n```\n\n#### `resolution`\n\nThe `resolution` method performs a resolution on a BraidWord. That is, it returns a new BraidWord whereby\nthe generator at a specified index is removed and the new BraidWord's length is decreased by one.\n\nThe resulting index can be set randomly with `random_index` set to `True`, or it can be set manually by setting `random_index=False` and assigning `index` with an integer value between zero and the length of the word of the BraidWord.\n\n```\nfrom braidgenerator import BraidWord\n\nbraidword = BraidWord([1, 2, 3])\n\n# Randomly set generator to be removed\nrandom_newbraidword = braidword.resolution(random_index=True)\n\n# Manually set generator to be removed\nmanual_newbraidword = braidword.resolution(random_index=False, index=1)\n\nrandom_newbraidword.word\n>>> [2, 3]\n\nmanual_newbraidword.word\n>>> [1, 3]\n```\n\n## Running the tests\n\nTests for these scripts are included in the github repository under the paths shown below.\n\n```\n.\n|\n\u2514\u2500\u2500\u2500tests\n test_braidword.py\n test_markovchain.py\n```\n\n### Breakdown of tests\n\nThe given tests use Pythons UnitTest package for testing.\n**test_braidword.py** contains over 350 lines of tests with 30+ test cases (at the time of writting this readme). The test cases contain suites that test for initialization, boolean helper functions (such as `canDestabilize`, `canFlip`, etc...), and the **BraidWord** methods (such as `Destabilize`, `Flip`, etc...). Examples of **test_braidword.py** include:\n\n```\ndef test_init_pathfail_0(self):\n '''\n Should raise TypeError if initword\n is not a list (args)\n '''\n with self.assertRaises(TypeError) as te:\n bw = BraidWord(1)\n```\n\n```\ndef test_canCancel_pathfail(self):\n \"\"\"Should return False when adjacent\n generators are not inverses of one other\"\"\"\n bw = BraidWord([1, 2, 3, -3])\n # Execution path False\n self.assertFalse(bw.canCancel(0))\n```\n\n```\ndef test_cancel_pathsuccess(self):\n \"\"\"Should successfully cancel gen @idx 3\n and should modify word\"\"\"\n bw = BraidWord([-1, 2, 3, 1])\n # Execution path True\n self.assertTrue(bw.cancel(3))\n # Word modification\n self.assertEqual(bw.word, [2, 3])\n```\n\n**test_markovchain.py** contains roughly 200 lines of tests with 18+ test cases (at the time of writing this readme). The test cases contain suites that test mainly for initialization and that containers, such as _logs_, _braidrepisms_, and _braidagg_, vis-a-vis the `aggregate`, `logs`, and `braidreps` methods, as well as exporting methods, such as `tocsv`, `topandas`, and `totxt`, are valid (i.e. not empty). The lack of automated tests for said script is due to the probabilistic nature of the results of the `model` method. Results for this method may be tested by hand or an auxiliary program, such as ``KnotPlot.\" Examples of **test_markovchain.py** include:\n\n```\ndef test_init_pathfail_0(self):\n \"\"\"Should throw error if BraidWord not given\"\"\"\n with self.assertRaises(Exception) as te:\n MarkovChain()\n```\n\n```\ndef test_aggregate(self):\n '''\n Should return non-empty self.braidagg\n '''\n mc = MarkovChain(BraidWord([1, 2, 3]))\n mc.model(num_braidreps=1, msteps=10)\n # Check if non-empty\n self.assertTrue(mc.aggregate())\n```\n\n```\ndef test_logs(self):\n '''\n Should return non-empty self.braidagg.logs\n '''\n mc = MarkovChain(BraidWord([1, 2, 3]))\n mc.model(num_braidreps=1, msteps=10)\n # Check if non-empty\n self.assertTrue(mc.logs())\n```\n\n> BraidWord's `crossing_change` and `resolution` methods follow similar formats and can be viewed in the `tests\\test_braidword` module in the repository.\n\n## Documentation\n\nFor more information about methods and code fragments, please refer to the [documentation](https://algebra8.github.io/braidgenerator_doc.github.io/).\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us.\n\n## Versioning\n\nWe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/your/project/tags).\n\n## Authors\n\n- **Allison Moore** - _Initial work_ - [allisonhmoore](https://github.com/allisonhmoore)\n- **Milad Michael Nasrollahi** - _Initial work_ - [Algebra8](https://github.com/Algebra8)\n- **Shawn Witte** - _Initial work_ - [Minirogue](https://github.com/Minirogue)\n\n\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.\n\n## Acknowledgements\n\nThis package makes use of _pandas_ as a requirement. Please refer to the [_pandas_ license](https://github.com/pandas-dev/pandas/blob/master/LICENSE) for more information on their license.\n\nThe CONTRIBUTING.md content was adapted from PurpleBooth's [Good-CONTRIBUTING.md-template.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426).\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Algebra8/Knots", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "braidgenerator", "package_url": "https://pypi.org/project/braidgenerator/", "platform": "", "project_url": "https://pypi.org/project/braidgenerator/", "project_urls": { "Homepage": "https://github.com/Algebra8/Knots" }, "release_url": "https://pypi.org/project/braidgenerator/1.0.0/", "requires_dist": [ "pandas", "unittest ; extra == 'tests'" ], "requires_python": "", "summary": "Braid Generator", "version": "1.0.0" }, "last_serial": 5502624, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "c90c76cbcdebe910c8d18b59c779fdb6", "sha256": "ed78cc3e4d4b9d00ca07f4e17e1d7de90ef614bfcb80c778af6239fd32f1ec9c" }, "downloads": -1, "filename": "braidgenerator-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c90c76cbcdebe910c8d18b59c779fdb6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15933, "upload_time": "2019-07-08T18:55:52", "url": "https://files.pythonhosted.org/packages/fa/09/ed72f331abb8e2ea1fff19c45461aad995f25184c8969c47a72eb4c9001e/braidgenerator-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ba138f4e27a75a1b9c5073c14f0ae636", "sha256": "5926ee0e17d403f11789edb91fe234432800aa0c6a68838d38120b763174574c" }, "downloads": -1, "filename": "braidgenerator-1.0.0.tar.gz", "has_sig": false, "md5_digest": "ba138f4e27a75a1b9c5073c14f0ae636", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14235, "upload_time": "2019-07-08T18:55:55", "url": "https://files.pythonhosted.org/packages/8a/16/517617856c1cb7ae6e28a9350d4f5829b338522196c6f03632eb516a763f/braidgenerator-1.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c90c76cbcdebe910c8d18b59c779fdb6", "sha256": "ed78cc3e4d4b9d00ca07f4e17e1d7de90ef614bfcb80c778af6239fd32f1ec9c" }, "downloads": -1, "filename": "braidgenerator-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c90c76cbcdebe910c8d18b59c779fdb6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 15933, "upload_time": "2019-07-08T18:55:52", "url": "https://files.pythonhosted.org/packages/fa/09/ed72f331abb8e2ea1fff19c45461aad995f25184c8969c47a72eb4c9001e/braidgenerator-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ba138f4e27a75a1b9c5073c14f0ae636", "sha256": "5926ee0e17d403f11789edb91fe234432800aa0c6a68838d38120b763174574c" }, "downloads": -1, "filename": "braidgenerator-1.0.0.tar.gz", "has_sig": false, "md5_digest": "ba138f4e27a75a1b9c5073c14f0ae636", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14235, "upload_time": "2019-07-08T18:55:55", "url": "https://files.pythonhosted.org/packages/8a/16/517617856c1cb7ae6e28a9350d4f5829b338522196c6f03632eb516a763f/braidgenerator-1.0.0.tar.gz" } ] }