aced/src/main.c

260 lines
7.8 KiB
C

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../includes/cg.h"
#include "../includes/matrix.h"
#include "../includes/permutation.h"
static void ReadArguments(char *from, size_t *into, const char *varname) {
if (!sscanf(from, "%zu", into)) {
fprintf(stderr, "Failed to read %s.", varname);
exit(EXIT_FAILURE);
}
}
static inline void AdvanceConditionalPermutations(
permutation_generator_t *generators, size_t count) {
PermutationNext(generators);
for (size_t i = 0; i < count - 1; i++) {
if (generators[i].exhausted) {
PermutationReset(generators + i);
PermutationNext(generators + i + 1);
}
}
// If generators[-1] is exhausted, the conditional permutations are exhausted.
}
static inline void ResetConditionalPermutations(
permutation_generator_t *generators, size_t count) {
for (size_t i = 0; i < count; i++) {
PermutationReset(generators + i);
}
}
typedef enum {
kRowFmt,
kCgFmt,
kPFmt,
kPRawFmt,
} arg_format_t;
int main(int argc, char *argv[]) {
if (argc < 5) {
fprintf(stderr,
"Usage:\n ./main.exe <A outputs> <B outputs> <A inputs> <B "
"inputs> [--cg|--p|--p-raw]");
exit(EXIT_FAILURE);
}
size_t a_out, b_out, a_in, b_in;
ReadArguments(argv[1], &a_out, "A outputs");
ReadArguments(argv[2], &b_out, "B outputs");
ReadArguments(argv[3], &a_in, "A inputs");
ReadArguments(argv[4], &b_in, "B inputs");
int cg_format = kRowFmt;
if (argc > 5) {
if (strcmp(argv[5], "--cg") == 0) {
cg_format = kCgFmt;
} else if (strcmp(argv[5], "--p") == 0) {
cg_format = kPFmt;
} else if (strcmp(argv[5], "--p-raw") == 0) {
cg_format = kPRawFmt;
}
}
size_t row_len = (a_out - 1) * (b_out - 1) * a_in * b_in +
(a_out - 1) * a_in + (b_out - 1) * b_in + 1;
matrix_t matrix = ParseMatrix(row_len);
size_t row_count = matrix.len / matrix.row_len;
data_t *p_buf = malloc(a_out * b_out * a_in * b_in * sizeof(data_t));
data_t *cg_buf = malloc((((a_out - 1) * (b_out - 1) * a_in * b_in +
(a_out - 1) * a_in + (b_out - 1) * b_in) +
1) *
sizeof(data_t));
_Bool *seen = calloc(row_count, sizeof(_Bool));
if (p_buf == NULL) {
fprintf(stderr, "Failed to allocate P notation buffer. Aborting.");
exit(EXIT_FAILURE);
}
if (cg_buf == NULL) {
fprintf(stderr, "Failed to allocate CG notation buffer. Aborting.");
exit(EXIT_FAILURE);
}
if (seen == NULL) {
fprintf(stderr, "Failed to allocate equivalence flag string. Aborting.");
exit(EXIT_FAILURE);
}
permutation_generator_t a_in_perm = PermutationNewGenerator(a_in);
permutation_generator_t b_in_perm = PermutationNewGenerator(b_in);
permutation_generator_t *a_out_perms =
malloc(a_in * sizeof(permutation_generator_t));
permutation_generator_t *b_out_perms =
malloc(b_in * sizeof(permutation_generator_t));
if (a_out_perms == NULL || b_out_perms == NULL) {
fprintf(stderr,
"Failed to allocate space for conditioned permutation generators. "
"Aborting.");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < a_in; i++) {
a_out_perms[i] = PermutationNewGenerator(a_out);
PermutationReset(a_out_perms + i);
}
for (size_t i = 0; i < b_in; i++) {
b_out_perms[i] = PermutationNewGenerator(b_out);
PermutationReset(b_out_perms + i);
}
// Start testing for equivalences.
for (size_t lhs_i = 0; lhs_i < row_count - 1; lhs_i++) {
if (seen[lhs_i]) {
continue;
}
fprintf(stderr, "%zu/%zu \033[G", lhs_i, row_count - 1);
fflush(stderr);
data_t *lhs = matrix.head + lhs_i * matrix.row_len;
for (size_t rhs_i = lhs_i + 1; rhs_i < row_count; rhs_i++) {
if (seen[rhs_i]) {
continue;
}
data_t *rhs = matrix.head + rhs_i * matrix.row_len;
PermutationReset(&a_in_perm);
while (!a_in_perm.exhausted) {
PermutationReset(&b_in_perm);
while (!b_in_perm.exhausted) {
ResetConditionalPermutations(a_out_perms, a_out);
while (!a_out_perms[a_out - 1].exhausted) {
ResetConditionalPermutations(b_out_perms, b_out);
while (!b_out_perms[b_out - 1].exhausted) {
// Compare the two rows
FromCgToP(a_out, b_out, a_in, b_in, rhs, p_buf,
a_in_perm.permutation, b_in_perm.permutation,
a_out_perms, b_out_perms);
{
FromPToCg(a_out, b_out, a_in, b_in, cg_buf, p_buf);
_Bool equivalent = 1;
for (size_t i = row_len; i > 0; i--) {
if (lhs[i - 1] != cg_buf[i - 1]) {
equivalent = 0;
break;
}
}
if (equivalent) {
seen[rhs_i] = 1;
goto skip_permutations;
}
}
// If the number of output labels are the same, and the number of
// input labels is also the same, we can also check for equality
// under party swapping.
// I don't expect this conditional to be very penalizing because
// it's very predictable.
if (a_in == b_in && a_out == b_out) {
// Use the results in p_buf
PSwapParties(a_out, a_in, p_buf);
FromPToCg(a_out, b_out, a_in, b_in, cg_buf, p_buf);
_Bool equivalent = 1;
for (size_t i = row_len; i > 0; i--) {
if (lhs[i - 1] != cg_buf[i - 1]) {
equivalent = 0;
break;
}
}
if (equivalent) {
seen[rhs_i] = 1;
goto skip_permutations;
}
}
AdvanceConditionalPermutations(b_out_perms, b_out);
}
AdvanceConditionalPermutations(a_out_perms, a_out);
}
PermutationNext(&b_in_perm);
}
PermutationNext(&a_in_perm);
}
skip_permutations:;
} // For loop over rhs_i
} // For loop over lhs_i
if (cg_format == kPFmt) {
PermutationReset(&a_in_perm);
PermutationReset(&b_in_perm);
for (size_t i = 0; i < a_in; i++) {
PermutationReset(a_out_perms + i);
}
for (size_t i = 0; i < b_in; i++) {
PermutationReset(b_out_perms + i);
}
}
// Print every unique row
for (size_t i = 0; i < row_count; i++) {
if (!seen[i]) {
switch (cg_format) {
default:
case kRowFmt: {
PrintMatrixRow(&matrix, i);
} break;
case kCgFmt: {
printf("%zu: ", i);
PrintCg(a_out, b_out, a_in, b_in, matrix.head + i * matrix.row_len);
} break;
case kPFmt: {
printf("%zu: ", i);
FromCgToP(a_out, b_out, a_in, b_in, matrix.head + i * matrix.row_len,
p_buf, a_in_perm.permutation, b_in_perm.permutation,
a_out_perms, b_out_perms);
PrintP(a_out, b_out, a_in, b_in, p_buf);
} break;
case kPRawFmt: {
FromCgToP(a_out, b_out, a_in, b_in, matrix.head + i * matrix.row_len,
p_buf, a_in_perm.permutation, b_in_perm.permutation,
a_out_perms, b_out_perms);
PrintPRaw(a_out, b_out, a_in, b_in, p_buf);
} break;
}
}
}
// Free all the memory so the sanitizer is happy.
free(seen);
free(cg_buf);
free(p_buf);
PermutationFree(&a_in_perm);
PermutationFree(&b_in_perm);
for (size_t i = 0; i < a_in; i++) {
PermutationFree(a_out_perms + i);
}
free(a_out_perms);
for (size_t i = 0; i < b_in; i++) {
PermutationFree(b_out_perms + i);
}
free(b_out_perms);
MatrixFree(&matrix);
return EXIT_SUCCESS;
}