/* * steiner_triples.c * * Created on: 26/03/2017 * Author: pedro * * http://www.csplib.org/Problems/prob044/ * https://github.com/MiniZinc/minizinc-benchmarks/tree/master/steiner-triples * * Steiner Triples: * The following program computes so-called Steiner triplets. These are triplets * of numbers from 1 to n such that any two triplets have at most one element in common. */ #include "steiner.h" #include #include #include #include "../config.h" #include "../constraints/at_most_one.h" #include "../constraints/le.h" #include "../constraints/linear_var.h" #include "../constraints/lt.h" #include "../split.h" #include "../variables.h" /* * Solve an instance of Steiner Triples problems with N numbers */ void run_steiner(int* csp_dims) { int n = csp_dims[0]; unsigned long result; int n_triples = (n * (n - 1)) / 6; unsigned int* sum_vs_id = malloc((unsigned long)n_triples * sizeof(unsigned int)); int cs[] = {(n + 1) * (n + 1), n + 1, 1}; unsigned int* triples = malloc((unsigned long)n_triples * 3 * sizeof(unsigned int)); int* cards = malloc((unsigned long)n_triples * sizeof(int)); int i; for (i = 0; i < n_triples * 3; i++) { triples[i] = v_new_range(0, (unsigned int)n - 1, true); } for (i = 0; i < n_triples; i++) { cards[i] = 3; } c_at_most_one(triples, cards, (unsigned int)n_triples); for (i = 0; i < n_triples; i++) { c_lt(triples[i * 3], triples[i * 3 + 1]); c_lt(triples[i * 3], triples[i * 3 + 2]); c_lt(triples[i * 3 + 1], triples[i * 3 + 2]); sum_vs_id[i] = v_new_range(0, ((unsigned int)n + 1) * ((unsigned int)n + 1) * (unsigned int)n + ((unsigned int)n + 1) * ((unsigned int)n - 1) + (unsigned int)n - 2, false); c_linear_var(cs, &triples[i * 3], 3, sum_vs_id[i]); } // Symmetry breaking for (i = 1; i < n_triples; i++) { c_le(sum_vs_id[i - 1], sum_vs_id[i]); } if (FINDING_ONE_SOLUTION) { printf("\nFinding one solution for Steiner Triples with N=%u.\n", n); } else { printf("\nCounting all the solutions for Steiner Triples with N=%u.\n", n); } // Solve the CSP result = solve_CSP(); if (FINDING_ONE_SOLUTION && result == 1) { printf("Solution:\n"); printf("{%u,%u,%u}", v_get_min(triples[0]) + 1, v_get_min(triples[1]) + 1, v_get_min(triples[2]) + 1); for (i = 1; i < n_triples; i++) { printf(",{%u,%u,%u}", v_get_min(triples[i * 3]) + 1, v_get_min(triples[i * 3 + 1]) + 1, v_get_min(triples[i * 3 + 2]) + 1); } printf("\n"); } else { printf("%lu solution(s) found\n", result); } free(triples); free(cards); free(sum_vs_id); }