Blame view

src/csps/steiner.c 2.55 KB
94b2b13d   Pedro Roque   PHACT source
1
2
3
4
/*
 * steiner_triples.c
 *
 *  Created on: 26/03/2017
4d26a735   Pedro Roque   Increased recogni...
5
 *      Author: pedro
94b2b13d   Pedro Roque   PHACT source
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 *      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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "../config.h"
#include "../constraints/at_most_one.h"
4d26a735   Pedro Roque   Increased recogni...
23
24
25
#include "../constraints/le.h"
#include "../constraints/linear_var.h"
#include "../constraints/lt.h"
94b2b13d   Pedro Roque   PHACT source
26
27
28
29
30
31
#include "../split.h"
#include "../variables.h"

/*
 * Solve an instance of Steiner Triples problems with N numbers
 */
4d26a735   Pedro Roque   Increased recogni...
32
void run_steiner(int* csp_dims) {
94b2b13d   Pedro Roque   PHACT source
33
34
35
	int n = csp_dims[0];
	unsigned long result;
	int n_triples = (n * (n - 1)) / 6;
4d26a735   Pedro Roque   Increased recogni...
36
37
38
39
	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));
94b2b13d   Pedro Roque   PHACT source
40
41
42
	int i;

	for (i = 0; i < n_triples * 3; i++) {
4d26a735   Pedro Roque   Increased recogni...
43
		triples[i] = v_new_range(0, (unsigned int)n - 1, true);
94b2b13d   Pedro Roque   PHACT source
44
45
46
47
48
49
	}

	for (i = 0; i < n_triples; i++) {
		cards[i] = 3;
	}

4d26a735   Pedro Roque   Increased recogni...
50
	c_at_most_one(triples, cards, (unsigned int)n_triples);
94b2b13d   Pedro Roque   PHACT source
51
52

	for (i = 0; i < n_triples; i++) {
4d26a735   Pedro Roque   Increased recogni...
53
54
55
		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]);
94b2b13d   Pedro Roque   PHACT source
56

4d26a735   Pedro Roque   Increased recogni...
57
58
59
		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]);
94b2b13d   Pedro Roque   PHACT source
60
	}
4d26a735   Pedro Roque   Increased recogni...
61

94b2b13d   Pedro Roque   PHACT source
62
63
64
65
	// Symmetry breaking
	for (i = 1; i < n_triples; i++) {
		c_le(sum_vs_id[i - 1], sum_vs_id[i]);
	}
4d26a735   Pedro Roque   Increased recogni...
66

94b2b13d   Pedro Roque   PHACT source
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	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);
}