示例#1
0
def forward_ehalver(g, n, k, v, s, t):
    m = n//2
    c2 = []
    type1 = set()
    type3 = set()
    i = k % m
    imask = 1<<i
    for j in range(m):
        jmask = 1<<(j+m)
        if (not (v & imask)) and (v & jmask):
            type1.add(j)
        elif (v & imask) and (not (v & jmask)):
            w = v + jmask - imask
            c2.append(Implies(g[k, j], Equal(t[v], s[v] | s[w])).to_cnf())
        else:
            type3.add(j)

    if len(type1) > 0:
        cmp1 = [g[k, j] for j in range(m) if j not in type1]
        c1 = [Or(*(cmp1 + [~t[v]]))]
    else:
        c1 = []

    if len(type3) > 0:
        cmp3 = [g[k, j] for j in range(m) if j not in type3]
        c3 = [Or(*(cmp3 + [~t[v], s[v]])), Or(*(cmp3 + [t[v], ~s[v]]))]
    else:
        c3 = []

    return c1 + c2 + c3
示例#2
0
def forward_size(g, n, k, v, s, t):
    c2 = []
    type1 = set()
    type3 = set()
    for i in range(n - 1):
        for j in range(i + 1, n):
            imask = 1 << i
            jmask = 1 << j
            if (not (v & imask)) and (v & jmask):
                type1.add((i, j))
            elif (v & imask) and (not (v & jmask)):
                w = v + jmask - imask
                c2.append(
                    Implies(g[k, i, j], Equal(t[v], s[v] | s[w])).to_cnf())
            else:
                type3.add((i, j))

    if len(type1) > 0:
        cmp1 = [
            g[k, i, j] for i in range(n - 1) for j in range(i + 1, n)
            if (i, j) not in type1
        ]
        c1 = [Or(*(cmp1 + [~t[v]]))]
    else:
        c1 = []

    if len(type3) > 0:
        cmp3 = [
            g[k, i, j] for i in range(n - 1) for j in range(i + 1, n)
            if (i, j) not in type3
        ]
        c3 = [Or(*(cmp3 + [~t[v], s[v]])), Or(*(cmp3 + [t[v], ~s[v]]))]
    else:
        c3 = []
    return c1 + c2 + c3
示例#3
0
    def test_only_one_root(self):
        small_puzzle = P.Puzzle(["1", "2"], [["a", "b"]], [])
        sx = small_puzzle.X
        root_rule_form = (And( Or( And(sx[0,0,0], ~sx[0,0,1]), And(~sx[0,0,0], sx[0,0,1])),
        Or( And(sx[0,1,0], ~sx[0,1,1]), And(~sx[0,1,0], sx[0,1,1]))))

        self.assertTrue(And(*small_puzzle.only_one_root()).equivalent(root_rule_form))
示例#4
0
def update(g, first, last, k, i, v, w):
    c = []
    c += [Or(~v[i], oneDown(g, k, first, i), w).to_cnf()]
    c += [Or(v[i], oneUp(g, k, i, last), ~w).to_cnf()]
    c += [Or(used(g, first, last, k, i), Equal(w, v[i])).to_cnf()]
    c += [
        Implies(g[k, j, i], Equal(w, v[j] & v[i])).to_cnf()
        for j in range(first, i)
    ]
    c += [
        Implies(g[k, i, j], Equal(w, v[j] | v[i])).to_cnf()
        for j in range(i + 1, last)
    ]
    return c
示例#5
0
def no_adjacent_unused_channels(g, n, d):
    c = [g[d - 1, 0, 1] | g[d - 1, 1, 2]]
    c += [
        Or(g[d - 1, i - 1, i], g[d - 1, i, i + 1], g[d - 1, i + 1, i + 2])
        for i in range(1, n - 2)
    ]
    c += [g[d - 1, n - 3, n - 2] | g[d - 1, n - 2, n - 1]]
    return c
示例#6
0
def once_size(g, n, k):
    c = [
        ~g[k, i, j] | ~g[k, l, m] for i in range(n - 1)
        for j in range(i + 1, n) for l in range(i, n) for m in range(l + 1, n)
        if (i != l) or (j < m)
    ]
    c.append(Or(*[g[k, i, j] for i in range(n) for j in range(i + 1, n)]))
    return c
