-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdfs.c
More file actions
130 lines (110 loc) · 3.64 KB
/
dfs.c
File metadata and controls
130 lines (110 loc) · 3.64 KB
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
125
126
127
128
129
130
// This function adds a pointer to a new leaf search-tree node at the front of the frontier.
int add_to_frontier(struct frontier_node *node)
{
if (node == NULL) {
return -1;
}
node->previous = NULL;
node->next = head;
if (head == NULL) {
head = node;
tail = node;
} else {
head->previous = node;
head = node;
}
return 0;
}
// Check whether a vector is a complete assignment and it is also valid.
int solution(struct frontier_node *node)
{
for (int i = 0; i < N; i++) {
if (node->vector[i] == 0) {
return 0;
}
}
return valid(node);
}
// Given a partial assignment vector, for which a subset of the first propositions have values,
// this function pushes up to two new vectors to the frontier, which concern giving to the first unassigned
// proposition the values true=1 and false=-1, after checking that the new vectors are valid.
void generate_children(struct frontier_node *node)
{
int i;
int *vector = node->vector;
// Find the first proposition with no assigned value.
for (i = 0; i < N && vector[i] != 0; i++);
vector[i] = -1;
struct frontier_node *negative = (struct frontier_node*) malloc(sizeof(struct frontier_node));
negative->vector = (int*)malloc(N * sizeof(int));
if (negative == NULL || negative->vector == NULL) {
mem_error = -1;
return;
}
copy(vector, negative->vector);
// Check whether a "false" assignment is acceptable...
if (valid(negative)) {
// ...and pushes it to the frontier.
add_to_frontier(negative);
}
vector[i] = 1;
struct frontier_node *positive = (struct frontier_node*) malloc(sizeof(struct frontier_node));
positive->vector = (int*)malloc(N * sizeof(int));
if (positive == NULL || positive->vector == NULL) {
mem_error = -1;
return;
}
copy(vector, positive->vector);
// Check whether a "true" assignment is acceptable...
if (valid(positive)) {
// ...and pushes it to the frontier.
add_to_frontier(positive);
}
}
// This function implements the searching algorithm we've used,
// checking the frontier head if it's a solution, otherwise creating its
// children and pushes them to the frontier.
struct frontier_node *search()
{
struct frontier_node *current_node;
// Initializing the frontier.
struct frontier_node *root = (struct frontier_node*) malloc(sizeof(struct frontier_node));
root->vector = (int*)malloc(N * sizeof(int));
if (root == NULL || root->vector == NULL) {
mem_error = -1;
return NULL;
}
for (int i = 0; i < N; i++) {
root->vector[i] = 0;
}
generate_children(root);
t1 = clock();
// While the frontier is not empty...
while (head != NULL) {
// Extract the first node from the frontier.
current_node = head;
// If it is a solution return it.
if (solution(current_node)) {
t2 = clock();
return current_node;
}
// Generate its children.
generate_children(current_node);
// Shift frontier head
if (current_node->previous != NULL) {
// Current node is no longer frontier head, so we link
// its previous with its next node.
current_node->previous->next = current_node->next;
} else {
// Node is still frontier head, so we move to next one.
head = current_node->next;
if (head != NULL) {
head->previous = NULL;
}
}
// Free node.
free(current_node);
}
t2 = clock();
return NULL;
}