Added some comments, fixed what I think is a bug in the clause sorting.
This commit is contained in:
28
cnf.c
28
cnf.c
@@ -13,15 +13,19 @@ cnf* readDIMACS(char* path) {
|
|||||||
|
|
||||||
CHECK(fgets(buf, sizeof(char) * bufsize, f), "Failed to read file\n");
|
CHECK(fgets(buf, sizeof(char) * bufsize, f), "Failed to read file\n");
|
||||||
|
|
||||||
|
// 'c' marks the beginning of a comment line in DIMACs. Skip this line
|
||||||
while (buf[0] == 'c') {
|
while (buf[0] == 'c') {
|
||||||
CHECK(fgets(buf, sizeof(char) * bufsize, f), "Failed to read file\n");
|
CHECK(fgets(buf, sizeof(char) * bufsize, f), "Failed to read file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The first non-comment line is the header, should have format 'p cnf [varcnt] [clausecnt]
|
||||||
|
// We skip the first bit by iterating and skipping any character that's p, c, n, f, or space
|
||||||
char* temp = buf;
|
char* temp = buf;
|
||||||
while (*temp == ' ' || *temp == 'p' || *temp == 'c' || *temp == 'n' || *temp == 'f') {
|
while (*temp == ' ' || *temp == 'p' || *temp == 'c' || *temp == 'n' || *temp == 'f') {
|
||||||
temp++;
|
temp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Char by char we read in the number of variables
|
||||||
c->varcnt = 0;
|
c->varcnt = 0;
|
||||||
while (((u8) (*temp - '0')) < 10) {
|
while (((u8) (*temp - '0')) < 10) {
|
||||||
c->varcnt *= 10;
|
c->varcnt *= 10;
|
||||||
@@ -29,8 +33,10 @@ cnf* readDIMACS(char* path) {
|
|||||||
temp++;
|
temp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip any trailing whitespace
|
||||||
while (*temp == ' ') temp++;
|
while (*temp == ' ') temp++;
|
||||||
|
|
||||||
|
// Read in clausecnt
|
||||||
c->clausecnt = 0;
|
c->clausecnt = 0;
|
||||||
while (((u8) (*temp - '0')) < 10) {
|
while (((u8) (*temp - '0')) < 10) {
|
||||||
c->clausecnt *= 10;
|
c->clausecnt *= 10;
|
||||||
@@ -38,6 +44,9 @@ cnf* readDIMACS(char* path) {
|
|||||||
temp++;
|
temp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resize line buffer: the maximum clause size is varcnt, the maximum size of a u32 in decimal
|
||||||
|
// is 10, and conservatively given 2 extra characters for the - symbol and space delimiting,
|
||||||
|
// resizing the buffer to this should mean we never encounter a clause we fail to read.
|
||||||
u32 nsize = sizeof(char) * (c->varcnt * 12LU) + 10;
|
u32 nsize = sizeof(char) * (c->varcnt * 12LU) + 10;
|
||||||
char* nbuf = realloc(buf, nsize);
|
char* nbuf = realloc(buf, nsize);
|
||||||
CHECK(nbuf, "Failed to realloc read buffer\n");
|
CHECK(nbuf, "Failed to realloc read buffer\n");
|
||||||
@@ -47,6 +56,9 @@ cnf* readDIMACS(char* path) {
|
|||||||
u32 cnt = 0;
|
u32 cnt = 0;
|
||||||
u32 cap = 32;
|
u32 cap = 32;
|
||||||
|
|
||||||
|
// We store separate arrays: literal i of the CNF has a parity at index i in one array
|
||||||
|
// the variable it corresponds to at the same index in another
|
||||||
|
// And the clause it's a member of in a third
|
||||||
c->variables = calloc( cap, sizeof(u32));
|
c->variables = calloc( cap, sizeof(u32));
|
||||||
CHECK(c->variables, "Failed to allocate literal variables\n");
|
CHECK(c->variables, "Failed to allocate literal variables\n");
|
||||||
c->clauses = calloc( cap, sizeof(u32));
|
c->clauses = calloc( cap, sizeof(u32));
|
||||||
@@ -60,15 +72,15 @@ cnf* readDIMACS(char* path) {
|
|||||||
for (u32 i = 0; i < c->clausecnt; ++i) {
|
for (u32 i = 0; i < c->clausecnt; ++i) {
|
||||||
CHECK(fgets(buf, nsize, f), "Failed to read clause\n");
|
CHECK(fgets(buf, nsize, f), "Failed to read clause\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
temp = buf;
|
temp = buf;
|
||||||
while (*temp == ' ') temp++;
|
while (*temp == ' ') temp++;
|
||||||
|
|
||||||
|
// Iterate through char by char
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
bool tr = true;
|
bool tr = true;
|
||||||
while (*temp != '\n') {
|
while (*temp != '\n') {
|
||||||
if (cnt == cap) {
|
if (cnt == cap) {
|
||||||
|
// Out of space to add more literals, realloc arrays
|
||||||
u32 ncap = cap << 1U;
|
u32 ncap = cap << 1U;
|
||||||
c->variables = realloc(c->variables, sizeof(u32) * ncap);
|
c->variables = realloc(c->variables, sizeof(u32) * ncap);
|
||||||
memset(c->variables + cap, 0, sizeof(u32) * cap);
|
memset(c->variables + cap, 0, sizeof(u32) * cap);
|
||||||
@@ -83,11 +95,15 @@ cnf* readDIMACS(char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*temp == '-') {
|
if (*temp == '-') {
|
||||||
|
// Mark that the literal currently being read is negated
|
||||||
tr = false;
|
tr = false;
|
||||||
} else if (((u8) (*temp - '0')) < 10) {
|
} else if (((u8) (*temp - '0')) < 10) {
|
||||||
|
// Read in the literal's digits
|
||||||
c->variables[cnt] *= 10;
|
c->variables[cnt] *= 10;
|
||||||
c->variables[cnt] += (*temp - '0');
|
c->variables[cnt] += (*temp - '0');
|
||||||
} else {
|
} else {
|
||||||
|
// Skip any whitespace and pack the read value into the arrays, along with
|
||||||
|
// any additional data
|
||||||
while (temp[1] == ' ') temp++;
|
while (temp[1] == ' ') temp++;
|
||||||
c->pars[cnt] = tr;
|
c->pars[cnt] = tr;
|
||||||
c->clauses[cnt] = i;
|
c->clauses[cnt] = i;
|
||||||
@@ -109,6 +125,8 @@ cnf* readDIMACS(char* path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lastvars is set to the index of the last variable of each clause. However, because in the
|
||||||
|
// counter, the last variable has the lsb position, we flip the value of lastvars
|
||||||
for (u32 i = 0; i < c->clausecnt; ++i) {
|
for (u32 i = 0; i < c->clausecnt; ++i) {
|
||||||
c->lastvars[i] += 1U;
|
c->lastvars[i] += 1U;
|
||||||
c->lastvars[i] = c->varcnt - c->lastvars[i];
|
c->lastvars[i] = c->varcnt - c->lastvars[i];
|
||||||
@@ -116,6 +134,7 @@ cnf* readDIMACS(char* path) {
|
|||||||
|
|
||||||
c->litcnt = cnt;
|
c->litcnt = cnt;
|
||||||
|
|
||||||
|
// Realloc the arrays to exactly match the number of literals
|
||||||
c->variables = realloc(c->variables, sizeof(u32) * c->litcnt);
|
c->variables = realloc(c->variables, sizeof(u32) * c->litcnt);
|
||||||
c->clauses = realloc(c->clauses, sizeof(u32) * c->litcnt);
|
c->clauses = realloc(c->clauses, sizeof(u32) * c->litcnt);
|
||||||
c->pars = realloc(c->pars, sizeof(u8) * c->litcnt);
|
c->pars = realloc(c->pars, sizeof(u8) * c->litcnt);
|
||||||
@@ -156,6 +175,7 @@ const u64 RMASK = RSIZE - 1;
|
|||||||
// I need to sort by lastvar, within that sort by clause
|
// I need to sort by lastvar, within that sort by clause
|
||||||
|
|
||||||
void sortlastnum(cnf* c, u64 N) {
|
void sortlastnum(cnf* c, u64 N) {
|
||||||
|
// Radix sort on the literals themselves based on their clause's
|
||||||
bool v = false;
|
bool v = false;
|
||||||
u32* d = malloc(sizeof(u32) * c->litcnt);
|
u32* d = malloc(sizeof(u32) * c->litcnt);
|
||||||
u32* d2 = malloc(sizeof(u32) * c->litcnt);
|
u32* d2 = malloc(sizeof(u32) * c->litcnt);
|
||||||
@@ -170,7 +190,7 @@ void sortlastnum(cnf* c, u64 N) {
|
|||||||
u64 shift = pass * RBITS;
|
u64 shift = pass * RBITS;
|
||||||
|
|
||||||
for (u64 i = 0; i < N; ++i) {
|
for (u64 i = 0; i < N; ++i) {
|
||||||
u32 val = UINT32_MAX - c->lastvars[(c->clausecnt - 1) - c->clauses[i]];
|
u32 val = UINT32_MAX - c->lastvars[c->clauses[i]];
|
||||||
u64 ind = (val >> shift) & RMASK;
|
u64 ind = (val >> shift) & RMASK;
|
||||||
qe[pass * RSIZE + ind]++;
|
qe[pass * RSIZE + ind]++;
|
||||||
}
|
}
|
||||||
@@ -185,7 +205,7 @@ void sortlastnum(cnf* c, u64 N) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < N; ++i) {
|
for (u64 i = 0; i < N; ++i) {
|
||||||
u32 val = UINT32_MAX - c->lastvars[(c->clausecnt - 1) - c->clauses[i]];
|
u32 val = UINT32_MAX - c->lastvars[c->clauses[i]];
|
||||||
u64 ind = (val >> shift) & RMASK;
|
u64 ind = (val >> shift) & RMASK;
|
||||||
d[qb[pass * RSIZE + ind]] = c->variables[i];
|
d[qb[pass * RSIZE + ind]] = c->variables[i];
|
||||||
d2[qb[pass * RSIZE + ind]] = c->clauses[i];
|
d2[qb[pass * RSIZE + ind]] = c->clauses[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user