示例#7
0
def valid_ehalver(g, n, d):
    m = n//2
    c = []
    for k in range(0, d*m, m):
        for i in range(m):
            c += [~g[k + i, j] | ~g[k + i, l] for j in range(m) for l in range(j + 1, m)]
            c += [~g[k + j, i] | ~g[k + l, i] for j in range(m) for l in range(j + 1, m)]
            c.append(Or(*[g[k + i, j] for j in range(m)]))
    return c
def satisfy_all(rows_vars, cols_vars, horizontal, vertical):
    """Uses a SAT Solver to satisfy all horizontal and vertical propositions"""
    terms = []
    for i, row_var in enumerate(rows_vars):
        row_terms = []
        for combination in gen_all_combinations(horizontal[i],
                                                len(horizontal)):
            row_terms.append(
                And(*list(v if p else Not(v)
                          for v, p in zip(row_var, combination))))
        terms.append(Or(*row_terms))
    for i, col_var in enumerate(cols_vars):
        col_terms = []
        for combination in gen_all_combinations(vertical[i], len(vertical)):
            col_terms.append(
                And(*list(v if p else Not(v)
                          for v, p in zip(col_var, combination))))
        terms.append(Or(*col_terms))
    return And(*terms).tseitin().satisfy_all()
示例#9
0
def HMerge(a, b, prefix=''):
    n = len(a)
    if n == 1:
        if prefix == '':
            prefix = 'c'
        c = exprvars(prefix, 2)
        s = [Or(~a[0], ~b[0], c[1]), ~a[0] | c[0], ~b[0] | c[0]]
        return (c, s)
    else:
        c = exprvars(prefix + 'c', (1, 2 * n - 1))
        d, sd = HMerge(even(a), even(b), prefix + 'd')
        e, se = HMerge(odd(a), odd(b), prefix + 'e')
        v = [d[0]] + [x for x in c] + [e[-1]]
        sp = []
        for i in range(n - 1):
            sp.append(Or(*(~d[i + 1], ~e[i], c[2 * i + 2])))
            sp.append(~d[i + 1] | c[2 * i + 1])
            sp.append(~e[i] | c[2 * i + 1])
        s = sd + se + sp
        return (v, s)
示例#10
0
def second_last_layer(g, n, d):
    c = [~g[d - 2, i, j] for i in range(n) for j in range(i + 4, n)]
    c += [
        Or(~g[d - 2, i, i + 2], g[d - 1, i, i + 1], g[d - 1, i + 1, i + 2])
        for i in range(n - 2)
    ]
    c += [
        ~g[d - 2, i, i + 3] | g[d - 1, k, k + 1] for i in range(n - 3)
        for k in (i, i + 2)
    ]
    return c
