c1bebb806ad0e453ebd1e5a7e087ca34ac697551
[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
16 IncrementalSolver *allocIncrementalSolver() {
17         IncrementalSolver *This = (IncrementalSolver *)ourmalloc(sizeof(IncrementalSolver));
18         This->buffer = ((int *)ourmalloc(sizeof(int) * IS_BUFFERSIZE));
19         This->solution = NULL;
20         This->solutionsize = 0;
21         This->offset = 0;
22         This->timeout = NOTIMEOUT;
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 = readStatus(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 int readStatus(IncrementalSolver *This) {
116         int retval;
117         fd_set rfds;
118         FD_ZERO(&rfds);
119         FD_SET(This->from_solver_fd, &rfds);
120         fd_set * temp;
121         if(This->timeout == NOTIMEOUT){
122                 retval = select(This->from_solver_fd+1, &rfds, NULL, NULL, NULL);
123         }else {
124                 struct timeval tv;
125                 tv.tv_sec = This->timeout;
126                 tv.tv_usec = 0;
127                 retval = select(This->from_solver_fd+1, &rfds, NULL, NULL, &tv);
128         }
129         if(retval == -1){
130                 perror("Error in select()");
131                 exit(EXIT_FAILURE);
132         }
133         else if (retval){
134                 printf("Data is available now.\n");
135                 return readIntSolver(This);
136         }else{
137                 printf("Timeout for the solver\n");
138                 return IS_INDETER;
139         }
140 }
141
142 void readSolver(IncrementalSolver *This, void *tmp, ssize_t size) {
143         char *result = (char *) tmp;
144         ssize_t bytestoread = size;
145         ssize_t bytesread = 0;
146         do {
147                 ssize_t n = read(This->from_solver_fd, &((char *)result)[bytesread], bytestoread);
148                 if (n == -1) {
149                         model_print("Read failure\n");
150                         exit(-1);
151                 }
152                 bytestoread -= n;
153                 bytesread += n;
154         } while (bytestoread != 0);
155 }
156
157 bool getValueSolver(IncrementalSolver *This, int variable) {
158         return This->solution[variable];
159 }
160
161 void createSolver(IncrementalSolver *This) {
162         int to_pipe[2];
163         int from_pipe[2];
164         if (pipe(to_pipe) || pipe(from_pipe)) {
165                 model_print("Error creating pipe.\n");
166                 exit(-1);
167         }
168         if ((This->solver_pid = fork()) == -1) {
169                 model_print("Error forking.\n");
170                 exit(-1);
171         }
172         if (This->solver_pid == 0) {
173                 //Solver process
174                 close(to_pipe[1]);
175                 close(from_pipe[0]);
176                 int fd = open("log_file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
177
178                 if ((dup2(to_pipe[0], 0) == -1) ||
179                                 (dup2(from_pipe[1], IS_OUT_FD) == -1) ||
180                                 (dup2(fd, 1) == -1)) {
181                         model_print("Error duplicating pipes\n");
182                 }
183                 //    setsid();
184                 execlp(SATSOLVER, SATSOLVER, NULL);
185                 model_print("execlp Failed\n");
186                 close(fd);
187         } else {
188                 //Our process
189                 This->to_solver_fd = to_pipe[1];
190                 This->from_solver_fd = from_pipe[0];
191                 close(to_pipe[0]);
192                 close(from_pipe[1]);
193         }
194 }
195
196 void killSolver(IncrementalSolver *This) {
197         close(This->to_solver_fd);
198         close(This->from_solver_fd);
199         //Stop the solver
200         if (This->solver_pid > 0) {
201                 int status;
202                 kill(This->solver_pid, SIGKILL);
203                 waitpid(This->solver_pid, &status, 0);
204         }
205 }
206
207 //DEBUGGING CODE STARTS
208 bool first = true;
209 //DEBUGGING CODE ENDS
210
211 void flushBufferSolver(IncrementalSolver *This) {
212         ssize_t bytestowrite = sizeof(int) * This->offset;
213         ssize_t byteswritten = 0;
214 #ifdef CONFIG_DEBUG
215         for (uint i = 0; i < This->offset; i++) {
216                 if (first)
217                         printf("(");
218                 if (This->buffer[i] == 0) {
219                         printf(")\n");
220                         first = true;
221                 } else {
222                         if (!first)
223                                 printf(" + ");
224                         first = false;
225                         printf("%d", This->buffer[i]);
226                 }
227         }
228 #endif
229         do {
230                 ssize_t n = write(This->to_solver_fd, &((char *)This->buffer)[byteswritten], bytestowrite);
231                 if (n == -1) {
232                         perror("Write failure\n");
233                         model_print("to_solver_fd=%d\n",This->to_solver_fd);
234                         exit(-1);
235                 }
236                 bytestowrite -= n;
237                 byteswritten += n;
238         } while (bytestowrite != 0);
239         This->offset = 0;
240 }