DAGを新しいDAGに縮小する最小サイズ


15

DAGがあります。ノード関数がありますF:VN(大まかに言うと、ノードに番号を付けます)。これらのルールを使用して、新しい有向グラフを作成します。

  1. F(x)F(y)xyxyF(x)F(y)
  2. :私たちは、新しいノード間のすべての古いエッジ追加。(x,y)Exy(x,y)E
  3. この新しいグラフはまだDAGです。

最小値は何ですか?最小限の新しいグラフを作成するアルゴリズムとは何ですか?|V|


1
したがって、決定の問題は次のように思われます:頂点色のDAGと整数与えられたk場合、同じ色の頂点を縮小することによって形成された最大k個の頂点を持つDAGがあるかどうかを決定します。
アンドラスサラモン

1
接続された2つのノードを縮小すると、禁止された自己ループが発生しますか?
ユヴァルフィルマス

1
いや。もう一度読みます。収縮後の2つのノードがまだ異なる場合にのみエッジを追加します。2つのノードが1つに縮小された場合、エッジは追加されません。
chx

1
@chxあなたは「最小」または「最小」を求めていますか?
リアルツスロー

1
あなたは、いくつかの動機/ BKGを与えることができますか?
vzn

回答:


5

この問題を解決する1つの方法は、整数線形計画法(ILP)を使用することです。レッツは、問題の決定版に取り組む:与えられた、サイズのDAGを取得する契約同色の頂点への道がありkはkk

これは、標準的な手法を使用してILPインスタンスとして表現できます。元のグラフの各頂点の色が与えられています。私たちは、ラベルと各頂点にラベルを付けることを示唆している。同じラベルと同じ色のすべての頂点が縮小されます。したがって、決定の問題は次のようになります。同じ色の同じラベルのすべての頂点を縮小するとDAGが生成されるようなラベル付けが存在するのでしょうか。{1,2,,k}

整数線形プログラムとしてこれを表現するために、整数変数導入各頂点のためのVの頂点のラベル表現するために、Vを。不平等追加1 Vkはvvv1vk

次のステップは、縮約されたグラフがDAGでなければならないという要件を表現することです。上記の形式のラベルがあり、一般性を失うことなく、ラベルが縮約グラフでトポロジカルソートを引き起こすようなラベルが存在することに注意してください(つまり、縮約グラフでwの前にある場合、vのラベルwのラベルよりも小さい)。したがって、元のグラフの各エッジv wに対して、vwのラベルと色が同じであるか、vのラベルがwのラベルより小さいという制約を追加します。具体的には、各エッジvvwvwvwvwvw初期グラフで V Wと同じ色を有するが、不等式追加 ℓのVℓをwは。各エッジ用の V Wここで、V Wを有する異なる色は、不等式追加 ℓのV < Wはvwv,wvwvwv,wv<w

次に、この整数線形プログラムに実行可能な解決策があるかどうかを確認します。(すなわち、すべて同じ色、同じラベルの頂点を契約すると、DAGを生成する)標識が所望の形態である場合にのみ実行可能な解決策があるでしょう。サイズのDAGに元のグラフを縮小する方法がある場合にのみ換言すれば、実現可能な解が存在するであろう。任意の整数線形計画法ソルバーを使用できます。ILPソルバ私たちに答えを与えるならば、我々は、元の決定問題への答えを持っています。k

もちろん、これは多項式時間で完了するとは限りません。保証はありません。ただし、ILPソルバーはかなり良くなっています。妥当なサイズのグラフでは、ILPソルバーが妥当な時間でこの問題を解決できる可能性が十分にあると期待しています。

これをSATインスタンスとしてエンコードし、SATソルバーを使用することもできます。それがより効果的かどうかはわかりません。ただし、ILPバージョンはおそらく考えやすいでしょう。

(これが正しいことを願っています。詳細を注意深く確認していないので、理由を再確認してください。


更新(10/21):この形式のILPは、トポロジ的にソートされた順序でDAGを処理し、各頂点のラベルの下限を追跡することにより、線形時間で解決できるようです。これは私の解決策に疑念を抱かせます:どこかで間違いを犯しましたか?


詳細な回答をありがとう!私は制限を取得し、彼らは合理的に見えます。ただし、ILPに精通していませんが、整数線形計画法では最大化(または最小化)する必要のある関数が必要だと思いました。私はウィキペディアでのみ反論したので、間違っているかもしれません。
chx

@ chx、ILPを使用して制約の実行可能性をテストしています。これは、ILPソルバーに任意の目的関数を最大化する(たとえば、0を最大化する)ように依頼し、目的関数の値を無視して、ILPが実行可能かどうかを確認するだけで実行できます。応答ソルバーILP(そこ大きさのない契約DAGませんを意味し、「実行不可能」のどちらかまたはそれが「実行可能」応答し、それは見つけることができる目的関数の最高値を提供します)。その場合、あなたは、目的関数の値を無視する(そして、あなたはサイズのDAGが存在しないことを知っているkは)。kk
DW

たとえば、engineering.purdue.edu /
DW

線形時間ソリューションについて; 私はあなたのILP定式化を消化していないので、それを判断することはできませんが、問題がNP困難であることを証明できると確信しています。これは線形時間解を非常に便利にします:P。すぐに投稿します。
Realzなスロー

@RealzSlaw、ありがとう!その場合、どこかで間違いを犯したのではないかと強く疑います(ただし、まだどこにいるのかわかりません)。
DW

5

注:AFAICT、DWはこの削減に穴を見つけましたが、これは間違っています(コメントを参照)。歴史的な理由でここに保管してください。

イントロ:最初の私は減少しますモノトーン3SATの我々の問題に問題が。けれどもモノトーン3SATの問題は自明充足、私たちの問題はさらに解決することができる最小の真のモノトーン3SATの NP困難であるという問題を、。したがって、この問題はNPハードです。

Monotone 3SATから問題への削減

一連の変数と一連の句として表現される単調なブール式があります。CNFは、次のような形式です。Φ=(V,C)

(ciC) ci=(xjxkxl)||(xj,xk,xlV)

i=1nci|ciC,n=|C|.

変換

G=V,EG

xiVxi

enter image description here

これらのノードは、同じラベルを持っているため、もちろん縮小できます。契約されている変数/ノードはfalseと評価され、契約されていないものはtrueと評価されると見なします

enter image description here

V2|V|ciC, ci=(xjxkxl)|xj,xk,xlVci

enter image description here

ci1 node labeled ci. (click image for full view)

After this step, we should have 2|V|+|C| nodes.

Now, if xi, xj and xk get contracted, cici will result in a cycle.

Here is another visualization, unrolling the clause constraint:

enter image description here

Thus, each clause constraint requires that at least one of the variables it contains remain uncontracted; since the uncontracted nodes are valued as true, this requires that one of the variables be true; exactly what Monotone SAT requires for its clauses.

Reduction from Minimum True Monotone 3SAT

Monotone 3SAT is trivially satisfiable; you can simply set all the variables to true.

However, since our DAG minimization problem is to find the most contractions, this translates to finding the satisfying assignment that produces the most false variables in our CNF; which is the same as finding the minimum true variables. This problem is sometimes called Minimum True Monotone 3SAT or here (as an optimization problem, or decision problem), or k-True Monotone 2SAT (as a weaker decision problem); both NP-hard problems. Thus our problem is NP-hard.


References:

Graph sources:


1
wow. then D.W.'s solution must be wrong (or we have proven NP=P which I somewhat at least doubt :P ) -- but where?
chx

I think there's something wrong with this reduction. Consider (x1x2x6)(x1x4x5)(x3x4x6). Your reduction rules out the assignment x1=x4=x6=False x2=x3=x5=True, as that would create a cycle c1x1x4x6c1. However, that assignment should not be ruled out, as it satisfies the formula (it doesn't violate any of the clauses). More fundamentally, the answer lacks a proof that solutions to the DAG problem map one-to-one to satisfying assignments to the 3SAT formula.
D.W.

@D.W. Also nice to talk to you again :D, and good luck, if we are both right we might have P=NP in your answer! /jk
Realz Slaw

@D.W. unless I am misunderstanding something, your formula has to be converted into the Minimum True Monotone 3SAT problem I linked, or one of the equivalent ones, before you can apply my own reduction. A solution to my own would then have to be converted back to 3SAT. Therefore, I don't think you can just point out a formula that would fail in my own; it needs to be reduced first, then you can talk about "ruling out assignment[s]". (incidentally a minimally true solution for your formula is probably (x1,x3) )
Realz Slaw

@RealzSlaw, I'm afraid I don't follow yet... I don't see any reason why my formula would have to be converted. I believe it already is an instance of Minimum True Monotone 3SAT. But let me take it up a level. More broadly, I see a proposed reduction, but I don't see any argument that the reduction is correct -- that's missing. For the reduction to be correct, it has to map YES instances to YES instances, and NO instances, to NO instances. I suspect that if you try to write out a proof of correctness for your reduction, you will run into a problem when you consider the formula I gave.
D.W.

1

With each replacement (except for direct-parent-child replacements), you add new ancestor-descendant relationships that make it non-trivial to determine which one is actually worth it in the long-term. Therefore, a simple greedy algorithm will fail in the general case. However, if you do a brute-force approach, you can determine the smallest graph:

Python-ish (not tested):

def play((V,E),F,sequence=[]):
  """
  (V,E) -- a dag.
  V     -- a set of vertices.
  E     -- a set of directed-edge-tuples.
  F     -- a function that takes a vertex, returns an integer.
  sequence -- the sequence of moved taken so far; starts with/defaults to
              an empty list, will contain tuples of the form (x,y)
              where x is removed and replaced with y.

  Returns the best recursively found solution.
  """

  #find all the integer values in the graph, remember which
  # values correspond to what vertices. Of the form {integer => {vertices}}.
  n2v = {}
  for x in V:
    n = F(x)

    #for each integer, make sure you have a set to put the vertices in.
    if n not in n2v:
      n2v[n] = set()

    #for each integer, add the vertex to the equivalent set.
    n2v[n].add(v)

  #record the best sequence/solution. You start with the current sequence,
  # and see if you can obtain anything better.
  best_solution = list(sequence)

  #Now you will try to combine a single pair of vertices, obtain a new
  # graph and then recursively play the game again from that graph. 

  #for each integer and equivalent set of vertices,
  for n,vset in n2v.iteritems():

    #pick a pair of vertices
    for x in vset:
      for y in vset:

        #no point if they are the same.
        if x == y:
          continue

        #If there is a path from x => y or y => x, then you will be
        # introducing a cycle, breaking a rule. So in that case, disregard
        # this pair.
        #However, the exception is when one is a direct child of the other;
        # in that case you can safely combine the vertices.
        if pathtest((V,E),x,y) and (x,y) not in E and (x,y) not in E:
          continue

        #combine the vertices (function is defined below), discard x,
        # replace it with y, obtain the new graph, (V',E').
        Vp,Ep = combine_vertex((V,E),x,y))

        #record the sequence for this move.
        sequencep = list(sequence) + [(x,y)]

        #recurse and play the game from this new graph.
        solution = play(Vp,Ep,F,sequencep)

        #if the returned solution is better than the current best,
        if len(solution) > len(best_solution):
          #record the new best solution
          best_solution = solution
  #return the best recorded solution
  return best_solution


def combine_vertex((V0,E0),x,y):
  """
  (V0,E0)   -- an initial digraph.
  V0        -- a set of vertices.
  E0        -- a set of directed-edge-tuples.
  x         -- vertex to discard.
  y         -- vertex to replace it with.

  returns a new digraph replacing all relationships to and from x to relate
   to y instead, and removing x from the graph entirely.
  """

  #the final vertex set will have everything except x
  V = set(V0)
  V.discard(x)

  #now you construct the edge set.
  E = set()

  #for every edge,
  for (u0,v0) in E0:
    #recreate the edge in the new graph, but replace any occurence
    # of x.  
    u,v = u0,v0
    #if x is in the edge: replace it
    if u == x:
      u = y
    if v == x:
      v == y

    #sometimes u=v=y and can now be pointing to itself, don't add that
    # edge
    if u == v:
      continue

    #add the new/replaced edge into the edge-set.
    E.add( (u,v) )
  return (V,E)

I am not sure if it really a hard problem, but playing with some graphs manually, it seems very combinatorial. I am curious if something difficult can be reduced to this problem, or if there is an algorithm with better running time.


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