0
$\begingroup$

discrete math problems

In the recent project, I encountered a puzzle, thought for several days, I simplified it. I will be very grateful for your help.

  • 0
    I've looked at your proposed edit that was rejected. I think that in the interest of readability, you should maybe add your modified code to your post, or post a separate answer of yours that explains the changes to the problem formulation that require the changes to the script. Regarding vectorization, I don't think that's the solution. Setting up the constraints is not where the time goes. Almost all the time is spent in `s.check()` and there you are staring NP-completeness in the face.2017-02-17

1 Answers 1

0

A solution for $N=7$ with the smallest value for $\omega_N$ is this:

$$ W = \begin{bmatrix} 25 & 26 & 28 & 29 & 34 & 36 & 37 \end{bmatrix} $$

$$M = \begin{bmatrix} 0 & 24 & 22 & 21 & 16 & 14 & 13 \\ 27 & 0 & 24 & 23 & 18 & 16 & 15 \\ 31 & 30 & 0 & 27 & 22 & 20 & 19 \\ 33 & 32 & 30 & 0 & 24 & 22 & 21 \\ 43 & 42 & 40 & 39 & 0 & 32 & 31 \\ 47 & 46 & 44 & 43 & 38 & 0 & 35 \\ 49 & 48 & 46 & 45 & 40 & 38 & 0 \end{bmatrix}$$

This solution is generated by this z3py script:

""" Find 0 < w1 < w2 < ... < wN < 1.5 w_1 such that all values of
    2wi - wj for i != j are distinct from all wk.
"""
from __future__ import print_function
from z3 import *

N = 7
omega = [Int('omega_%s' % (i+1)) for i in range(N)]

s = Solver()

s.add(omega[0] > 0)
for i in range(1,N):
    s.add(omega[i] > omega[i-1])
s.add(2*omega[-1] < 3*omega[0])

# Impose upper bound on omega[-1] to find "smallest" solution.
s.add(omega[-1] < 38)

for i in range(N):
    for j in range(i+1,N):
        for w in omega:
            s.add(2*omega[i] - omega[j] != w)
            s.add(2*omega[j] - omega[i] != w)

result = s.check()
if result == sat:
    mdl = s.model()
    print('W =', ' '.join([str(mdl.evaluate(w).as_long()) for w in omega]))

    mat = [[0] * N for _ in range(N)]
    for i in range(N):
        for j in range(i):
            orow = mdl.evaluate(omega[i]).as_long()
            ocol = mdl.evaluate(omega[j]).as_long()
            mat[i][j] = 2 * orow - ocol
            mat[j][i] = 2 * ocol - orow

    print('\n'.join([' '.join(['{:3}'.format(item) for item in row])
                    for row in mat]))
else:
    print(result)
  • 0
    Very thanks, your solution is absolutely correct. But what confused me is that for larger N, how to find a proper sequence W.2017-02-16
  • 0
    @YanXu I've used [Z3](https://github.com/Z3Prover/z3) and I was able to get solutions for $N$ up to $32$ is a few seconds. The values of the $\omega_i$'s though got quite large (approximately 4 billions) and imposing upper bounds on their values resulted in much harder satisfiability problems.2017-02-16
  • 0
    I have not known Z3 yet, needing some time to learn it. Thanks a lot.2017-02-16
  • 0
    Z3 is a power SMT Solver. I have learned the Z3 tutorial, but could't model the problem. Can you tell me the Z3 code to help me understand?2017-02-16
  • 0
    @YanXu I've added the Python code I used. For this type of problems it's usually more convenient than the SMT-LIB 2 language. The drawback is that you have to install Z3 on your machine.2017-02-16
  • 0
    Much thanks. The python code helps me a lot.2017-02-16
  • 0
    I have understood the python code and solved my problem, thank you very much again.2017-02-16