三角形を失うことなく三角形配列からポイントを削除する


17

私が持っている組合せ論の問題、私は上に置くしたいというOEISを -the問題は、私は十分な条件を持っていないということです。このコードの課題は、より多くの用語を計算できるようにすることです。勝者は、最も多くの用語を含む提出物を持つユーザーになります。


問題

辺の長さがn三角形の電球の配列を与えたとしましょう:

     o
    o o
   o o o
  o o o o
 o o o o o
o o o o o o
1 2  ...  n

次の例のように、「直立した」正三角形を形成する3つの電球をオンにします。

     o
    o x
   o o o
  o o o o
 o x o o x
o o o o o o

照明をオンにする前に、あなたの仕事は、オンになっている電球の三角形を推測する能力を失うことなく、できるだけ多くの電球をアレイから削除することです。明確にするために、電球が取り外されている場合、その位置がオンになったときに電球は点灯しません。

たとえば、次の電球(でマークされている.)を取り外した場合、次の2つのライトのみが点灯(でマークされているx)し、3番目(消灯)の位置を一意に推測できます。

     .              .
    . o            . x
   . . o          . . o
  o o o .   =>   o o o .
 o o o o .      o x o o . <- the third unlit position
o . . . o o    o . . . o o

ましょうa(n)あいまいさを導入せずに削除できる電球の最大数です。


以下に示すように、単純なアルゴリズムを使用して、辺の長さが7の三角形までの値をチェックしました。

                                                                      .
                                                      .              . o
                                        .            . o            o . o
                           .           . .          . . o          . o o .
              .           . .         . o o        o o o .        o o . o .
 .           . .         . o o       o o . o      o o o o .      o . o . o o
. .         . o o       . o o o     o . . o o    o . . . o o    o . o . o o o

a(2) = 3    a(3) = 4    a(4) = 5    a(5) = 7     a(6) = 9       a(7) = 11

得点

[a(2), a(3), ..., a(n)]最大n個のシーケンスを計算するサブミッションが勝ちです。2つの提出物のシーケンスが同一である場合、以前に投稿されたものが優先されます。

提出には必要ではありませんが、上記の例のように、結果の三角形配列の構築を投稿すると有益です。


1
これは最速のコードではなく、コードチャレンジではありませんか?
ドンサウザンド

6
時間制限(60秒など)を選択する必要があると思います。そのため、コンテストは、コードの実行に費やされた時間に関するものではありません。
ディルナン

いい問題だ。「直立」三角形とはどういう意味ですか?
ダミアン

回答:


10

Python 3n=8

import itertools
from ortools.sat.python import cp_model


def solve(n):
    model = cp_model.CpModel()
    solver = cp_model.CpSolver()
    cells = {
        (y, x): model.NewBoolVar(str((y, x)))
        for y in range(n) for x in range(y + 1)}
    triangles = [
            {cells[v] for v in ((y1, x1), (y2, x1), (y2, x1 + y2 - y1))}
            for (y1, x1) in cells.keys() for y2 in range(y1 + 1, n)]
    for t1, t2 in itertools.combinations(triangles, 2):
        model.AddBoolOr(t1.symmetric_difference(t2))
    model.Minimize(sum(cells.values()))
    solver.Solve(model)
    return len(cells) - round(solver.ObjectiveValue())


for n in itertools.count(2):
    print('a(%d) = %d' % (n, solve(n)))

Google OR-ToolsのCP-SATソルバーを使用します

〜30秒間実行した後、次を出力します。

a(2) = 3
a(3) = 4
a(4) = 5
a(5) = 7
a(6) = 9
a(7) = 11
a(8) = 13

