2-স্যাট সমাধান করুন (বুলিয়ান সন্তুষ্টিযোগ্যতা)


16

সাধারণ স্যাট (বুলিয়ান সন্তুষ্টিযোগ্যতা) সমস্যাটি এনপি-সম্পূর্ণ। তবে 2-স্যাট , যেখানে প্রতিটি অনুচ্ছেদে কেবল 2 ভেরিয়েবল রয়েছে, পি তে রয়েছে । 2-স্যাট জন্য একটি solver লিখুন।

ইনপুট:

নিম্নলিখিত হিসাবে সিএনএফএনকোডড একটি 2-স্যাট উদাহরণ । প্রথম লাইনে ভি, বুলিয়ান ভেরিয়েবলের সংখ্যা এবং এন, ধারাগুলির সংখ্যা রয়েছে। তারপরে এন লাইনগুলি অনুসরণ করে, প্রত্যেকটি 2 টি ননজারো পূর্ণসংখ্যা সহ একটি অনুচ্ছেদের আক্ষরিক প্রতিনিধিত্ব করে। ধনাত্মক পূর্ণসংখ্যা প্রদত্ত বুলিয়ান ভেরিয়েবলকে উপস্থাপন করে এবং negativeণাত্মক পূর্ণসংখ্যাগুলি ভেরিয়েবলের অবহেলা উপস্থাপন করে।

উদাহরণ 1

ইনপুট

4 5
1 2
2 3
3 4
-1 -3
-2 -4

যা সূত্র এনকোড (এক্স 1 বা এক্স 2 ) এবং (X 2 বা এক্স 3 ) এবং (এক্স 3 বা এক্স 4 ) এবং (না এক্স 1 বা এক্স না 3 ) এবং (না এক্স 2 বা এক্স না 4 )

4 টি ভেরিয়েবলের একমাত্র সেটিংটি পুরো সূত্রটিকে সত্য করে তোলে x 1 = মিথ্যা, x 2 = সত্য, x 3 = সত্য, x 4 = মিথ্যা , সুতরাং আপনার প্রোগ্রামটি একক লাইন আউটপুট করা উচিত

আউটপুট

0 1 1 0

ভি ভেরিয়েবলের সত্য মানগুলি উপস্থাপন করে ( x 1 থেকে x ভি থেকে ক্রমানুসারে )। যদি একাধিক সমাধান থাকে তবে আপনি সেগুলিতে কোনও লম্বা সাবসেট আউটপুট দিতে পারেন, প্রতি লাইন। যদি কোনও সমাধান না হয় তবে আপনাকে অবশ্যই আউটপুট দিতে হবে UNSOLVABLE

উদাহরণ 2

ইনপুট

2 4
1 2
-1 2
-2 1
-1 -2

আউটপুট

UNSOLVABLE

উদাহরণ 3

ইনপুট

2 4
1 2
-1 2
2 -1
-1 -2

আউটপুট

0 1

উদাহরণ 4

ইনপুট

8 12
1 4
-2 5
3 7
2 -5
-8 -2
3 -1
4 -3
5 -4
-3 -7
6 7
1 7
-7 -1

আউটপুট

1 1 1 1 1 1 0 0
0 1 0 1 1 0 1 0
0 1 0 1 1 1 1 0

(বা এই 3 লাইনের কোনও অসাধারণ সাবসেট)

আপনার প্রোগ্রামটি অবশ্যই একটি উপযুক্ত সময়ে সমস্ত এন, ভি <100 পরিচালনা করবে। আপনার প্রোগ্রামটি কোনও বড় উদাহরণ হ্যান্ডেল করতে পারে তা নিশ্চিত করার জন্য এই উদাহরণটি ব্যবহার করে দেখুন । ক্ষুদ্রতম প্রোগ্রামের জয়।


আপনি উল্লেখ করেছেন যে 2-স্যাট পি-তে রয়েছে, তবে এটি নয় যে সমাধানটি বহুপাক্ষিক সময়ে চালানো দরকার ;-)
টিমভি

@ টিমভি: না, তবে এটি একটি যুক্তিসঙ্গত সময়ে ভি = 99 পরিচালনা করতে হবে ...
কেথ র্যান্ডাল

