-
Notifications
You must be signed in to change notification settings - Fork 22
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
differing results between runs #8
Comments
Here is a smaller example with fewer ones which also shows different results between runs - alternating between 5 and 6 (usually 6). # tmp.py
import qm
q = qm.QuineMcCluskey()
simple = q.simplify([1,2,5,6,7,8,9,10,11,12,13,14,17])
print(len(simple), simple) $ python tmp.py
6 {'01-0-', '0011-', '0--10', '-0001', '010--', '0--01'}
$ python tmp.py
5 {'001-1', '-0001', '01-0-', '010--', '0--10'} |
Hi. I just wanted to add that I have similar effects and that I can reproduce the effects on @travisstaloch's minimal example.
Edit:
|
I'm experiencing the same behaviour on the included test suite. I created a small script which runs the
The script itself is just import subprocess
res = {0: 0, 1: 0}
for _ in range(100):
ret = subprocess.run(["python", "tests/test.py"], check=False)
res[ret.returncode] += 1
print(res) |
I'm doing some investigation of what the problem might be. I'm working with @travisstaloch's example. First thing I have noticed is that the result of the call to I then sorted the results and in runs returning 28 and 29 the implicants are the same. This is not the case for >>> for x in a.union(b): print(x, x in a, x in b)
...
001111000 True True
110001111 True True
011110100 True True
0-0001110 True True
01110-011 True False
0000-100- True True
011000100 True True
000--0110 False True
000-10101 True True
00000--1- True True
010111001 True True
-11101111 True True
000001--- True True
001100101 True True
0001-11-0 True True
111111100 True True
-00010111 True True
011-10011 True True
01-110011 True True
00-011001 True True
0000-1-01 True True
0000101-- True True
0000--1-1 True True
011101-11 True True
0000-011- True False
001111101 True True
000-0110- True True
0111-0011 False True
0001--110 True True
00000---1 True True
01111001- True True
000-0011- True True
0-0110011 True True
01110111- True True
00-110110 True True
00-010111 True True I have also tried hard-coding only one version of the After drilling down into the >>> sorted(a)
['-00010111', '-11101111', '0-0001110', '0-0110011', '00-010111', '00-011001', '00-110110', '000--0110', '000-0011-', '000-0110-', '000-10101', '0000--1-1', '0000-1-01', '0000-100-', '00000---1', '00000--1-', '000001---', '0000101--', '0001--110', '0001-11-0', '001100101', '001111000', '001111101', '01-110011', '010111001', '011-10011', '011000100', '01110-011', '011101-11', '01110111-', '01111001-', '011110100', '110001111', '111111100']
>>> sorted(b)
['-00010111', '-11101111', '0-0001110', '0-0110011', '00-010111', '00-011001', '00-110110', '000-0011-', '000-0110-', '000-10101', '0000--1-1', '0000-1-01', '0000-100-', '00000---1', '00000--1-', '000001---', '0000101--', '0001--110', '0001-11-0', '001100101', '001111000', '001111101', '01-110011', '010111001', '011-10011', '011000100', '0111-0011', '011101-11', '01110111-', '01111001-', '011110100', '110001111', '111111100'] I added this print Original code: non-deterministic for t in sorted(list(groups.keys()), reverse=True):
for g in groups[t]:
if not perms[g] <= ei_range:
ei.add(g)
ei_range |= perms[g] Code with sort: deterministic for t in sorted(list(groups.keys()), reverse=True):
for g in sorted(groups[t]):
if not perms[g] <= ei_range:
ei.add(g)
ei_range |= perms[g] Code with reverse sort: deterministic for t in sorted(list(groups.keys()), reverse=True):
for g in sorted(groups[t], reverse=True):
if not perms[g] <= ei_range:
ei.add(g)
ei_range |= perms[g] This is not a surprise as the sets have no order. I don't understand the algorithm enough to judge which order is the correct one but when sorting them in the reverse order, the tests pass in 100% of the runs I did. When sorting them in ascending order they fail in 100% of cases. With the benefit of hindsight one can guess that Pypi is storing sets in deterministic way (at least across multiple deterministic runs) but Cpython is at least using different seed for the hash function used to represent the sets. Both implementations appear to be using hash tables under the hood for sets. It would be great if somebody could double-check the order is actually supposed to be like this. |
Wow. Thanks @tomas789 for your in-depth investigation. Would be great if @tpircher-zz could take a look at your investigation and the PR. |
First of all, thank you for sharing this nice implementation. I've been experimenting with porting it to zig in hopes of using it in zig's universal headers project. The aim of that project is to compress their distributed c headers and so quine-mccluskey has come up.
I've been randomly generating ones and checking the results of
qm.simple(random_ones)
against my port. While doing so, i think I've found some type of problem with the results. The following script shows either 28 or 29 for the length of the simplified implicants. When run in a loop 100 times, the length is the same each 100 times but varies between runs - once again either 100 28s or 100 29s.So I am not sure what to make of this. I'm not sure if its a bug or just an inherent limitation. I've been doing a some print debugging and noticed that the length of
essential_implicants
seems change between 33 and 34. This is as far as I've looked so far and thought i would ask for advice before digging any further. Any idea why this might be happening?The text was updated successfully, but these errors were encountered: