2012-01-11 20 views
3

のは、私はこのようになります関係の集合を持っているとしましょう:複雑なマージ

relations :: [(A, B)] 
instance Monoid A 
instance Monoid B 

私はA Sの関係とB Sの新しいセットに関係のこのセットを変換したいです。そのBmappend編を持っている必要があり等しい

  1. A S:

    は今、ここにトリッキーなものをしています。

  2. Bは、A s mappend edである必要があります。
  3. ABが別々のものになるまで繰り返す(そうでない場合は、何らかの理由でこれをやり直すことができるかどうかによって異なります)。

EDIT:注文の制約により問題は些細なものになっていたので、削除しました。

Ord,Hashableなど、必要なものはすべて利用可能です。すべての意図や目的のために、一つはAを振る舞う正確HashSetB等が正確Vector(または合理的なサイズのチェックといくつかの他のタイプ)などが動作することを言うことができます。

これは、など

この変換が起こる方法の例

[(<1>, [a]), (<4>, [d]), (<2>, [b]), (<5>, [e]), (<1>, [b]), (<2>, [a]), (<3>, [c])] 
-- Merge `A`s for equal `B`s 
[(<1,2>, [a]), (<4>, [d]), (<1,2> [b]), (<5>, [e]), (<3>, [c])] 
-- Merge `B`s for equal `A`s 
[(<1,2>, [a, b]), (<4>, [d]), (<5>, [e]), (<3>, [c])] 
-- All values are distinct, so we're done. 

これを行うことができますどのように(<a, b>Set.fromList [a, b]であることをふり)1は、そのlet s = size (mappend a b); s >= size a; s >= size b、そのa, b :: B; mappend a b /= mappend b a <=> a, b not mempty; a > b => (mappend a c) > bを、想定することができることを意味しできるだけ効率的な方法で(時間、空間)?

+0

「B」は、等価チェックを実行すると、かなりの順序でセットされたものとして扱われますが、正しいですか?私の特定の状況のた​​めには(すべての 'B 'は追加されたときにソートされるので)、この質問は有益であるためには、[[1,2]/= [2,1]' – jberryman

+0

@jberryman他には、 'インスタンスイクB'があると言って、それをそのまま残しておくといいかもしれません。 – dflemstr

+2

プロシージャの順序(1.)と(2.)は重要です。これらの規則を適用する順序が異なると、異なる結果につながります。それはどのように動作するはずですか? (1.)、次に(2.)、(1.)、(2.)のいずれのルールも適用されなくなるまで、すぐには適用できません。 –

答えて

2

一般的なケースは、O(n^2)マージで簡単な方法よりも優れているとは思えないので、合計アルゴリズムはO(n^3)になる可能性があります。リスト内の要素の順序と結果がmappendでなければ、各要素のペアをマージするかどうかを確認し、完了するまで繰り返す必要があります。

merge :: Eq e => (a -> a -> a) -> (a -> e) -> [a] -> (Bool,[a]) 
merge combine eqval [] = (False, []) 
merge combine eqval (x:xs) = (not (null a) || t, y : zs) 
    where 
    e = eqval x 
    (a,b) = partition ((e ==) . eqval) xs 
    y = mconcat (x:a) 
    (t,zs) = merge combine eqval b 

mergeRelations :: [(A,B)] -> [(A,B)] 
mergeRelations = go False 
    where 
    mergeFsts = merge (\(a1,b1) (a2,b2) -> (a1, b1 `mappend` b2)) fst 
    mergeSnds = merge (\(a1,b1) (a2,b2) -> (a1 `mappend` a2, b1)) snd 
    go started xs 
     | started && not f = xs 
     | s = go True n 
     | otherwise = m 
     where 
      (f,m) = mergeFsts xs 
      (s,n) = mergeSnds m 
+0

注文制約が削除された場合、これはどのように変更されますか?関係が順序付けされていないことを意味し、 'a/= b'のときには' a/b/= mappend b a 'になる。 'Ord'、' Hashable'などはもちろん利用可能です。 – dflemstr

+0

ミスコミュニケーション、私は恐れています。私は、「A」は常にソートされていて、「mappend」は順序に関してはうまく動作するというようないくつかの制限があることを意味しました。そこに_might_良い方法がある、そうでなければ、私はほとんどないと確信しています。 –

+0

私は注文の制約を取り除き、問題をより軽くするためにいくつかの詳細を追加しましたが、より良いアルゴリズムに対応しています。詳細は質問を参照してください。 – dflemstr