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

csp convert to binary #81

Open
matanhol opened this issue Jan 11, 2023 · 1 comment
Open

csp convert to binary #81

matanhol opened this issue Jan 11, 2023 · 1 comment

Comments

@matanhol
Copy link

matanhol commented Jan 11, 2023

Hi,

I'm using the library for solving cryptarithmetic problems ("SEND"+"MORE"="MONEY" where each letter stands for some digits) by converting it to CSP
then I use convert_to_binary to convert the constraints to binary ones, thus speeding the backtracking
I tried the usual "SEND" + "MORE" = "MONEY", "TWO"+"TWO"="FOUR", it works great with and without binarization
but when
"CBA" + "MMMCBA" = "ROOOODE"
this has a solution as 543+999543=1000086 and it gives me that when I call backtrack without binarization.
but after binarization it gives me 745+999745=1000068 which does not satisfy the constraints.
maybe there is some bug in convert_to_binary?

what I understand the problem is here (csp.py line 239)
new_domains[hidden] = [t for t in product(*map(domains.get, vars_)) if const(vars_, t)]
in case of same variable appear twice in the constraint (A + A = E + carry), it still creates a domain which is the cartesian product D_A X D_A X D_E X D_carry, though different assignments to same variable should not be allowed (e.g. the tuple (9, 8, 7, 1) is not allowed, only (9, 9, 7, 1 ). must somehow ensure that in the hidden variable possible vector all appearances of the same variable get the same value. because when it checks inside wdiff.diff it checks only the index of the first appearance in vars_ (since that what vars_.index returns)

I solved this by adding a condition "same_variable_same_assignment(vars_, t)" in line 239:
new_domains[hidden] = [t for t in product(*map(domains.get, vars_))
if const(vars_, t) and same_variable_same_assignment(vars_, t)]
where:
def same_variable_same_assignment(vars_, t):
....unique_vars = set(vars_)
....for var_ in unique_vars:
........inds = [i for i in range(len(vars_)) if vars_[i]==var_]
........if any([t[ind]!=t[inds[0]] for ind in inds]):
............return False
....return True

Thanks

@fisadev
Copy link
Member

fisadev commented Jan 18, 2023

Hi! thanks for the report and the proposed solution! I'm a little busy with work and other stuff during these days, but I'll try to take a better look at this in the following couple of weeks :)

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

2 participants