{"id":13507155,"url":"https://github.com/dkendal/aruspex","last_synced_at":"2025-04-11T04:32:59.268Z","repository":{"id":36115058,"uuid":"40417301","full_name":"Dkendal/aruspex","owner":"Dkendal","description":"A configurable constraint solver","archived":false,"fork":false,"pushed_at":"2016-07-10T22:20:38.000Z","size":159,"stargazers_count":39,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T22:04:10.977Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dkendal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-08T21:46:27.000Z","updated_at":"2025-01-13T23:09:15.000Z","dependencies_parsed_at":"2022-09-03T11:10:46.282Z","dependency_job_id":null,"html_url":"https://github.com/Dkendal/aruspex","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/Dkendal%2Faruspex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dkendal%2Faruspex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dkendal%2Faruspex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dkendal%2Faruspex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dkendal","download_url":"https://codeload.github.com/Dkendal/aruspex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345202,"owners_count":21088231,"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-08-01T02:00:25.418Z","updated_at":"2025-04-11T04:32:59.231Z","avatar_url":"https://github.com/Dkendal.png","language":"Elixir","funding_links":[],"categories":["Algorithms and Data structures"],"sub_categories":[],"readme":"# Aruspex\nAruspex is a configurable [constraint\nsolver](https://en.wikipedia.org/wiki/Constraint_satisfaction_problem), written\npurely in Elixir.\n\nAruspex does, or atleast has the capacity to, support multiple constraint problem\nsatisfaction strategies. Because of this property it is theoretically capable\nof supporting various types of CSPs.\n\nAt the time of writing Aruspex ships with one strategy, simulated annealing,\nwhich supports weighted CSPs.\n\n**This readme refers to master, please check the readme for your release.**\n\n## Example\nGiven a map of Australia, find some colouring of teritories, such that no adjacent territory has the same colour.\n\n![](http://australia.pppst.com/Australia_map_regions.gif)\n\n```elixir\nimport Aruspex.Server\nuse Aruspex.Constraint\n\n{:ok, problem} = start_link\n\nvariables = [\n  wa  = :western_australia,\n  nt  = :nothern_territory,\n  q   = :queensland,\n  sa  = :south_australia,\n  nsw = :new_south_wales,\n  v   = :victoria,\n  t   = :tasmania\n]\n\ndomain = [:red, :green, :blue]\n\nEnum.map variables, \u0026(variable problem, \u00261, domain)\n\nproblem\n|\u003e set_search_strategy(Aruspex.Strategy.SimulatedAnnealing)\n# adjacent territories cannot be the same colour\n# The pin operator is used to reference a named variable in a constraint,\n# check the section on variables below.\n|\u003e post(linear ^wa != ^nt)\n|\u003e post(linear ^wa != ^sa)\n|\u003e post(linear ^sa != ^nt)\n|\u003e post(linear ^sa != ^q)\n|\u003e post(linear ^sa != ^nsw)\n|\u003e post(linear ^sa != ^v)\n|\u003e post(linear ^nt != ^q)\n|\u003e post(linear ^q != ^nsw)\n|\u003e post(linear ^nsw != ^v)\n|\u003e find_solution\n|\u003e IO.inspect\n# [ new_south_wales:    :blue,\n#   nothern_territory:  :blue,\n#   queensland:         :green,\n#   south_australia:    :red,\n#   tasmania:           :green,\n#   victoria:           :green,\n#   western_australia:  :green ]\n```\n\nFor some more examples checkout [these.](test/support/examples/)\n\n## Usage\nCheck the api exposed by `Aruspex.Server`\n\n### Creating a new problem\nAruspex uses a `GenServer` under the hood, to create a new problem simply use\n```elixir\n{:ok, pid} = Aruspex.Server.start_link\n```\n\n### Defining a new variable\nA literal is used to name a new variable, and a domain is specified for the\nvariable.  This literal will be used to reference the variable later when\ndefining constraints and will appear in the solution.\n```elixir\n@spec variable(pid, Literals, Enum.t) :: pid\n^pid = Aruspex.Server.variable(pid, :x, 1..100)\n```\n\n### Defining a new constraint\nAdding a new constraint is called *posting* a constraint. Posting a constraint\nrequires specifying the variables that participate in the constraint, as well\nas a function the returns a *cost* when tested.\n\nStrategies attempt to minimize\nthe cost of all constraints, where a total cost of 0 would be a perfect\nsolution.\n\n#### all_diff/1\nConstraints may be defined using built in constraints:\n\n```elixir\npid\n|\u003e post(all_diff [:x, :y])\n```\n\nThe `all_diff` constraint would impose a condition that all variables specified\nmust be unique.\n\n#### linear/1\nusing the `linear/{1,2}` macro (only supports clauses that can be inlined -\nonly expressions that can appear in guard clauses):\n\n```elixir\npid\n|\u003e post(linear ^:x == ^:y)\n```\n\ninside the body of the `linear/1` macro pinned literals indicate that the value\nrefers to a named variable which will be substituted in during compilation.\npinned variables may also be used to the same effect.\n\nunpinned values will be used by value.\n\n```elixir\nsome_var = :x\nz = 1\npid\n|\u003e post(linear ^some_var == ^:y + z)\n```\n\nis equivalent to:\n\n```elixir\npid\n|\u003e post(linear ^:x == ^:y + 1)\n```\n\n#### linear/2\nIn it's second form, the named variables may be defined explicitly, and matched\non.\n\n```elixir\npid\n|\u003e post(linear [:x, :y],\n               [{x1, _}, {_, y2}] when x1 == y2)\n```\n\n#### constraint/1\nUser defined constraints are also supported by using the constraint record\ndirectly.\n\nStrategies will test constraints by applying the values for `variables`, in\nthe order specified, to `function`.\n\n`function` **must** have a type of `[Literals] -\u003e number`.\n\n```elixir\npid\n|\u003e post(constraint(\n  variables: [:v, :w],\n  function: fn ([v, w]) -\u003e\n    cond do\n      v \u003e 10 -\u003e\n        100\n      w \u003c 10 -\u003e\n        9999\n      true -\u003e\n       0\n    end\n  end\n))\n```\n## Roadmap\n- [ ] configurable settings for s.a. strategy (run time, cooling strategy, etc.)\n- [ ] configurable tolerance for what is an acceptable solution (default is only perfect solutions)\n- [ ] allow strategies to return multiple soltuions with message box.\n- [ ] allow multiple strategies to be employed, which will act as middlewear.\n- [ ] user defined optimization tolerance\n- [ ] implement more common constraints from [the global constraint catalog](http://www.emn.fr/z-info/sdemasse/gccat/sec5.html).\n- [ ] add additional strategies\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkendal%2Faruspex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkendal%2Faruspex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkendal%2Faruspex/lists"}