summaryrefslogtreecommitdiff
path: root/src/instance.c
blob: bb1ac8c8370e3c8f48eb811ca6f27b8c02748344 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

#include "fracture.h"

net_t *create_instance(graph_t *network, double inf, bool voltage_bound,
											 bool startnow, cholmod_common *c) {
	net_t *instance = (net_t *)calloc(1, sizeof(net_t));
	assert(instance != NULL);

	instance->graph = network;
	instance->num_remaining_edges = network->ne;
	instance->fuses = (bool *)calloc(network->ne, sizeof(bool));
	assert(instance->fuses != NULL);
	instance->inf = inf;
	instance->voltage_bound = voltage_bound;
	instance->boundary_cond = CHOL_F(zeros)(
			network->break_dim, 1, CHOLMOD_REAL, c);
	if (network->boundary == TORUS_BOUND) {
		for (unsigned int i = 0; i < network->bound_inds[1]; i++) {
			((double *)instance->boundary_cond->x)[network->bound_verts[i]] = 1;
			((double *)instance->boundary_cond->x)[network->nv + i] = -1;
		}
		((double *)instance->boundary_cond->x)[network->bound_verts[0]] = 1;
	} else if (network->boundary == EMBEDDED_BOUND) {
		// do nothing
		for (unsigned int i = 0; i < network->bound_inds[1]; i++) {
			((double *)instance->boundary_cond->x)[network->bound_verts[i]] =1;
		}
	} else {
		if (voltage_bound) {
			for (unsigned int i = 0; i < network->bound_inds[1]; i++) {
				((double *)instance->boundary_cond->x)[network->bound_verts[i]] =1;
			}
		} else {
			((double *)instance->boundary_cond->x)[0] = 1;
			((double *)instance->boundary_cond->x)[network->nv] = 1;
			((double *)instance->boundary_cond->x)[network->nv + 1] = -1;
		}
	}

	if (network->boundary != TORUS_BOUND) instance->adjacency = gen_adjacency(instance, false, false, 0, c);
	else instance->adjacency = gen_adjacency(instance, true, false, 0, c);

	if (startnow) {
		cholmod_sparse *laplacian = gen_laplacian(instance, c, true);
		instance->factor = CHOL_F(analyze)(laplacian, c);
		CHOL_F(factorize)(laplacian, instance->factor, c);
		CHOL_F(free_sparse)(&laplacian, c);
	}

	instance->marks = (unsigned int *)malloc(
			(instance->graph->break_dim) *
			sizeof(unsigned int));
	instance->dual_marks = (unsigned int *)malloc(
			(instance->graph->dnv) *
			sizeof(unsigned int));
	assert(instance->marks != NULL);

	for (unsigned int i = 0;
			 i < (instance->graph->break_dim);
			 i++) {
		instance->marks[i] = 1;
	}
	for (unsigned int i = 0;
			 i < (instance->graph->dnv);
			 i++) {
		instance->dual_marks[i] = i+1;
	}
	instance->num_components = 1;

	return instance;
}

void finish_instance(net_t *instance, cholmod_common *c) {
	cholmod_sparse *laplacian = gen_laplacian(instance, c, true);
	instance->factor = CHOL_F(analyze)(laplacian, c);
	CHOL_F(factorize)(laplacian, instance->factor, c);
	CHOL_F(free_sparse)(&laplacian, c);
}

net_t *copy_instance(const net_t *instance, cholmod_common *c) {
	net_t *instance_copy = (net_t *)calloc(1, sizeof(net_t));
	memcpy(instance_copy, instance, sizeof(net_t));

	size_t fuses_size = (instance->graph)->ne * sizeof(bool);
	instance_copy->fuses = (bool *)malloc(fuses_size);
	memcpy(instance_copy->fuses, instance->fuses, fuses_size);

	size_t marks_size =
			(instance->graph->break_dim) *
			sizeof(unsigned int);
	instance_copy->marks = (unsigned int *)malloc(marks_size);
	memcpy(instance_copy->marks, instance->marks, marks_size);

	size_t dual_marks_size =
			(instance->graph->dnv) *
			sizeof(unsigned int);
	instance_copy->dual_marks = (unsigned int *)malloc(dual_marks_size);
	memcpy(instance_copy->dual_marks, instance->dual_marks, dual_marks_size);

	instance_copy->adjacency = CHOL_F(copy_sparse)(instance->adjacency, c);
	instance_copy->boundary_cond = CHOL_F(copy_dense)(instance->boundary_cond, c);
	instance_copy->factor = CHOL_F(copy_factor)(instance->factor, c);

	return instance_copy;
}

void free_instance(net_t *instance, cholmod_common *c) {
	free(instance->fuses);
	CHOL_F(free_dense)(&(instance->boundary_cond), c);
	CHOL_F(free_sparse)(&(instance->adjacency), c);
	CHOL_F(free_factor)(&(instance->factor), c);
	free(instance->marks);
	free(instance->dual_marks);
	free(instance);
}

bool check_instance(const net_t *instance, cholmod_common *c) {
	assert(instance != NULL);
	assert(instance->fuses != NULL);
	assert(CHOL_F(check_dense)(instance->boundary_cond, c));
	assert(CHOL_F(check_factor)(instance->factor, c));

	return true;
}