n=9おそらく何時間もかかるので、待つことを試みませんでした(制約の数はように増加しますn6。30分未満の計算の後、私はそれを見つけましたa(9)=15n=8現時点では時間の制約が不明確ですが、30分はおそらく長すぎるため、スコアを残しています。

使い方

T1T2T1T2です。

したがって、質問は、三角形のペアごとに1つの制約があるSAT問題と言い換えることができます。

PS:の 例を含めたいとn=8思いますが、SATソルバーに問題があり、明らかにソリューションをすべて維持したいと思っています。



2

@ Delfad0rのプログラムからソリューションを取得する

@ Delfad0rのプログラムを出力ソリューションに拡張しました。また、中間結果が得られるため、次のような出力が得られます。

Solving n = 8:
a(8) >= 9
a(8) >= 10
a(8) >= 11
a(8) >= 12
a(8) >= 13
       o
      . o
     . o o
    . o o .
   o o . o o
  o o o o . .
 o . . o o o .
o . . o . o o o
a(8) = 13

Solving n = 9:
a(9) >= 10
a(9) >= 13
a(9) >= 14
a(9) >= 15
        o
       o o
      o . .
     o . o o
    . o . o o
   . o o o o o
  o o o . o . .
 o o o . . . o o
. o o o o o o . .
a(9) = 15

この計算には数時間かかりました。

Ctrl-C最適化されていない可能性のある解決策が見つかった後、イライラして押した場合、プログラムはその解決策を示します。したがって、これを取得するのに時間がかかりません:

                   .
                  o o
                 . o o
                . o o o
               o o . o o
              o . o o o .
             o . o . o o o
            . o o o o o . o
           o . . o o o o o o
          o o o o o o o o o .
         o o . o o o o . o o o
        o o o o o o . o . o o o
       o . o o . o o o o o o o o
      o o o . o o o o o . o o o o
     o o o . o o o o o o o o . . o
    o o o o o o o o o o o . o . . o
   o o o o . o o o o . o o o o o . o
  o o o o o o o o . o o . . o o o o .
 o o o o . o o . o . o o o o o o . o o
o o . o o . o o o o . o o o . o o o o o
a(20) >= 42

拡張プログラムは次のとおりです。

import itertools
from ortools.sat.python import cp_model

class ReportPrinter(cp_model.CpSolverSolutionCallback):

    def __init__(self, n, total):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.__n = n
        self.__total = total

    def on_solution_callback(self):
        print('a(%d) >= %d' %
              (self.__n, self.__total-self.ObjectiveValue()) )

def solve(n):
    model = cp_model.CpModel()
    solver = cp_model.CpSolver()
    cells = {
        (y, x): model.NewBoolVar(str((y, x)))
        for y in range(n) for x in range(y + 1)}
    triangles = [
            {cells[v] for v in ((y1, x1), (y2, x1), (y2, x1 + y2 - y1))}
            for (y1, x1) in cells.keys() for y2 in range(y1 + 1, n)]
    for t1, t2 in itertools.combinations(triangles, 2):
        model.AddBoolOr(t1.symmetric_difference(t2))
    model.Minimize(sum(cells.values()))
    print('Solving n = %d:' % n)
    status = solver.SolveWithSolutionCallback(model, ReportPrinter(n,len(cells)))
    if status == cp_model.OPTIMAL:
        rel = '='
    elif status == cp_model.FEASIBLE:
        rel = '>='
    else:
        print('No result for a(%d)\n' % n)
        return
    for y in range(n):
        print(' '*(n-y-1), end='')
        for x in range(y+1):
            print('.o'[solver.Value(cells[(y,x)])],end=' ')
        print()
    print('a(%d) %s %d' % (n, rel, len(cells) - solver.ObjectiveValue()))
    print()

for n in itertools.count(2):
    solve(n)

1

Python 3

Delfad0rの答えに強く基づいて、三角形のペアをチェックし、この検証に失敗した三角形のペアが含まれていない場合は構成を検証することにより、ほとんど同じロジック進行に従います。私はitertoolsとcopy以外のライブラリを使用しなかったため、プログラム全体で遭遇する例を保存することを完全に制御できます。

examples = dict() # stores examples by key pair of n to a tuple with the triangle and number of lights turned off

for n in range(3, 8):
    tri = [] # model of the triangle, to be filled with booleans representing lights
    tri_points = [] # list of tuples representing points of the triangle
    for i in range(n):
        tri.append([True]*(i + 1))
        for j in range(i+1):
            tri_points.append((i, j))

    t_set = [] # list of all possible triangles from tri, represented by lists of points
    for i in range(n):
        for j in range(len(tri[i])):
            for k in range(1, n - i):
                t_set.append([(i, j), (i + k, j), (i + k, j + k)])

    from itertools import combinations
    import copy

    # validates whether or not a triangle of n lights can have i lights turned off, and saves an example to examples if validated
    def tri_validate(x):
        candidate_list = list(combinations(tri_points, x))
        tri_pairs = list(combinations(t_set, 2))
        for candidate in candidate_list:
            temp_tri = copy.deepcopy(tri)
            valid = False
            for point in candidate:
                (row, col) = point
                temp_tri[row][col] = False
            for pair in tri_pairs:
                valid = False
                (tri1, tri2) = pair
                for point in tri1:
                    if not valid:
                        if point not in tri2:
                            (row, col) = point
                            if temp_tri[row][col]:
                                valid = True
                for point in tri2:
                    if not valid:
                        if point not in tri1:
                            (row, col) = point
                            if temp_tri[row][col]:
                                valid = True
                if not valid:
                    break
            if valid:
                examples[n] = (temp_tri, x)
                return True
        return False

    # iterates up to the point that validation fails, then moves on to the next n
    for i in range(len(tri_points)):
        if tri_validate(i + 1):
            continue
        break

問題は、あまり効率的ではないということです。それは本当に高速で実行されますがn=5、その時点を過ぎるとかなり遅くなり始めます。でn=6、実行に約1分かかり、ではるかに遅くなりますn=7。このプログラムで行える効率の修正はたくさんあると思いますが、すぐに作成された優れたソリューションのラフドラフトであり、このメソッドの内部動作をチェックする柔軟性がはるかに高くなっています。私はこれから少しずつ作業していきます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.