示例#11
0
def SMerge(a, b, prefix=''):
    n = len(a)
    if n == 1:
        if prefix == '':
            prefix = 'c'
        c = exprvars(prefix, 2)
        s = [Or(~a[0], ~b[0], c[1]), ~a[0] | c[0], ~b[0] | c[0]]
        return (c, s)
    else:
        c = exprvars(prefix + 'c', (1, n + 1))
        d, sd = SMerge(even(a), even(b), prefix + 'd')
        e, se = SMerge(odd(a), odd(b), prefix + 'e')
        v = [d[0]] + list(c)
        sp = []
        for i in range(n // 2):
            sp.append(Or(~d[i + 1], ~e[i], c[2 * i + 2]))
            sp.append(~d[i + 1] | c[2 * i + 1])
            sp.append(~e[i] | c[2 * i + 1])
        s = sd + se + sp
        return (v, s)
示例#12
0
    def are_not(self, value1, value2):
        """
        Returns the formula where the two given (non-root) values are a not-- they do not occur at the same root value
        :param value1: str- an english variable that is in self.groups
        :param value1: str- an english variable that is in self.groups, that is not in the same category as value1
        :return Expr: the formula for this clue
        """
        (group_1, val_1) = self.get_val_tuple(value1)
        (group_2, val_2) = self.get_val_tuple(value2)
        f_arenot = Or(*[
            And(self.X[group_1, val_1, idx], ~self.X[group_2, val_2, idx])
            for idx in range(0, self.items_per)
        ])

        return f_arenot
示例#13
0
def once_depth(g, n, k):
    clauses_from = [
        ~g[k, i, j] | ~g[k, i, l] for j in range(n) for l in range(j)
        for i in range(l)
    ]
    clauses_to = [
        ~g[k, j, i] | ~g[k, l, i] for j in range(n) for l in range(j + 1, n)
        for i in range(l + 1, n)
    ]
    clauses_to_from = [
        ~g[k, j, i] | ~g[k, i, l] for j in range(n) for i in range(j + 1, n)
        for l in range(i + 1, n)
    ]
    once = [Or(*[g[k, i, j] for i in range(n) for j in range(i + 1, n)])]
    c = clauses_from + clauses_to + clauses_to_from + once
    return c
示例#14
0
def sorts_backward_size(g, n, kf, kl, xlist, s=0):
    ninputs = 1 << n
    c = []
    xset = set(xlist)

    # Input: TRUE for each input that is not sorted
    input = [TRUE if v != vsort(v) else FALSE for v in range(ninputs)]

    # Output variables
    o = exprvars('o', ninputs)
    if s == 0:
        # All sorted: 0 if already sorted by a prefix
        output = [0 if v in xset else o[v] for v in range(ninputs)]
    elif isinstance(s, (list, set)):
        # Exceptions: 1 to keep inputs in s unsorted
        output = [1 if v in s else 0 for v in range(ninputs)]
    else:
        # Fixed number of exceptions (unsorted inputs)
        output = o
        if s == 1:
            c_size = [Or(*output)]
            c_size += [
                ~output[i] | ~output[j] for i in range(ninputs)
                for j in range(i + 1, ninputs)
            ]
        elif s > 1:
            card, c_size = Card(output, s + 1)
            c_size += [~card[s]]
        c += c_size
    d = kl - kf
    # Backward layer iteration
    if d == 1:
        for v in range(ninputs):
            c += backward_size(g, n, kf, v, input, output)
    else:
        s = exprvars('s', d - 1, ninputs)
        for v in range(ninputs):
            c += backward_size(g, n, kl - 1, v, input, s[0])
        for k in range(1, d - 1):
            for v in range(ninputs):
                c += backward_size(g, n, kl - k - 1, v, s[k - 1], s[k])
        for v in range(ninputs):
            c += backward_size(g, n, kl - d, v, s[d - 2], output)
    return c
示例#15
0
def sorts_backward_depth(g, n, kf, kl, xlist=None, s=0):
    ninputs = 1 << n
    if xlist is None:
        xlist = range(ninputs)
    xset = set(xlist)
    c = []
    # FALSE for each input that is not sorted
    input = [TRUE if v != vsort(v) else FALSE for v in range(ninputs)]
    # all sorted
    o = exprvars('o', ninputs)
    if s == 0:
        output = [FALSE if v in xset else o[v] for v in range(ninputs)]
    elif isinstance(s, (list, set)):
        output = [TRUE if v in s else FALSE for v in range(ninputs)]
    else:
        output = o
        if s == 1:
            c_size = [Or(*output)]
            c_size += [
                ~output[i] | ~output[j] for i in range(ninputs)
                for j in range(i + 1, ninputs)
            ]
        elif s > 1:
            card, c_size = Card(output, s + 1, prefix='o_')
            c_size += [~card[s]]
        c += c_size
    d = kl - kf
    aux = exprvars('ly', d, n - 2, ninputs) if n > 2 else [None]
    if d == 1:
        c += backward_depth(g, n, kf, input, output, aux[0])
    else:
        s = exprvars('s', d - 1, ninputs)
        c += backward_depth(g, n, kl - 1, input, s[0], aux[0])
        for k in range(1, d - 1):
            c += backward_depth(g, n, kl - k - 1, s[k - 1], s[k], aux[k])
        c += backward_depth(g, n, kl - d, s[d - 2], output, aux[d - 1])
    return c
示例#16
0
def all_adjacent(g, n, d):
    c = [Or(*[g[k, i, i + 1] for k in range(d)]) for i in range(n - 1)]
    return c
示例#17
0
def comp(x1, x2, y1, y2):
    return [Or(~x1, ~x2, y2), ~x1 | y1, ~x2 | y1]
示例#18
0
def oneUp(g, k, i, j):
    c = [g[k, i, l] for l in range(i + 1, j)]
    return Or(*c)
示例#19
0
    def test_translate_f(self):
        f = (Or(And(self.ex_puzzle.X[0,2,2], self.ex_puzzle.X[2,0,1]),
        And(self.ex_puzzle.X[0,2,1], self.ex_puzzle.X[2,0,0])))
        f_str = 'Or(And(Starbuck_3, Batman_2), And(Starbuck_2, Batman_1))'

        self.assertEqual(self.ex_puzzle.translate_f(f), f_str)
示例#20
0
def used(g, first, last, k, i):
    c = [g[k, i, j]
         for j in range(i + 1, last)] + [g[k, j, i] for j in range(first, i)]
    return Or(*c)
示例#21
0
def oneDown(g, k, i, j):
    c = [g[k, l, j] for l in range(i, j)]
    return Or(*c)
示例#22
0
 def _to_pyeda_expr(self, val_to_sym: MutableMapping[T, str]) -> Expression:
     return Or(*(expr._to_pyeda_expr(val_to_sym) for expr in self.exprs))
示例#23
0
def search(n, d, s, u=0, epsilon=1/4, opt='d', solver='picosat', lprefix=None, wsize=0, task=None, nthreads=4):

    if wsize <= 0:
        wsize = n + wsize

    print("n:", n, "d:", d, "s:", s, "u:", u, "opt:", opt, "solver:", solver,
          "wsize:", wsize, "task:", task, "prefix:", lprefix, "nthreads:", nthreads, file=sys.stderr)

    if opt.startswith('h'):
        # Comparator variables
        g = variables(n, d)
        
        # Empty prefix
        c_prefix = []

        # valid constraints
        c_valid = valid_depth1(g, n, d)

        # size constraints
        if s:
            ncard = s
            gcard = [g[k, i, j] for i in range(n) for j in range(i+1, n) for k in range(d)]
            c, c_size = Card(gcard, ncard + 1, prefix='g_')
            if len(c) > ncard:
                c_size += [~c[ncard]]
        else:
            c_size = []

        c_sorts = halver(g, n, 0, d, epsilon)

    elif opt.startswith('e'):
        m = n//2
        g = exprvars('g', d*m, m)
        c_valid = valid_ehalver(g, n, d)
        c_prefix = [g[i, m+i] for i in range(m)]
        d0 = 1
        c_size = []
        net = Network(to_ehalver(c_prefix, g, n, d0))
        xlist = net.outputs(n, range(1<<n))
        c_sorts = halver(g, n, d0, d, epsilon, xlist)

    elif opt.startswith('s1'):
        d = s
        g = variables(n, d)
        c_prefix = []
        c_valid = valid_size1(g, n, d)
        c_size = []
        c_sorts = sorts_backward_size(g, n, 0, d, [], u)

    elif opt.startswith('s'):
        d = s
        g = variables(n, d)

        if lprefix is None:
            lprefix  = [[(0, 1)]]
            c_prefix = [g[k, i, j] if (i, j) in layer else ~g[k, i, j] for k, layer in enumerate(lprefix) for i in range(n-1) for j in range(i+1, n)]
            if n > 3:
                c_prefix.append(Or(g[1, 0, 2], g[1, 2, 3]))
        else:
            c_prefix = [g[k, i, j] if (i, j) in layer else ~g[k, i, j] for k, layer in enumerate(lprefix) for i in range(n-1) for j in range(i+1, n)]
        net = Network(lprefix)
        d0 = len(net)

        c_valid = valid_size(g, n, d0, d)

        c_size = []

        inputs = net.not_sorted(n)
        inputs = [x for x in inputs if window_size(x, n) > 2 and window_size(x, n) <= wsize]
        xlist = net.outputs(n, inputs)

        print("d0:", d0, "len(xlist):", len(xlist), file=sys.stderr)
        c_sorts = sorts(g, n, d0, d, xlist)

    elif opt.startswith('d1'):
        g = variables(n, d)

        c_valid = valid_depth1(g, n, d)

        c_prefix = []

        if s:
            c, c_size = Card([g[k, i, j] for i in range(0, n) for j in range(i+1, n) for k in range(d)], s+1, prefix='g_')
            c_size += [~c[s]]
        else:
            c_size = []

        c_sorts = sorts_backward_depth(g, n, 0, d, None, u)

    else:
        # Comparator variables
        g = variables(n, d)

        # Prefix constraints
        if lprefix is None:
            lprefix  = [[(i, n-i-1) for i in range(n//2)]]
        sprefix = sum(len(layer) for layer in lprefix)
        c_prefix = [g[k, i, j] if (i, j) in layer else ~g[k, i, j] for k, layer in enumerate(lprefix) for i in range(n-1) for j in range(i+1, n)]
        net = Network(lprefix)
        d0 = len(net)

        # valid constraints
        c_valid = valid_depth(g, n, d0, d, s)

        # size constraints
        if s:
            ncard = s - sprefix
            gcard = [g[k, i, j] for i in range(n) for j in range(i+1, n) for k in range(d0, d)]
            c, c_size = Card(gcard, ncard + 1, prefix='g_')
            if len(c) > ncard:
                c_size += [~c[ncard]]
        else:
            c_size = []

        inputs = net.not_sorted(n)
        inputs = [x for x in inputs if window_size(x, n) > 2 and window_size(x, n) <= wsize]
        xlist = net.outputs(n, inputs)
        print("d0:", d0, "len(xlist):", len(xlist), file=sys.stderr)
        c_sorts = sorts(g, n, d0, d, xlist)

    print("c_valid:  ", len(c_valid), elapsed_time(), file=sys.stderr)
    print("c_prefix: ", len(c_prefix), elapsed_time(), file=sys.stderr)
    print("c_size:   ", len(c_size),  elapsed_time(), file=sys.stderr)
    print("c_sorts:  ", len(c_sorts), elapsed_time(), file=sys.stderr)
    clauses = c_valid + c_prefix + c_sorts + c_size
    constraint = And(*clauses)
    print("Is cnf?", constraint.is_cnf(), "Size: ", len(clauses), elapsed_time(), file=sys.stderr)

    while True:
        if solver == "picosat":
            point = constraint.satisfy_one()
            res = point is not None
        else:
            litmap, cnf = expr2dimacscnf(constraint)
            task = task if task is not None else int(time.monotonic())
            dimacscnf = "dimacscnf_{}.txt".format(task)
            litmapcnf = "litmap_{}.txt".format(task)
            with open(dimacscnf, "wt") as fp:
                print(cnf, file=fp)
            with open(litmapcnf, "wt") as fp:
                print(litmap, file=fp)
            ofile = "output_{}_{}_{}_{}.txt".format(n, d, s, task)
            with open(ofile+".log", "wt") as out:
                if solver == "minisat":
                    subprocess.call(["minisat", dimacscnf, ofile], stdout=out)
                elif solver == "glucose":
                    subprocess.call(["../../glucose-syrup-4.1/simp/glucose_release", "-model", dimacscnf], stdout=out)
                elif solver == "glucose-syrup":
                    subprocess.call(["../../glucose-syrup-4.1/parallel/glucose-syrup_release", "-nthreads={}".format(nthreads), "-model", dimacscnf, ofile], stdout=out)
                else:
                    subprocess.call(["../../cryptominisat-5.0.1/cryptominisat5", "-t", str(nthreads), dimacscnf], stdout=out)
            if solver == "minisat":
                res, soln = dimacs.read(ofile, minisat=True)
            else:
                res, soln = dimacs.read(ofile+".log")
            point = ConjNormalForm.soln2point(soln, litmap)

        print("len(point): ", len(point) if point else None, elapsed_time(), file=sys.stderr)

        if res is None:
            return 'UNDETERMINED'
        elif not res:
            return 'UNSATISFIABLE'
        else:
            if opt.startswith('h'):
                net = Halver(to_network(point, g, n, d))
                return net
            elif opt.startswith('e'):
                net = Halver(to_ehalver(point, g, n, d))
                return net
            else:
                net = to_network(point, g, n, d)
                xnew = net.not_sorted(n, log=False)
            
                if len(xnew) == u or opt not in ['d', 's']:
                    return net
                else:
                    m = 16
                    print("Unsorted:", len(xnew), file=sys.stderr)
                    new_clauses = sorts(g, n, d0, d, xnew[:m])
                    clauses += new_clauses
                    constraint = And(*clauses)