-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Swift wrapper #5
Comments
I'm writing a C++11 wrapper, too. And I also find this issue. the amoeba.lua is a pure Lua implement, but lua_amoeba.c is real a Lua binding for C implement of amoeba. In this binding, I still need a solver to create variable/constraint. this API is intend to solve the pure C memory management issue. all objects are under the same memory pool. so a solver is likely a arena. you could allocate any object you want in this arena, and after am_delsolver(), all objects are freed. So, in my C++11 solution, I'm trying to construct constraint in pure C++ way, recording all variable and terms it used, and when add to solver, it will be convert into amoeba object. In this way, you could create object apart from solver itself. Another way is always using the amoeba object, something like this: Solver solver;
Variable xl(solver), xm(solver), xr(solver);
solver.add((xl + 10 < xr) / amoeba::Required); notice that you could add a solver pointer into variable, so creating a constraint object is easy. this is the way of the Lua binding. I don't know which is better, amoeba is a pure C library, means I must manage all memory it use. So I could not create objects part from it (or you had call am_del** on any object you created, just like other C libraries). We could work out some better solution, any feedback are welcome :-) |
A idea, if I add some routines to copy/assignment data across solver, maybe we could make a static solver for allocate temporary objects, and copy it into the solver it will be added. |
Yep, trying that out now. Seems promising. |
Can you explain What happens when a constraint already is added to the solver and you change the constraint? Example: add a new term after the constraint has been added. |
|
|
constraint is just like expression, e.g. x >= 10 means x - 10 >= 0, so constraint only have two state (kiwi has three state, >=, <= and ==) for example, if you want spec a + b <= 10 + c, it become this:
notice that if you set relation to so, the constraint always in form |
Thanks for that thorough explanation! Very useful! I am making progress here. This is f***ing amazing! This is done using only pointers and no wrappers (except for the solver) do {
let solver = AMSolver() // solver is a swift solver class
let x = solver.createVariable() // x is a `am_Variable *`
let c = solver.createConstraint(strength: Strength.required) // c is a `am_Constraint *`
try c.setRelation(.eq)
try c.addTerm(variable: x, multiplier: 1.0)
try c.addConstant(-10)
try c.addToSolver()
print("value of x: \(x.value)")
} catch let error {
print("Error \(error)")
} Outputs
I also tested creating wrappers around variable, term and constraint do {
let solver = Solver() // solver is a swift `Solver` class
let x = Variable() // x is a swift `Variable` class
let c = Constraint() // c is a swift `Constraint` class
c.relation = .eq
c.strength = Strength.required
c.add(term: Term(variable: x, multiplier: 1.0))
c.add(constant: -10)
try solver.add(constraint: c)
print("value of x: \(solver.value(x))")
} catch let error {
print("Error \(error)")
} Outputs
I will check more closely wether I need this object oriented approach or if I kind just extend the pointers in Swift. I kind of like the first alternative. It is the least memory intensive, but I have a couple of questions. What happens if someone uses I'm impressed how easy it is to use this c api's like this from Swift. |
you can't. the solver is just like a arena, all object allocated by it. after delete solver, all object relate with it (variables, constraints, etc) are all freed, if you still have these pointer, they will become wild pointer. so in Lua/C++11 wrapper, I make a weak-referenced mapping between object and solver, if delete the solver, I will clear all pointers in object. |
I see! But what if I call am_usevariable() and friends? Still wild pointers? |
This logic will need to be duplicated/added to a pure swift constraint I guess. Very useful that you took the time to explain it. |
yes, even if you call usevariable. And you needn't duplicate this logic, even needn't do e.g. Merge the same variable. I just recorded all expressions using a vector, and leave things when add constraints into solver. |
Good idea. Can I see the preliminary c++ code? |
Can swift override operators? If it can't,you just need bind the current interface, and if it can, you could record the expressions, yet. Because operators always create new object, amoeba objects are cheap, but swift objects may cheaper. |
Yep, I'm creating operator overloads as we speak :) |
I'm still working on it(and changing API when necessary), after finished I will upload it. And if you need new functionality I can add them for you. :-) |
You could do some benchmarks to determine whether swift or amoeba object cheaper, and deciding how to implement operator overrides |
I'm currently at this point let solver = Solver()
let v1 = Variable()
let v2 = Variable()
try solver.add(v1 / 2 == v2 * 3)
try solver.add(v1 + v1 - v1 == 8)
print("value of v1: \(solver.value(v1))")
print("value of v2: \(solver.value(v2))")
In native swift classes I have now Solver, Variable, Term, Expression, Constraint. I had to create Expression in order to compile time enforce that it isn't possible to say |
the correct way to avoid a == b <= 3 is using typing:
this is how kiwi and my wrapper done. |
Yep, that's what Rhea did as well.
|
Currently
Should we keep all in one repo or should it be in separate? I'm in favor of keeping them all together if the API is similar. My swift wrapper may support string parsing etc as well, but I don't know if that's too much. Any thoughts on this? |
Yes, I prefer together, too. should we build separate folders for different bindings? pull requests welcome :-) |
Sounds good. I'm packing quite a lot into the swift wrapper. So I think I will divide my code as following
It may be necessary to place a |
yes, that seems good. |
How's the c++ project going btw? |
because C++ project only one header, so I plan to put it direct into this project :-) I have not much time for the end of year :-( so I will put the source later, as soon as I have time, sorry. |
I see. How big is that file (line count)? |
I am looking into creating a wrapper around this api in Swift. I'm facing some difficult choices.
All variables are created using a solver and the solvers am_Allocf. This makes it hard to create an object oriented model as they are tied to the solver pretty closely. This is seen throughout the API as well. Example:
To me I now think it is not feasible to create an object oriented swift model around Amoeba unless variables, terms and constraints can be created independently from the solver.
Methods like
would have to be rewritten to
This is not a request to change anything. I'm just thinking loudly :) amoeba.lua is not a wrapper, but the whole implementation written in Lua if I understand correctly?
The text was updated successfully, but these errors were encountered: