Skip to content
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

[kiwijs] Constraint C Strength affects the priority at which constraint A beats constraint B #33

Closed
cacaodev opened this issue May 25, 2017 · 6 comments

Comments

@cacaodev
Copy link

In this setup, there is initially one variable and two constraint. One Constraint (A) is an inequality, the other constraint (B) is an equality used to set a value on the variable. B can break A or not.

priority is a strength created like this : kiwi.Strength.create(0, 1, 0, priority).

A: variable >= 100 (priority 501)
B: variable = 90 (500)

After solving, the result is variable = 100 and is the expected result.

Now, if I add another equality constraint C with a very low priority variable = 50 (10) the variable value after solving is 90. It means that adding this constraint helps constraint B to break constraint A even if constraint B priority < A priority && C priority < A&B priority.

With the C constraint, the A priority needed to break constraint B is equal to (B + C).

A: variable >= 100 (501)
B: variable = 90 (500)
C: variable = 10 (10)
=> variable == 90 (Not expected)
A: variable >= 100 (511)
B: variable = 90 (500)
C: variable = 10 (10)
=> variable == 100 (Expected)

I also tried to suggestValue(variable, 90) instead of using constraint B and got the same results.

It seems that a third constraint affects the priority at which a constraint beats another , even if this third constraint priority is lower than the two other constraints fighting.

Is this a bug or the regular behavior ?

Test here: https://runkit.com/cacaodev/kiwi-bug (Hit the green button to run the test).

@sccolbert
Copy link
Member

This is expected behavior, because there is not enough difference in the weights/strengths to express your intent. Instead of using hand-coded numerical strengths, try using the predefined strengths, which have sufficient delta that they wont trample each other:
https://github.com/nucleic/kiwi/blob/master/kiwi/strength.h#L28-L34

For performance, stengths/weights are not treated with pure lexographic ordering. Instead they are converted to a sufficiently large number base so that strengths of a lower order will not effect strengths of a higher order.

In the end, a strength is just a multiplier on an error term, and the solver minimizes the error. The difference between 500 and 501 is not sufficient to make the error for the 100 solution be larger than the error for the 90 solution. However, the difference between 500 and 511 is (for this case).

Note that the difference between each of the three weak, medium, strong built in strengths is three orders of magnitude.

@cacaodev
Copy link
Author

cacaodev commented May 28, 2017

Thanks a lot, i have been able to get the correct result when using different strengths.

In case we need more than the 3 levels available (it is my case), I wonder is there is a way to calculate the minimum distance between levels to avoid that they clash each other.

@sccolbert
Copy link
Member

There's not a really way to do that, since it depends on how large the error is for the associated terms, and that varies based on the system of constraints which is being solved. The right way to solve it, would be to fully lexographic order the strengths internally. But as I mentioned, that way would be much slower than what we currently do.

@sccolbert
Copy link
Member

Your case may be fine by picking a 4 strength in the middle of the two you care about, or creating some other set of 4 (or more) strengths with sufficient distance between them.

@cacaodev
Copy link
Author

cacaodev commented May 28, 2017

I created sub-strengths but I was getting conflicts between them. The solution for me was to just generate numbers corresponding to new strengths higher than strong and with the same order of magnitude x1000 . Of course I had to redefine required higher.

@MatthieuDartiailh
Copy link
Member

Closing as the primary issue is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants