Commiting my local changes ...
[satune.git] / src / Backend / inc_solver.cc
1 /*      Copyright (c) 2015 Regents of the University of California
2  *
3  *      Author: Brian Demsky <bdemsky@uci.edu>
4  *
5  *      This program is free software; you can redistribute it and/or
6  *      modify it under the terms of the GNU General Public License
7  *      version 2 as published by the Free Software Foundation.
8  */
9
10 #include "inc_solver.h"
11 #define SATSOLVER "sat_solver"
12 #include <fcntl.h>
13 #include "common.h"
14 #include <string.h>
15 #include <stdexcept>
16
17 IncrementalSolver *allocIncrementalSolver() {
18         IncrementalSolver *This = (IncrementalSolver *)ourmalloc(sizeof(IncrementalSolver));
19         This->buffer = ((int *)ourmalloc(sizeof(int) * IS_BUFFERSIZE));
20         This->solution = NULL;
21         This->solutionsize = 0;
22         This->offset = 0;
23         createSolver(This);
24         return This;
25 }
26
27 void deleteIncrementalSolver(IncrementalSolver *This) {
28         killSolver(This);
29         ourfree(This->buffer);
30         if (This->solution != NULL)
31                 ourfree(This->solution);
32         ourfree(This);
33 }
34
35 void resetSolver(IncrementalSolver *This) {
36         killSolver(This);
37         This->offset = 0;
38         createSolver(This);
39 }
40
41 void addClauseLiteral(IncrementalSolver *This, int literal) {
42         This->buffer[This->offset++] = literal;
43         if (This->offset == IS_BUFFERSIZE) {
44                 flushBufferSolver(This);
45         }
46 }
47
48 void addArrayClauseLiteral(IncrementalSolver *This, uint numliterals, int *literals) {
49         uint index = 0;
50         while (true) {
51                 uint bufferspace = IS_BUFFERSIZE - This->offset;
52                 uint numtowrite = numliterals - index;
53                 if (bufferspace > numtowrite) {
54                         memcpy(&This->buffer[This->offset], &literals[index], numtowrite * sizeof(int));
55                         This->offset += numtowrite;
56                         This->buffer[This->offset++] = 0;       //have one extra spot always
57                         if (This->offset == IS_BUFFERSIZE) {//Check if full
58                                 flushBufferSolver(This);
59                         }
60                         return;
61                 } else {
62                         memcpy(&This->buffer[This->offset], &literals[index], bufferspace * sizeof(int));
63                         This->offset += bufferspace;
64                         index += bufferspace;
65                         flushBufferSolver(This);
66                 }
67         }
68 }
69
70 void finishedClauses(IncrementalSolver *This) {
71         This->buffer[This->offset++] = 0;
72         if (This->offset == IS_BUFFERSIZE) {
73                 flushBufferSolver(This);
74         }
75 }
76
77 void freeze(IncrementalSolver *This, int variable) {
78         addClauseLiteral(This, IS_FREEZE);
79         addClauseLiteral(This, variable);
80 }
81
82 int solve(IncrementalSolver *This) {
83         //add an empty clause
84         startSolve(This);
85         return getSolution(This);
86 }
87
88 void startSolve(IncrementalSolver *This) {
89         addClauseLiteral(This, IS_RUNSOLVER);
90         flushBufferSolver(This);
91 }
92
93 int getSolution(IncrementalSolver *This) {
94         int result = readIntSolver(This);
95         if (result == IS_SAT) {
96                 int numVars = readIntSolver(This);
97                 if (numVars > This->solutionsize) {
98                         if (This->solution != NULL)
99                                 ourfree(This->solution);
100                         This->solution = (int *) ourmalloc((numVars + 1) * sizeof(int));
101                         This->solution[0] = 0;
102                 }
103                 readSolver(This, &This->solution[1], numVars * sizeof(int));
104                 This->solutionsize = numVars;
105         }
106         return result;
107 }
108
109 int readIntSolver(IncrementalSolver *This) {
110         int value;
111         readSolver(This, &value, 4);
112         return value;
113 }
114
115 void readSolver(IncrementalSolver *This, void *tmp, ssize_t size) {
116         char *result = (char *) tmp;
117         ssize_t bytestoread = size;
118         ssize_t bytesread = 0;
119         do {
120                 ssize_t n = read(This->from_solver_fd, &((char *)result)[bytesread], bytestoread);
121                 if (n == -1) {
122                         model_print("Read failure\n");
123                         throw std::runtime_error("Read failure\n");
124                 }
125                 bytestoread -= n;
126                 bytesread += n;
127         } while (bytestoread != 0);
128 }
129
130 bool getValueSolver(IncrementalSolver *This, int variable) {
131         return This->solution[variable];
132 }
133
134 void createSolver(IncrementalSolver *This) {
135         int to_pipe[2];
136         int from_pipe[2];
137         if (pipe(to_pipe) || pipe(from_pipe)) {
138                 model_print("Error creating pipe.\n");
139                 exit(-1);
140         }
141         if ((This->solver_pid = fork()) == -1) {
142                 model_print("Error forking.\n");
143                 exit(-1);
144         }
145         if (This->solver_pid == 0) {
146                 //Solver process
147                 close(to_pipe[1]);
148                 close(from_pipe[0]);
149                 int fd = open("log_file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
150
151                 if ((dup2(to_pipe[0], 0) == -1) ||
152                                 (dup2(from_pipe[1], IS_OUT_FD) == -1) ||
153                                 (dup2(fd, 1) == -1)) {
154                         model_print("Error duplicating pipes\n");
155                 }
156                 //    setsid();
157                 execlp(SATSOLVER, SATSOLVER, NULL);
158                 model_print("execlp Failed\n");
159                 close(fd);
160         } else {
161                 //Our process
162                 This->to_solver_fd = to_pipe[1];
163                 This->from_solver_fd = from_pipe[0];
164                 close(to_pipe[0]);
165                 close(from_pipe[1]);
166         }
167 }
168
169 void killSolver(IncrementalSolver *This) {
170         close(This->to_solver_fd);
171         close(This->from_solver_fd);
172         //Stop the solver
173         if (This->solver_pid > 0) {
174                 int status;
175                 kill(This->solver_pid, SIGKILL);
176                 waitpid(This->solver_pid, &status, 0);
177         }
178 }
179
180 //DEBUGGING CODE STARTS
181 bool first = true;
182 //DEBUGGING CODE ENDS
183
184 void flushBufferSolver(IncrementalSolver *This) {
185         ssize_t bytestowrite = sizeof(int) * This->offset;
186         ssize_t byteswritten = 0;
187 #ifdef CONFIG_DEBUG
188         for (uint i = 0; i < This->offset; i++) {
189                 if (first)
190                         printf("(");
191                 if (This->buffer[i] == 0) {
192                         printf(")\n");
193                         first = true;
194                 } else {
195                         if (!first)
196                                 printf(" + ");
197                         first = false;
198                         printf("%d", This->buffer[i]);
199                 }
200         }
201 #endif
202         do {
203                 ssize_t n = write(This->to_solver_fd, &((char *)This->buffer)[byteswritten], bytestowrite);
204                 if (n == -1) {
205                         perror("Write failure\n");
206                         model_print("to_solver_fd=%d\n",This->to_solver_fd);
207                         exit(-1);
208                 }
209                 bytestowrite -= n;
210                 byteswritten += n;
211         } while (bytestowrite != 0);
212         This->offset = 0;
213 }