@@ -7,5 +7,110 @@ import java.nio.file.{Files, Path}
77
88object SatSolver :
99 def solve (problem : ProblemDefinition ): Unit =
10- println(" Don't wanna play anymore." )
11- return
10+ println(s " Solving problem ${problem.name}. " )
11+ Ædificium.select(problem.name)
12+ println(s " ${problem.name} has been selected. " )
13+
14+ var knowledge = KnowledgeHolder (Vector .empty, Vector .empty)
15+ while true do
16+ println(" Determining next step..." )
17+ val step = nextStep(problem, knowledge)
18+ println(s " Next step is ${step.getClass.getSimpleName}" )
19+ step match
20+ case Step .ExploreStep (plans) =>
21+ knowledge = explore(problem, knowledge, plans)
22+ case Step .GuessStep (solution) =>
23+ println(" Trying to commit the solution." )
24+ val correct = Ædificium.guess(solution)
25+ if correct then
26+ println(s " The solution for problem ${problem.name} is correct. " )
27+ return
28+ else
29+ println(s " The solution for problem ${problem.name} is not correct! " )
30+ throw new Exception (" Incorrect solution! Analyze results in \" path\" ." )
31+ case Step .StopGuessing () =>
32+ println(" Don't wanna play anymore." )
33+ return
34+
35+ private def nextStep (problem : ProblemDefinition , knowledge : KnowledgeHolder ): Step =
36+ var exploredConnections = Seq .empty[(Int , Int , Int )]
37+
38+ for j <- knowledge.visitedRoutes.indices do
39+ val plan = knowledge.visitedRoutes(j)
40+ val rooms = knowledge.visitedRooms(j)
41+
42+ for i <- plan.indices do
43+ val door = plan(i)
44+ val enter = rooms(i)
45+ val exit = rooms(i + 1 )
46+
47+ exploredConnections = exploredConnections :+ (enter, exit, door)
48+
49+ println(s " explored conntection: ${exploredConnections}" )
50+
51+ val folder = Files .createTempDirectory(s " icfpc.sat. ${problem.name}" )
52+ println(s " Temp directory: ${folder}" )
53+
54+ val sb = new StringBuilder ()
55+ val roomLabelVariablesCount = problem.size* 4
56+ val roomLabelClausesCount = problem.size
57+
58+ val connectionVariablesCount = problem.size* problem.size* 6 + problem.size* 6
59+ val connectionClausesCount = problem.size* 6 + problem.size* problem.size* 6
60+
61+ val variablesCount = roomLabelVariablesCount + connectionVariablesCount
62+ val clausesCount = roomLabelClausesCount + connectionClausesCount
63+ sb ++= s " p cnf ${variablesCount} 9999 \n "
64+
65+ // rooms has one of {0, 1, 2, 3} labels
66+ for i <- 0 to problem.size - 1 do
67+ for l <- 0 to 3 do
68+ sb ++= s " ${roomLabelVariableIndex(i, l)} "
69+ sb ++= " 0\n "
70+
71+ // for door d should exist at least one connection
72+ for i <- 0 to problem.size - 1 do
73+ for d <- 0 to 5 do
74+ for j <- 0 to problem.size - 1 do
75+ sb ++= s " ${roomLabelVariablesCount + connectionVariableIndex(problem.size, i, j, d)} "
76+ sb ++= " 0\n "
77+
78+ // but no more than one
79+ for i <- 0 to problem.size - 1 do
80+ for d <- 0 to 5 do
81+ for k <- 0 to problem.size - 1 do
82+ for l <- 0 to problem.size - 1 do
83+ if k < l then
84+ sb ++= s " - ${roomLabelVariablesCount + connectionVariableIndex(problem.size, i, k, d)} "
85+ sb ++= s " - ${roomLabelVariablesCount + connectionVariableIndex(problem.size, i, l, d)} "
86+ sb ++= " 0\n "
87+
88+ // no isolated rooms
89+ for i <- 0 to problem.size - 1 do
90+ for d <- 0 to 5 do
91+ sb ++= s " - ${roomLabelVariablesCount + connectionVariableIndex(problem.size, i, i, d)} "
92+ sb ++= " 0\n "
93+
94+ // there is should be at least one back connection OR forward connection should not exist
95+ for i <- 0 to problem.size - 1 do
96+ for j <- 0 to problem.size - 1 do
97+ for d <- 0 to 5 do
98+ sb ++= s " - ${roomLabelVariablesCount + connectionVariableIndex(problem.size, i, j, d)} "
99+ for k <- 0 to 5 do
100+ sb ++= s " ${roomLabelVariablesCount + connectionVariableIndex(problem.size, j, i, k)} "
101+ sb ++= " 0\n "
102+
103+
104+ Files .writeString(folder.resolve(" step1.dimacs" ), sb.toString)
105+ throw new Exception (" Incorrect solution! Analyze results in \" path\" ." )
106+
107+ if knowledge.visitedRoutes.size > 0 then
108+ return Step .StopGuessing ()
109+ else
110+ val plan = Seq (Lanternarius .lanternarius(problem.maxRouteLength))
111+ return Step .ExploreStep (plan)
112+
113+ private def roomLabelVariableIndex (room : Int , label : Int ): Int = room* 4 + label + 1
114+
115+ private def connectionVariableIndex (roomsCount : Int , enterRoom : Int , exitRoom : Int , door : Int ) =
116+ enterRoom* roomsCount* 6 + exitRoom* 6 + door + 1
0 commit comments