- Notifications
You must be signed in to change notification settings - Fork 4
Description
I've been trying to compare PyVSC and constrainedrandom's performance when it comes to randomization of 2D-arrays. The test case is a "checkerboard randomization", where each field can be 0 or 1, but cannot have the same value as its neighbours.
Consider the following implementations
PyVSC
import vsc import timeit @vsc.randobj class Checkers(): def __init__(self, N): self.N = N self.board = [vsc.rand_list_t(vsc.rand_uint8_t(), self.N) for _ in range(self.N)] @vsc.constraint def con_values(self): for row in self.board: with vsc.foreach(row) as c: 0 <= c and c <= 1 @vsc.constraint def constraints(self): for i in range(1, self.N): with vsc.foreach(self.board[i], idx=True) as j: if j == 0: pass (self.board[i][j] != self.board[i-1][j]) and (self.board[i][j] != self.board[i][j-1]) def benchmark(): numRounds = 10 for N in (4, 8, 16, 32, 64, 128, 256): t = timeit.timeit(stmt='c.randomize()', setup=f'c = Checkers({N})', number=numRounds, globals=globals()) print(f"N={N:4d}: Runtime: {t/numRounds}") benchmark()constrainedrandom
from constrainedrandom import RandObj import timeit class Checkers(RandObj): def __init__(self, N): super().__init__(max_iterations=1000) self.N = N for i in range(self.N): self.add_rand_var(f"list{i}", domain=range(2), length=self.N, disable_naive_list_solver=True) for i in range(1, self.N): for j in range(1, self.N): self.add_constraint((lambda row1, row2: row1[j] != row2[j]), (f"list{i-1}", f"list{i}")) self.add_constraint((lambda row: row[j-1] != row[j]), (f"list{i}", )) def benchmark(): numRounds = 10 for N in (4, 8, 16, 32, 64, 128, 256): t = timeit.timeit(stmt='c.randomize()', setup=f'c = Checkers({N})', number=numRounds, globals=globals()) print(f"N={N:4d}: Runtime: {t/numRounds}") benchmark()The average runtimes reported for the two on my machine are as follows. The fields labeled "DNF" took so long that I didn't bother waiting for them to complete
| N | PyVSC | constrainedrandom |
|---|---|---|
| 4 | 0.008 | 0.001 |
| 8 | 0.029 | 1.265 |
| 16 | 0.112 | 45.786 |
| 32 | 0.305 | DNF |
| 64 | 1.208 | DNF |
| 128 | 5.371 | DNF |
| 256 | 22.421 | DNF |
As you can see, the performance of PyVSC seems vastly superior to the performance of constrainedrandom. However, I am unsure whether my implementation with constrainedrandom is optimal, but I haven't found a better way of implementing 2D-arrays and randomization thereof.
Is there a better way of constraining this problem that would lead to better performance with constrainedrandom?