From: yu.dongliang <18588496441@163.com>
Date: Wed, 1 Nov 2023 06:15:25 +0000 (+0800)
Subject: ses_cross_graph.c
X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=6f6467f0aa74795412f623d5efd4a975b028fdea;p=ses.git

ses_cross_graph.c
---

diff --git a/Makefile b/Makefile
index bc29d85..4405e05 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,7 @@ CFILES += main.c
 CFILES += scf_eda.pb-c.c
 CFILES += scf_eda_pb.c
 CFILES += ses_layout.c
+CFILES += ses_cross_graph.c
 CFILES += ses_utils.c
 
 CFILES += ses_steps.c
diff --git a/ses_core.h b/ses_core.h
index 300e8a1..539c21b 100644
--- a/ses_core.h
+++ b/ses_core.h
@@ -16,6 +16,7 @@ struct ses_edge_s
 	ScfEcomponent* c;
 
 	scf_vector_t*  crosses;
+	intptr_t       color;
 };
 
 struct ses_flow_s
diff --git a/ses_cross_graph.c b/ses_cross_graph.c
new file mode 100644
index 0000000..c12690f
--- /dev/null
+++ b/ses_cross_graph.c
@@ -0,0 +1,398 @@
+#include"ses_core.h"
+
+static intptr_t __cross_color_select(ses_edge_t* edge, scf_vector_t* colors)
+{
+	ses_edge_t* cross;
+
+	int i;
+	int j;
+
+	for (i = 0; i < colors->size; ) {
+
+		intptr_t c = (intptr_t)(colors->data[i]);
+
+		for (j = 0; j < edge->crosses->size; j++) {
+			cross     = edge->crosses->data[j];
+
+			if (c == cross->color)
+				goto next;
+		}
+
+		return c;
+next:
+		i++;
+	}
+
+	return 0;
+}
+
+static int __cross_color_del(scf_vector_t* colors, intptr_t color)
+{
+	return scf_vector_del(colors, (void*)color);
+}
+
+static int __cross_kcolor_check(scf_vector_t* graph)
+{
+	ses_edge_t* edge;
+
+	int i;
+	for (i = 0; i < graph->size; i++) {
+		edge      = graph->data[i];
+
+		if (0 == edge->color)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int __cross_graph_add(scf_vector_t* graph, ses_edge_t* edge)
+{
+	ses_edge_t* cross;
+
+	int i;
+
+	for (i = 0; i < edge->crosses->size; i++) {
+		cross     = edge->crosses->data[i];
+
+		if (scf_vector_find(graph, cross)) {
+
+			int ret = scf_vector_add_unique(cross->crosses, edge);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return scf_vector_add(graph, edge);
+}
+
+static int __cross_graph_del(scf_vector_t* graph, ses_edge_t* edge)
+{
+	ses_edge_t* cross;
+
+	int i;
+
+	for (i = 0; i < edge->crosses->size; i++) {
+		cross     = edge->crosses->data[i];
+
+		scf_vector_del(cross->crosses, edge);
+	}
+
+	return scf_vector_del(graph, edge);
+}
+
+static int __cross_kcolor_delete(scf_vector_t* graph, int k, scf_vector_t* deleted)
+{
+	ses_edge_t* edge;
+
+	while (graph->size > 0) {
+
+		int n_deleted = 0;
+		int i = 0;
+
+		while (i < graph->size) {
+			edge = graph->data[i];
+
+			scf_logd("graph->size: %d, crosses: %d, k: %d, edge: %p\n",
+					graph->size, edge->crosses->size, k, edge);
+
+			if (edge->crosses->size >= k) {
+				i++;
+				continue;
+			}
+
+			if (0 != __cross_graph_del(graph, edge)) {
+				scf_loge("\n");
+				return -1;
+			}
+
+			if (0 != scf_vector_add(deleted, edge)) {
+				scf_loge("\n");
+				return -1;
+			}
+
+			n_deleted++;
+		}
+
+		if (0 == n_deleted)
+			break;
+	}
+
+	return 0;
+}
+
+static int __cross_kcolor_fill(scf_vector_t* graph, int k, scf_vector_t* colors, scf_vector_t* deleted)
+{
+	scf_logd("graph->size: %d\n", graph->size);
+
+	scf_vector_t* __colors;
+	ses_edge_t*   edge;
+	ses_edge_t*   cross;
+
+	int i;
+	int j;
+
+	for (i   = deleted->size - 1; i >= 0; i--) {
+		edge = deleted->data[i];
+
+		if (edge->crosses->size >= k);
+
+		__colors = scf_vector_clone(colors);
+		if (!__colors)
+			return -ENOMEM;
+
+		scf_logd("edge: %p, crosses: %d, k: %d\n", edge, edge->crosses->size, k);
+
+		for (j = 0; j < edge->crosses->size; j++) {
+			cross     = edge->crosses->data[j];
+
+			if (cross->color > 0) {
+				int ret = __cross_color_del(__colors, cross->color);
+				if (ret < 0)
+					goto error;
+
+				if (0 != edge->color && edge->color == cross->color) {
+					scf_logd("edge: %p, cross: %p, color: %#lx:%#lx\n", edge, cross, edge->color, cross->color);
+					edge->color = 0;
+				}
+			}
+
+			if (0 != scf_vector_add(cross->crosses, edge))
+				goto error;
+		}
+
+		assert(__colors->size >= 0);
+
+		if (0 == edge->color) {
+			edge->color = __cross_color_select(edge, __colors);
+
+			if (0 == edge->color) {
+				edge->color = -1;
+				scf_logd("__colors->size: %d\n", __colors->size);
+			}
+		}
+
+		if (0 != scf_vector_add(graph, edge))
+			goto error;
+
+		scf_vector_free(__colors);
+		__colors = NULL;
+	}
+
+	return 0;
+
+error:
+	scf_vector_free(__colors);
+	return -1;
+}
+
+static int __cross_kcolor_find_not_neighbor(scf_vector_t* graph, int k, ses_edge_t** pp0, ses_edge_t** pp1)
+{
+	assert(graph->size >= k);
+
+	ses_edge_t* edge0;
+	ses_edge_t* edge1;
+
+	int i;
+	int j;
+
+	for (i = 0; i < graph->size; i++) {
+		edge0     = graph->data[i];
+
+		if (edge0->crosses->size > k)
+			continue;
+
+		edge1 = NULL;
+
+		for (j = i + 1; j < graph->size; j++) {
+			edge1         = graph->data[j];
+
+			if (!scf_vector_find(edge0->crosses, edge1)) {
+				assert(!scf_vector_find(edge1->crosses, edge0));
+				break;
+			}
+
+			edge1 = NULL;
+		}
+
+		if (edge1) {
+			*pp0 = edge0;
+			*pp1 = edge1;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+static ses_edge_t* __cross_max_neighbors(scf_vector_t* graph)
+{
+	ses_edge_t* max  = NULL;
+	ses_edge_t* edge = NULL;
+
+	int n = 0;
+	int i;
+
+	for (i = 0; i < graph->size; i++) {
+		edge      = graph->data[i];
+
+		if (!max || n < edge->crosses->size) {
+			max = edge;
+			n   = edge->crosses->size;
+		}
+	}
+
+	return max;
+}
+
+static void __cross_kcolor_process_conflict(scf_vector_t* graph)
+{
+	ses_edge_t* edge0;
+	ses_edge_t* edge1;
+
+	int i;
+	int j;
+
+	for (i = 0; i < graph->size - 1; i++) {
+		edge0     = graph->data[i];
+
+		if (0 == edge0->color)
+			continue;
+
+		for (j = i + 1; j < graph->size; j++) {
+
+			edge1 = graph->data[j];
+
+			if (0 == edge1->color)
+				continue;
+
+			if (edge0->color != edge0->color)
+				continue;
+
+			if (edge0->crosses->size > edge1->crosses->size)
+				edge1->color = 0;
+			else
+				edge0->color = 0;
+		}
+	}
+}
+
+static int __cross_graph_kcolor(scf_vector_t* graph, int k, scf_vector_t* colors)
+{
+	scf_vector_t* deleted  = scf_vector_alloc();
+	scf_vector_t* __colors = NULL;
+	ses_edge_t*   edge0    = NULL;
+	ses_edge_t*   edge1    = NULL;
+	ses_edge_t*   max      = NULL;
+
+	if (!deleted)
+		return -ENOMEM;
+
+	scf_logd("graph->size: %d, k: %d\n", graph->size, k);
+
+	int ret = __cross_kcolor_delete(graph, k, deleted);
+	if (ret < 0)
+		goto error;
+
+	if (0  == __cross_kcolor_check(graph)) {
+
+		ret = __cross_kcolor_fill(graph, k, colors, deleted);
+		if (ret < 0)
+			goto error;
+
+		scf_vector_free(deleted);
+		deleted = NULL;
+		return 0;
+	}
+
+	assert(graph->size > 0);
+	assert(graph->size >= k);
+
+	if (0 == __cross_kcolor_find_not_neighbor(graph, k, &edge0, &edge1)) {
+
+		__colors = scf_vector_clone(colors);
+		if (!__colors) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		edge0->color = __cross_color_select(edge0, __colors);
+		if (0 == edge0->color)
+			goto overflow;
+		edge1->color = edge0->color;
+
+		ret = __cross_color_del(__colors, edge0->color);
+		if (ret < 0)
+			goto error;
+		assert(!scf_vector_find(__colors, (void*)edge0->color));
+
+		ret = __cross_graph_del(graph, edge0);
+		if (ret < 0)
+			goto error;
+
+		ret = __cross_graph_del(graph, edge1);
+		if (ret < 0)
+			goto error;
+
+		ret = __cross_graph_kcolor(graph, k - 1, __colors);
+		if (ret < 0)
+			goto error;
+
+		ret = __cross_graph_add(graph, edge0);
+		if (ret < 0)
+			goto error;
+
+		ret = __cross_graph_add(graph, edge1);
+		if (ret < 0)
+			goto error;
+
+		scf_vector_free(__colors);
+		__colors = NULL;
+
+	} else {
+
+overflow:
+		max = __cross_max_neighbors(graph);
+		assert(max);
+
+		ret = __cross_graph_del(graph, max);
+		if (ret < 0)
+			goto error;
+		max->color = -1;
+
+		ret = __cross_graph_kcolor(graph, k, colors);
+		if (ret < 0)
+			goto error;
+
+		ret = __cross_graph_add(graph, max);
+		if (ret < 0)
+			goto error;
+	}
+
+	ret = __cross_kcolor_fill(graph, k, colors, deleted);
+	if (ret < 0)
+		goto error;
+
+	scf_vector_free(deleted);
+	deleted = NULL;
+	return 0;
+
+error:
+	if (__colors)
+		scf_vector_free(__colors);
+
+	scf_vector_free(deleted);
+	return ret;
+}
+
+int ses_cross_graph_kcolor(scf_vector_t* graph, int k, scf_vector_t* colors)
+{
+	if (!graph || !colors || 0 == colors->size) {
+		scf_loge("\n");
+		return -EINVAL;
+	}
+
+	__cross_kcolor_process_conflict(graph);
+
+	return __cross_graph_kcolor(graph, k, colors);
+}