উত্তর:


4

হাস্কেল, 278 টি অক্ষর

(∈)=elem
r v[][]=[(>>=(++" ").show.fromEnum.(∈v))]
r v[]c@(a:b:_)=r(a:v)c[]++r(-a:v)c[]++[const"UNSOLVABLE"]
r v(a:b:c)d|a∈v||b∈v=r v c d|(-a)∈v=i b|(-b)∈v=i a|1<3=r v c(a:b:d)where i w|(-w)∈v=[]|1<3=r(w:v)(c++d)[]
t(n:_:c)=(r[][]c!!0)[1..n]++"\n"
main=interact$t.map read.words

নিষ্ঠুর শক্তি নয়। বহুপক্ষীয় সময়ে চলে। কঠিন সমস্যাটি (60 ভেরিয়েবল, 99 টি ধারা) দ্রুত সমাধান করে:

> time (runhaskell 1933-2Sat.hs < 1933-hard2sat.txt)
1 1 1 0 0 0 0 0 0 1 1 0 0 1 0 1 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 1 0 1 1 1 1 0 

real 0m0.593s
user 0m0.502s
sys  0m0.074s

এবং প্রকৃতপক্ষে, সেই সময়টির বেশিরভাগ সময়টি কোড সংকলনে ব্যয় করা হয়!

ফুল সোর্স ফাইল, পরীক্ষা ক্ষেত্রে এবং দ্রুত-চেক দিয়ে পরীক্ষা প্রাপ্তিসাধ্য

Ungolf'd:

-- | A variable or its negation
-- Note that applying unary negation (-) to a term inverts it.
type Term = Int

-- | A set of terms taken to be true.
-- Should only contain  a variable or its negation, never both.
type TruthAssignment = [Term]

-- | Special value indicating that no consistent truth assignment is possible.
unsolvable :: TruthAssignment
unsolvable = [0]

-- | Clauses are a list of terms, taken in pairs.
-- Each pair is a disjunction (or), the list as a whole the conjuction (and)
-- of the pairs.
type Clauses = [Term]

-- | Test to see if a term is in an assignment
(∈) :: Term -> TruthAssignment -> Bool
a∈v = a `elem` v;

-- | Satisfy a set of clauses, from a starting assignment.
-- Returns a non-exhaustive list of possible assignments, followed by
-- unsolvable. If unsolvable is first, there is no possible assignment.
satisfy :: TruthAssignment -> Clauses -> [TruthAssignment]
satisfy v c@(a:b:_) = reduce (a:v) c ++ reduce (-a:v) c ++ [unsolvable]
  -- pick a term from the first clause, either it or its negation must be true;
  -- if neither produces a viable result, then the clauses are unsolvable
satisfy v [] = [v]
  -- if there are no clauses, then the starting assignment is a solution!

-- | Reduce a set of clauses, given a starting assignment, then solve that
reduce :: TruthAssignment -> Clauses -> [TruthAssignment]
reduce v c = reduce' v c []
  where
    reduce' v (a:b:c) d
        | a∈v || b∈v = reduce' v c d
            -- if the clause is already satisfied, then just drop it
        | (-a)∈v = imply b
        | (-b)∈v = imply a
            -- if either term is not true, the other term must be true
        | otherwise = reduce' v c (a:b:d)
            -- this clause is still undetermined, save it for later
        where 
          imply w
            | (-w)∈v = []  -- if w is also false, there is no possible solution
            | otherwise = reduce (w:v) (c++d)
                -- otherwise, set w true, and reduce again
    reduce' v [] d = satisfy v d
        -- once all caluses have been reduced, satisfy the remaining

-- | Format a solution. Terms not assigned are choosen to be false
format :: Int -> TruthAssignment -> String
format n v
    | v == unsolvable = "UNSOLVABLE"
    | otherwise = unwords . map (bit.(∈v)) $ [1..n]
  where
    bit False = "0"
    bit True = "1"

