Skip to content

Commit abd6f67

Browse files
committed
Fix: use enum for SAT assignment + speedup SAT#to_variables
1 parent 98fd7d7 commit abd6f67

File tree

1 file changed

+25
-23
lines changed

1 file changed

+25
-23
lines changed

src/sat.cr

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ module Shards
77
alias Literal = Int32
88
alias Clause = Array(Literal)
99

10+
enum Assignment : Int8
11+
NOT_SELECTED = 0
12+
SELECTED = 1
13+
UNDEFINED = -1
14+
end
15+
1016
def self.from_io(io : IO) : SAT
1117
new.tap do |sat|
1218
while line = io.gets
@@ -65,39 +71,35 @@ module Shards
6571
end
6672
end
6773

68-
protected def assignment_to_s(assignment : Array(Literal?), brief = false)
74+
protected def assignment_to_s(assignment, brief = false)
6975
String.build do |str|
70-
assignment.zip(@variables).compact_map do |(a, v)|
71-
if a == 0
72-
next if brief
73-
str << '~'
76+
assignment.each_with_index do |a, index|
77+
if a.selected?
78+
str << @variables[index] << ' '
79+
elsif !brief && a.not_selected?
80+
str << '~' << @variables[index] << ' ' unless brief
7481
end
75-
str << v << ' '
7682
end
7783
end
7884
end
7985

80-
protected def to_assigment(assignment : Array(Literal?), brief = false)
81-
aa = Array(String).new(assignment.size)
82-
83-
assignment.zip(@variables).each do |(a, v)|
84-
if a == 0
85-
aa << "~#{v}" unless brief
86-
else
87-
aa << v
86+
protected def to_variables(assignment, brief = false)
87+
assignment.each_with_index.compact_map do |(a, index)|
88+
if a.selected?
89+
@variables[index]
90+
elsif !brief && a.not_selected?
91+
"~#{@variables[index]}"
8892
end
89-
end
90-
91-
aa
93+
end.to_a
9294
end
9395

9496
# Solves SAT and yields solutions.
9597
def solve(brief = true, verbose = false) : Nil
9698
watchlist = setup_watchlist
97-
assignment = Array(Literal?).new(@variables.size) { nil }
99+
assignment = Array(Assignment).new(@variables.size) { Assignment::UNDEFINED }
98100

99101
solve(watchlist, assignment, 0, verbose) do |solution|
100-
yield to_assigment(solution, brief)
102+
yield to_variables(solution, brief)
101103
end
102104
end
103105

@@ -130,10 +132,10 @@ module Shards
130132

131133
# set the bit indicating a has been tried for d:
132134
state[d] |= 1 << a
133-
assignment[d] = a
135+
assignment[d] = Assignment.from_value(a)
134136

135137
if !update_watchlist(watchlist, (d << 1) | a, assignment, verbose)
136-
assignment[d] = nil
138+
assignment[d] = Assignment::UNDEFINED
137139
else
138140
d += 1
139141
break
@@ -149,7 +151,7 @@ module Shards
149151

150152
# backtrack:
151153
state[d] = 0
152-
assignment[d] = nil
154+
assignment[d] = Assignment::UNDEFINED
153155
d -= 1
154156
end
155157
end
@@ -183,7 +185,7 @@ module Shards
183185
a = alternative & 1
184186
av = assignment[v]
185187

186-
if av.nil? || av == a ^ 1
188+
if av.undefined? || av.value == a ^ 1
187189
found_alternative = true
188190
watchlist[false_literal].shift?
189191
watchlist[alternative] << clause

0 commit comments

Comments
 (0)