{"id":20932829,"url":"https://github.com/piotr-yuxuan/polygam","last_synced_at":"2025-06-27T10:34:29.850Z","repository":{"id":147669771,"uuid":"67296911","full_name":"piotr-yuxuan/polygam","owner":"piotr-yuxuan","description":"Experiment with core.logic","archived":false,"fork":false,"pushed_at":"2025-05-29T07:45:41.000Z","size":848,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-30T09:57:57.164Z","etag":null,"topics":["clojure","core-logic","logic-programming"],"latest_commit_sha":null,"homepage":"https://github.com/piotr-yuxuan/slava","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piotr-yuxuan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.org","contributing":null,"funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS.yml","security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["piotr-yuxuan"]}},"created_at":"2016-09-03T15:21:34.000Z","updated_at":"2025-05-30T07:22:26.000Z","dependencies_parsed_at":"2024-08-03T19:44:46.787Z","dependency_job_id":"092e4127-0f3a-446b-979d-b80998582f16","html_url":"https://github.com/piotr-yuxuan/polygam","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/piotr-yuxuan/polygam","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-yuxuan%2Fpolygam","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-yuxuan%2Fpolygam/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-yuxuan%2Fpolygam/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-yuxuan%2Fpolygam/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piotr-yuxuan","download_url":"https://codeload.github.com/piotr-yuxuan/polygam/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotr-yuxuan%2Fpolygam/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262239777,"owners_count":23280393,"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":["clojure","core-logic","logic-programming"],"created_at":"2024-11-18T21:53:31.894Z","updated_at":"2025-06-27T10:34:29.826Z","avatar_url":"https://github.com/piotr-yuxuan.png","language":"Clojure","funding_links":["https://github.com/sponsors/piotr-yuxuan"],"categories":[],"sub_categories":[],"readme":"# polygam\n\nTL;DR:\n\n\u003e Choose as many spouses as you want according to your taste.\n\n![polygyny](img/polygyny.jpeg)\n\nThis description above (about spouses) is actually rather accurate but it would\nbe easier to explain it with trees, colours and arrows.\n\nYou are given two trees (aka directed acyclic connected graphs), A and B. Each\nvertex of tree A has veen give some 'gutt', that's to say a set of logical\nrules. The gutt of a node from A defines which vertices of B are available for\nit. In the same way, each vertex of B has some gutt which define which vertices\nof A are available for it.\n\nMy goal in this project is to write such a function `availableo` which takes a\nvertex from a tree and returns all available vertices of the other tree. It's\nreally a perfect playground for logic programming.\n\n\u003e End of TL;DR\n\nLet me say it another way: a vertex from a tree is somehow linked to some set of\nvertices of the other tree. A vertex and its linked set can't be from the same\ntree.\n\nThis project currently barely stands as a draft which I'm working on during my\nspare time. I've found useful to see this problem from different viewpoints,\nhence you can still find vocabulary about genealogy, graph, match-making, logic\nand relational algebra.\n\nI've found both necessary and educational to keep attaching documentation to my\nside projects for it helps to more clearly define your goals and where you are\nin relation to them. The [changelog](CHANGELOG.org) aims at keeping an\nup-to-date history of what has been done and what is left.\n\nOnce redacted, this document will introduce the problem and the tools I've\ndefined through a running example. This kind of literate programming should make\nvery easy to understand the code. However, this is not an introduction from\nscratch. You can look up on the fly for the definition of things you don't know:\n\n* What is [a graph](https://en.wikipedia.org/wiki/Graph_(discrete_mathematics))\n* Learning [logic programming](https://mitpress.mit.edu/books/reasoned-schemer)\n* Getting started with\n  [`core.logic`](https://github.com/swannodette/logic-tutorial)\n  ([code here](https://github.com/clojure/core.logic))\n\n## Tools\n\nIn this section we define the current semantic of goals then we give some\nexamples of expected behaviours.\n\n### Definitions\n\nConsider the following tree, which arrows are from top to bottom.\n\n![graph](./img/graph-sample.png)\n\nEach arrow stands for the parent / child relation. It's defined in the code by\nthe relation `child`. We can extend this relation to ascendant / descandant:\nit's the relational goal `kino`. Logic goal are used to be suffixed with a\nsuperscript `o` (or another vowel), which we render in the code by a standard\nletter `o`. The name `kino` comes from English nouns kin and kinship which\ndenotes such a relationship. Last word about the family, you can access siblings\nof a vertex (other children of the same parents different from the given vertex)\nby goal `siblingso`.\n\nVertices can be elicited or rejected. Two relations embodie this is the code.\nTheir names are pretty straightforward as `yap` convey a positive meaning\n(chosen amongst siblings) whilst `yuk` sounds negatively yucky. Ikks! The goal\n`yap-treeo` accepts any node which is elicited or which descend from an elicited\nnode. `yuk-treeo` is the symetric goal which can accept any rejected (yukked)\nvertex of any children of such a vertex.\n\nSome subtlety appears when intertwin yukked and yapped vertices.\n\n### Simple visual example\n\nConsider the same graph.\n\nVertices `a`, `b`, `c`, `h`, `j`, `k` and `n` have been added some marks. Nodes\n`a`, `c`, `j`, `k` and `n` are marked with blue, meaning they have been elicited\n(yapped). Others are explicitly rejected.\n\nLet's describe the expected behaviour of the code: what will it reply to the\nquestion \"Which nodes are available\"?\n\n* Node `a` is in blue then it's available\n* `a` has three children: `b`, `m` and `c`. Node `b`is explicitly rejected then\n  is coloured in red. Node `m` should be available but node `c` has been\n  explicitly chosen so it has precedence: node `m` is not available and node `c`\n  is available.\n* =\u003e so far, available nodes are `a` and `c`\n* Node `b` is explicitly rejected so are its children. Neither `d`, `e`, `f` or\n  `r` will be available.\n* =\u003e so far, available nodes are still `a` and `c`\n* Node `m` is not available and node `o` is a regular node so is not available\n  either. However, node `n` has been explicitly chosen so is available. The\n  descandants of node `n` are also available because none of them has been\n  rejected or elicited against another one.\n* =\u003e so far, available vertices are now `a`, `c`, `n`, `q`, `g` and `p`\n* Node `c` is available so it child `h` should also be, however the latter node\n  has been explicitly rejected. No vertex is added.\n* Children of an explicitly rejected node should not be available, however `j`\n  and `k` have been explicitly chosen so they are available.\n* =\u003e finally available vertices are `a`, `c`, `n`, `q`, `g` and `p`\n\nWhen looking for general answer, which are available nodes to be chosen? This is\nleft as exercise for the reader.\n\n\n### Step-by-step examples\n\nThe two strategies presented here are explained with the help of the following graph.\n\n* The [substraction](./docs/substraction.md) algorithm uses soft-cut strategy to\n  remove values from the initial set untill it matches the answer.\n* The [accumulation](./docs/accumulation.md) algorithm uses logical disjunction\n  to unfold possible case and accept or reject values.\n\n![big-graph](./img/graph-sample-extended.png)\n\n## Performance\n\nLast but not least word about performance: the two strageties implemented here give:\n\n``` Clojure\n\"Elapsed time: 949.399797 msecs\" ;; accumulation\n\"Elapsed time: 979.701262 msecs\" ;; substraction\n```\n\nMethinks it's important to keep in mind computation time is rather sensitive to\nthe complexity of the problem you want to solve. For example, if you forbid a\ngraph to be inconsistent, elapsed time will substantially shrink:\n\n``` Clojure\n\"Elapsed time: 633.909367 msecs\" ;; accumulation\n\"Elapsed time: 432.91587 msecs\"  ;; substraction\n``` \n\nComputation time can be further reduced with the asumption of rooted tree.\n\n## Thanks\n\n* William E. Byrd\n* Any other people cited in his dissertation\n\n## License\n\nCopyright © 2016 piotr-yuxuan\n\nDistributed under the GNU General Public License either version 3.0 or (at your\noption) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotr-yuxuan%2Fpolygam","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiotr-yuxuan%2Fpolygam","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotr-yuxuan%2Fpolygam/lists"}