{"id":19599733,"url":"https://github.com/starwing/amoeba","last_synced_at":"2025-04-27T16:32:08.681Z","repository":{"id":60130687,"uuid":"61445801","full_name":"starwing/amoeba","owner":"starwing","description":"a Cassowary constraint solving algorithm implements in pure C.","archived":false,"fork":false,"pushed_at":"2021-01-15T06:31:31.000Z","size":115,"stargazers_count":177,"open_issues_count":6,"forks_count":24,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-09-18T01:20:52.990Z","etag":null,"topics":["cassowary-algorithm","constraint-solving-algorithm","lua-language","single-header-lib"],"latest_commit_sha":null,"homepage":null,"language":"C++","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/starwing.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2016-06-18T17:51:19.000Z","updated_at":"2024-08-30T21:30:00.000Z","dependencies_parsed_at":"2022-09-25T23:23:16.438Z","dependency_job_id":null,"html_url":"https://github.com/starwing/amoeba","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starwing%2Famoeba","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starwing%2Famoeba/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starwing%2Famoeba/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starwing%2Famoeba/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/starwing","download_url":"https://codeload.github.com/starwing/amoeba/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251171450,"owners_count":21547112,"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":["cassowary-algorithm","constraint-solving-algorithm","lua-language","single-header-lib"],"created_at":"2024-11-11T09:12:16.949Z","updated_at":"2025-04-27T16:32:08.420Z","avatar_url":"https://github.com/starwing.png","language":"C++","readme":"# Amoeba -- the constraint solving algorithm in pure C\n\n[![Build Status](https://travis-ci.org/starwing/amoeba.svg?branch=master)](https://travis-ci.org/starwing/amoeba)\n[![Coverage Status](https://coveralls.io/repos/github/starwing/amoeba/badge.svg?branch=master)](https://coveralls.io/github/starwing/amoeba?branch=master)\n\nAmoeba is a pure C implement of Cassowary algorithm.\nAmoeba use Clean C, which is the cross set of ANSI C89 and C++, like\nthe Lua language.\n\nAmoeba is a single-file library, for more single-file library, see the\nstb project [here][1].\n\nAmoeba largely impressed by [kiwi][2], the C++ implement of Cassowary\nalgorithm, and the algorithm [paper][3].\n\nAmoeba ships a hand written Lua binding.\n\nAmoeba has the same license with the [Lua language][4].\n\n[1]: https://github.com/nothings/stb\n[2]: https://github.com/nucleic/kiwi\n[3]: http://constraints.cs.washington.edu/solvers/uist97.html\n[4]: https://www.lua.org/license.html\n\n## How To Use\n\nThis libary export a constraint solver interface, to solve a constraint problem, you should use it in steps:\n\n- create a new solver: `am_newsolver()`\n- create some variables: `am_newvariable()`\n- create some constraints that may use variables: `am_newconstraint()`\n- make constraints by construct equation using:\n  - `am_addterm()` add a $a \\times variable$ term to constraint equation items\n  - `am_setrelation()` to specify the equal/greater/less sign in center of equation\n  - `am_addconstant()` to add a number without variable\n  - `am_setstrength()` to specify the priority of this constraint in all constraints\n- after make up a constraint, you could add it into solver by `am_add()`\n- and you can read out the result of each variable with `am_value()`\n- or you can manually specify a new value to variable with `am_sugguest()`\n- after done, use `am_delsolver()` to free al memory\n\nbelow is a tiny example to demonstrate the steps:\n\n```c\n#define AM_IMPLEMENTATION // include implementations of library\n#include \"amoeba.h\"       // and interface\n\nint main(void)\n{\n    // first, create a solver:\n    am_Solver *S = am_newsolver(NULL, NULL);\n\n    // create some variable:\n    am_Var *l = am_newvariable(S);\n    am_Var *m = am_newvariable(S);\n    am_Var *r = am_newvariable(S);\n\n    // create the constraint: \n    am_Constraint *c1 = am_newconstraint(S, AM_REQUIRED);\n    am_Constraint *c2 = am_newconstraint(S, AM_REQUIRED);\n\n    // c1: m is in middle of l and r:\n    //     i.e. m = (l + r) / 2, or 2*m = l + r\n    am_addterm(c1, m, 2.f);\n    am_setrelation(c1, AM_EQUAL);\n    am_addterm(c1, l, 1.f);\n    am_addterm(c1, r, 1.f);\n    // apply c1\n    am_add(c1);\n\n    // c2: r - l \u003e= 100\n    am_addterm(c2, r, 1.f);\n    am_addterm(c2, l, -1.f);\n    am_setrelation(c2, AM_GREATEQUAL);\n    am_addconstant(c2, 100.f);\n    // apply c2\n    am_add(c2);\n\n    // now we set variable l to 20\n    am_suggest(l, 20.f);\n\n    // and see the value of m and r:\n    am_updatevars(S);\n\n    // r should by 20 + 100 == 120:\n    assert(am_value(r) == 120.f);\n\n    // and m should in middle of l and r:\n    assert(am_value(m) == 70.f);\n    \n    // done with solver\n    am_delsolver(S);\n    return 0;\n}\n```\n\n\n\n## Reference\n\nAll functions below that returns `int` may return error codes:\n\n- `AM_OK`: the operations success.\n- `AM_FAILED`: the operation fail\n- `AM_UNSATISFIED`: can not add specific constraints into solver\n- `AM_UNBOUND`: add specific constraints failed because variables in constraints unbound\n\nRoutines:\n\n- `am_Solver *am_newsolver(am_Allocf *allocf, void *ud);`\n\n  create a new solver with custom memory alloculator, pass NULL for use default ones.\n\n- `void am_resetsolver(am_Solver *solver, int clear_constraints);`\n\n  remove all variable suggests from solver.\n\n  if `clear_constraints` is nonzero, also remove and delete all constraints from solver.\n\n- `void am_delsolver(am_Solver *solver);`\n\n  delete a solver and frees all memory it used, after that, all variables/constraints created from this solver are all freed.\n\n- `void am_updatevars(am_Solver *solver);`\n\n  refresh variables' value into it's constrainted value, you could use `am_autoupdate()` to avoid call this routine every time on changing constraints in solver.\n\n- `void am_autoupdate(am_Solver *solver, int auto_update);`\n\n  set auto update flags, if set, all variable will auto update to its' latest value after any changes to solver.\n\n- `int am_hasedit(am_Var *var);`\n\n  check whether a variable has suggested value in solver.\n\n- `int am_hasconstraint(am_Constraint *cons);`\n\n  check whether a constraint has been added into solver.\n\n- `int am_add(am_Constraint *cons);`\n\n  add constraint into solver it's created from.\n\n- `void am_remove(am_Constraint *cons);`\n\n  remove added constraint.\n\n- `int am_addedit(am_Var *var, am_Num strength);`\n\n  prepare to change the value of variables or the `strength` value if the variable is in edit now.\n\n- `void am_suggest(am_Var *var, am_Num value);`\n\n  actually change the value of the variable `var`, after changed, other variable may changed due to the constraints in solver. if you do not want change the strength of suggest (default is `AM_MEDIUM`), you may call this routine directly.\n\n- `void am_deledit(am_Var *var);`\n\n  cancel the modify of variable, the value will restore to the referred value according the solver.\n\n- `am_Var *am_newvariable(am_Solver *solver);`\n\n  create a new variable. variable is reference counting since it may used in serveral constraints,\n\n  so if you want store it in multiple place, call `am_usevariable()` before. \n\n- `void am_usevariable(am_Var *var);`\n\n  add the reference counting of a variable to avoid it been freed.\n\n- `void am_delvariable(am_Var *var);`\n\n  sub the reference counting of a variable, and free it when the count down to 0.\n\n- `int am_variableid(am_Var *var);`\n\n  return a unqiue id (within solver) of the variable `var`.\n\n- `am_Num am_value(am_Var *var);`\n\n  fetch the current value of variable `var`, note that if auto update not set and `am_updatevars()` not called, the value may not the latest values that inferred by solver.\n\n- `am_Constraint *am_newconstraint(am_Solver *solver, am_Num strength);`\n\n  create a new constraints.\n\n- `am_Constraint *am_cloneconstraint(am_Constraint *other, am_Num strength);`\n\n  make a new constraints from existing one, with new `strength`\n\n- `void am_resetconstraint(am_Constraint *cons);`\n\n  remove all terms and variables from the constraint.\n\n- `void am_delconstraint(am_Constraint *cons);`\n\n  frees the constraint. if it's added into solver, remove it first.\n\n- `int am_addterm(am_Constraint *cons, am_Var *var, am_Num multiplier);`\n\n  add a term into constraint, e.g. a constraint like $2*m = x + y$, the terms are $2*m$, $1*x$ and $1*y$.\n\n  so makeup this constraint you could:\n\n  ```c\n  am_addterm(c, m, 2.0); // 2*m\n  am_setrelation(c, AM_EQUAL); // =\n  am_addterm(c, x, 1.0); // x\n  am_addterm(c, y, 1.0); // y\n  ```\n\n- `int am_setrelation(am_Constraint *cons, int relation);`\n\n  set the relations of constraint, could be one of these:\n\n  - `AM_EQUAL`\n  - `AM_GREATEQUAL`\n  - `AM_LESSEQUAL`\n\n  the terms added before `am_setrelation()` become the left hand terms of constraints, and the terms adds after call will become the right hand terms of constraints.\n\n- `int am_addconstant(am_Constraint *cons, am_Num constant);`\n\n  add a constant without variable into constraint as a term.\n\n- `int am_setstrength(am_Constraint *cons, am_Num strength);`\n\n  set the strength of a constraint.\n\n- `am_mergeconstraint(am_Constraint *cons, const am_Constraint *other, am_Num multiplier);`\n\n  merge other constraints into `cons`, with a multiplier multiples with `other`.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarwing%2Famoeba","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstarwing%2Famoeba","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarwing%2Famoeba/lists"}