main = interact $ run . map read . words 
  where
    run (n:_:c) = (format n $ head $ satisfy [] c) ++ "\n"
        -- first number of input is number of variables
        -- second number of input is number of claues, ignored
        -- remaining numbers are the clauses, taken two at a time

Golf'd সংস্করণে, satisfyএবং formatব্যক্তির মধ্যে সমন্বিত করা হয়েছে reduce, যদিও এড়ানোর পাসিং করার জন্য n, reduceভেরিয়েবল (একটি তালিকা থেকে একটি ফাংশন ফেরৎ [1..n]) স্ট্রিং ফলাফলের জন্য।


  • সম্পাদনা করুন: (330 -> 323) sএকটি অপারেটর তৈরি করেছে, নতুন লাইনের আরও ভাল পরিচালনা করা হয়েছে
  • সম্পাদনা করুন: (323 -> 313) ফলাফলের অলস তালিকার প্রথম উপাদানটি একটি কাস্টম শর্ট সার্কিট অপারেটরের চেয়ে ছোট; প্রধান সলভার ফাংশনটির নামকরণ হয়েছে 'কারণ আমি অপারেটর হিসাবে ব্যবহার করতে চাই !
  • সম্পাদনা করুন: (313 -> 296) ধারাগুলি একক তালিকা হিসাবে রাখুন, তালিকার তালিকা নয়; এটি একবারে দুটি উপাদান প্রক্রিয়া করুন
  • সম্পাদনা করুন: (296 -> 291) দুটি পারস্পরিক পুনরাবৃত্তি ফাংশন একত্রিত; এটি ইনলাইন করাতে সস্তা ছিল তাই এখন পরীক্ষার নামকরণ করা হয়েছে
  • সম্পাদনা করুন: (291 -> 278) ফলাফল উত্পন্ন করার জন্য ইনিল্যান্ড আউটপুট বিন্যাস ting

4

জে, 119 103

echo'UNSOLVABLE'"_`(#&c)@.(*@+/)(3 :'*./+./"1(*>:*}.i)=y{~"1 0<:|}.i')"1 c=:#:i.2^{.,i=:0&".;._2(1!:1)3

সম্পাদনা: এলিমিনেট করা হয়েছে (n#2)এবং এভাবে n=:কিছু র‌্যাঙ্ক প্যারেনস (ধন্যবাদ, আইস্যাড্রোনস) মুছে ফেলা হচ্ছে। স্পষ্ট-> সুস্পষ্ট এবং dyadic-> monadic, প্রতিটি আরও কয়েকটি অক্ষর মুছে ফেলা। }.}.to }.,

সম্পাদনা: ওফস। এটি বৃহত এন এর জন্য কেবল একটি সমাধান নয়, তবে i. 2^99x-> মূর্খতায় অপমান যুক্ত করতে "ডোমেন ত্রুটি"।

এখানে বর্ণহীন মূল সংস্করণ এবং সংক্ষিপ্ত বিবরণ দেওয়া হল।

input=:0&".;._2(1!:1)3
n =:{.{.input
clauses=:}.input
cases=:(n#2)#:i.2^n
results =: clauses ([:*./[:+./"1*@>:@*@[=<:@|@[{"(0,1)])"(_,1) cases
echo ('UNSOLVABLE'"_)`(#&cases) @.(*@+/) results
  • input=:0&".;._2(1!:1)3 প্রতিটি লাইনে নিউলাইনগুলিকে ইনপুট কেটে দেয় এবং ফলাফলগুলি ইনপুটে জমা করে।
  • n বরাদ্দ করা হয়েছে n, ক্লজ ম্যাট্রিক্সকে বরাদ্দ করা হয়েছে clauses(ক্লজ কাউন্টের প্রয়োজন নেই)
  • cases0..2 এন -1 হয় বাইনারি অঙ্কগুলিতে রূপান্তরিত (সমস্ত পরীক্ষার কেস)
  • (Long tacit function)"(_,1)casesসমস্ত সঙ্গে প্রতিটি ক্ষেত্রে প্রয়োগ করা হয় clauses
  • <:@|@[{"(0,1)] ধারাগুলির অপারেশনগুলির একটি ম্যাট্রিক্স পায় (অ্যাবস (বিকল্প নম্বর) - 1 গ্রহণ করে এবং কেস থেকে নির্ধারণ করে, যা একটি অ্যারে)
  • *@>:@*@[ সাইনামের অপব্যবহারের মাধ্যমে 'নট' বিটস (নোটের জন্য 0 নয়) এর ধারা-আকারের অ্যারে পায়।
  • = অপারেডগুলিতে বিটগুলি প্রয়োগ করে না।
  • [:*./[:+./"1+.ফলাফলের ম্যাট্রিক্সের সারিগুলিতে (এবং) প্রয়োগ করে এবং *.(বা) এর ফলাফল জুড়ে।
  • এই সমস্ত ফলাফল প্রতিটি ক্ষেত্রে 'উত্তর' বাইনারি অ্যারে হিসাবে শেষ হয়।
  • *@+/ ফলাফলের জন্য প্রয়োগ ফলাফল রয়েছে যদি একটি 0 দেয় এবং ফলাফল না থাকলে 1 দেয়।
  • ('UNSOLVABLE'"_) `(#&cases) @.(*@+/) results 0, যদি 'UNSOLVABLE' প্রদান করে ধ্রুবক ফাংশন চালায় এবং যদি 1 এর ক্ষেত্রে প্রতিটি 'সমাধান' উপাদানের একটি অনুলিপি দেয়।
  • echo যাদু-ফলাফল মুদ্রণ।

আপনি র‌্যাঙ্ক যুক্তির আশেপাশে পেরেনগুলি সরিয়ে ফেলতে পারেন। "(_,1)to "_ 1#:বাম যুক্তি ছাড়া কাজ করবে।
isawdrones

@ আইসড্রোনস: আমি মনে করি theতিহ্যবাহী প্রতিক্রিয়া হ'ল দীর্ঘক্ষণ অর্ধেক উত্তর উত্সাহিত করে আমার আত্মাকে চূর্ণ করবে। "চিৎকার এবং লাফিয়ে উঠুন", যেমন কেজিন বলতেন। ধন্যবাদ, যদিও এটি 10-বিজোড় চরিত্রগুলি মুছে ফেলে ... আমি যখন এটিতে ফিরে আসি তখন আমি 100 এর নিচে হতে পারি।
জেসি মিলিকান

সুন্দর এবং বিস্তারিত ব্যাখ্যার জন্য +1, খুব আকর্ষণীয় পড়ুন!
টিমউই

সম্ভবত কোনও উপযুক্ত সময়ে N = V = 99 পরিচালনা করবে না। আমি সবে যুক্ত করা বড় উদাহরণ চেষ্টা করুন।
কীথ র্যান্ডাল

3

কে - 89

জে সমাধান হিসাবে একই পদ্ধতি।

n:**c:.:'0:`;`0::[#b:t@&&/+|/''(0<'c)=/:(t:+2_vs!_2^n)@\:-1+_abs c:1_ c;5:b;"UNSOLVABLE"]

ভাল লাগল, আমি জানতাম না এখানে ফ্রি কে বাস্তবায়ন হয়েছে।
জেসি মিলিকান

সম্ভবত কোনও উপযুক্ত সময়ে N = V = 99 পরিচালনা করবে না। আমি সবে যুক্ত করা বড় উদাহরণ চেষ্টা করুন।
কিথ র্যান্ডাল

2

রুবি, 253

n,v=gets.split;d=[];v.to_i.times{d<<(gets.split.map &:to_i)};n=n.to_i;r=[1,!1]*n;r.permutation(n){|x|y=x[0,n];x=[0]+y;puts y.map{|z|z||0}.join ' 'or exit if d.inject(1){|t,w|t and(w[0]<0?!x[-w[0]]:x[w[0]])||(w[1]<0?!x[-w[1]]:x[w[1]])}};puts 'UNSOLVABLE'

তবে এটি ধীর :(

সুন্দর পাঠযোগ্য একবার প্রসারিত:

n,v=gets.split
d=[]
v.to_i.times{d<<(gets.split.map &:to_i)} # read data
n=n.to_i
r=[1,!1]*n # create an array of n trues and n falses
r.permutation(n){|x| # for each permutation of length n
    y=x[0,n]
    x=[0]+y
    puts y.map{|z| z||0}.join ' ' or exit if d.inject(1){|t,w| # evaluate the data (magic!)
        t and (w[0]<0 ? !x[-w[0]] : x[w[0]]) || (w[1]<0 ? !x[-w[1]] : x[w[1]])
    }
}
puts 'UNSOLVABLE'

সম্ভবত কোনও উপযুক্ত সময়ে N = V = 99 পরিচালনা করবে না। আমি সবে যুক্ত করা বড় উদাহরণ চেষ্টা করুন।
কীথ র্যান্ডাল

1

OCaml + ব্যাটারি, 438 436 টি অক্ষর

শীর্ষ স্তরের অন্তর্ভুক্ত একটি ওসিএএমএল ব্যাটারি প্রয়োজন:

module L=List
let(%)=L.mem
let rec r v d c n=match d,c with[],[]->[String.join" "[?L:if x%v
then"1"else"0"|x<-1--n?]]|[],(x,_)::_->r(x::v)c[]n@r(-x::v)c[]n@["UNSOLVABLE"]|(x,y)::c,d->let(!)w=if-w%v
then[]else r(w::v)(c@d)[]n in if x%v||y%v then r v c d n else if-x%v then!y else if-y%v then!x else r v c((x,y)::d)n
let(v,_)::l=L.of_enum(IO.lines_of stdin|>map(fun s->Scanf.sscanf s"%d %d"(fun x y->x,y)))in print_endline(L.hd(r[][]l v))

আমাকে অবশ্যই স্বীকার করতে হবে, এটি হ্যাস্কেল সমাধানের সরাসরি অনুবাদ। আমার প্রতিরক্ষা হিসাবে, পরিবর্তে এটি এখানে উপস্থাপন করা অ্যালগরিদমের সরাসরি কোডিং [পিডিএফ] রয়েছে, পারস্পরিক satisfy- eliminateপুনরাবৃত্তিটি একটি ফাংশনে রূপান্তরিত করে। কোডের একটি অবিস্মরণীয় সংস্করণ, ব্যাটারিগুলির ব্যবহার বিয়োগ:

let rec satisfy v c d = match c, d with
| (x, y) :: c, d ->
    let imply w = if List.mem (-w) v then raise Exit else satisfy (w :: v) (c @ d) [] in
    if List.mem x v || List.mem y v then satisfy v c d else
    if List.mem (-x) v then imply y else
    if List.mem (-y) v then imply x else
    satisfy v c ((x, y) :: d)
| [], [] -> v
| [], (x, _) :: _ -> try satisfy (x :: v) d [] with Exit -> satisfy (-x :: v) d []

let rec iota i =
    if i = 0 then [] else
    iota (i - 1) @ [i]

let () = Scanf.scanf "%d %d\n" (fun k n ->
    let l = ref [] in
    for i = 1 to n do
        Scanf.scanf "%d %d\n" (fun x y -> l := (x, y) :: !l)
    done;
    print_endline (try let v = satisfy [] [] !l in
    String.concat " " (List.map (fun x -> if List.mem x v then "1" else "0") (iota k))
    with Exit -> "UNSOLVABLE") )

( iota kপাং আমি আশা করি আপনি ক্ষমা করবেন)।


ওসিএএমএল সংস্করণ দেখে ভাল লাগল! এটি কার্যকরী প্রোগ্রামগুলির জন্য একটি দুর্দান্ত রোসটা স্টোন শুরু করে। এখন যদি আমরা স্কেলা এবং এফ # সংস্করণটি পেতে পারি ... - অ্যালগোরিদম হিসাবে - আপনি এখানে উল্লেখ না করা পর্যন্ত আমি পিডিএফটি দেখতে পাইনি! আমি আমার বাস্তবায়নটি উইকিপিডিয়া পৃষ্ঠার "সীমিত ব্যাকট্র্যাকিং" এর বর্ণনা থেকে বন্ধ করে দিয়েছি।
এমটিএনভিউমার্ক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.