https://hal.archives-ouvertes.fr/hal-03445821
dvk.c
/*
Copyright Universite de Versailles Saint-Quentin en Yvelines 2009
AUTHORS: Sebastien Briais, Sid Touati
This file is part of RS.
RS is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
RS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with RS. If not, see
<http://www.gnu.org/licenses/>.
*/
#include <SCEDA/common.h>
#include <SCEDA/graph_antichain.h>
#include <SCEDA/graph_dag.h>
#include "dvk.h"
#include "extk.h"
/** Compute DV_k(G), the disjoint values DAG.
@param[in] ddg = GDD_DAG
@param[in] type = type of values
@param[in] pkg = potential killers graph
@param[in] killing_map = killing function
@return the disjoint value DAG.
Vertices are labelled with vertex of the underlying DAG.
Edges are not labelled. */
SCEDA_Graph *RS_ddag_dvk(GDD_DAG *ddg, const char *type, SCEDA_Graph *pkg, SCEDA_HashMap *killing_map) {
SCEDA_Graph *dvk_g = SCEDA_graph_create(NULL, NULL);
SCEDA_Graph *g = GDD_dag_get_ddg(ddg);
SCEDA_HashMap *g_to_dvkg = SCEDA_vertex_map_create(NULL);
{
SCEDA_VerticesIterator g_vertice;
SCEDA_vertices_iterator_init(g, &g_vertice);
while(SCEDA_vertices_iterator_has_next(&g_vertice)) {
SCEDA_Vertex *v = SCEDA_vertices_iterator_next(&g_vertice);
if(GDD_vertex_is_value_of_type(v, type)) {
SCEDA_Vertex *dvv = SCEDA_graph_add_vertex(dvk_g, v);
SCEDA_hashmap_put(g_to_dvkg, v, dvv, NULL);
}
}
SCEDA_vertices_iterator_cleanup(&g_vertice);
}
SCEDA_Graph *g_extk = RS_ddag_extk_order(ddg, type, pkg, killing_map);
SCEDA_Graph *g_extk_closure = SCEDA_graph_transitive_closure(g_extk);
SCEDA_HashMap *g_to_g_extk_closure = SCEDA_vertex_map_create(NULL);
{
SCEDA_VerticesIterator vertices;
SCEDA_vertices_iterator_init(g_extk_closure, &vertices);
while(SCEDA_vertices_iterator_has_next(&vertices)) {
SCEDA_Vertex *v_extk_closure = SCEDA_vertices_iterator_next(&vertices);
SCEDA_Vertex *v_extk = SCEDA_vertex_get_data(SCEDA_Vertex *, v_extk_closure);
SCEDA_Vertex *v = SCEDA_vertex_get_data(SCEDA_Vertex *, v_extk);
SCEDA_hashmap_put(g_to_g_extk_closure, v, v_extk_closure, NULL);
}
SCEDA_vertices_iterator_cleanup(&vertices);
}
{
SCEDA_HashMapIterator killers;
SCEDA_hashmap_iterator_init(killing_map, &killers);
while(SCEDA_hashmap_iterator_has_next(&killers)) {
SCEDA_Vertex *u;
SCEDA_Vertex *ku = SCEDA_hashmap_iterator_next(&killers, &u);
SCEDA_Vertex *dvu = SCEDA_hashmap_get(g_to_dvkg, u);
SCEDA_Vertex *ku_extk_closure = SCEDA_hashmap_get(g_to_g_extk_closure, ku);
SCEDA_VertexSuccIterator desc;
SCEDA_vertex_succ_iterator_init(ku_extk_closure, &desc);
while(SCEDA_vertex_succ_iterator_has_next(&desc)) {
SCEDA_Vertex *v_extk_closure = SCEDA_vertex_succ_iterator_next(&desc);
SCEDA_Vertex *v_extk = SCEDA_vertex_get_data(SCEDA_Vertex *, v_extk_closure);
SCEDA_Vertex *v = SCEDA_vertex_get_data(SCEDA_Vertex *, v_extk);
if(GDD_vertex_is_value_of_type(v, type)) {
SCEDA_Vertex *dvv = SCEDA_hashmap_get(g_to_dvkg, v);
SCEDA_graph_add_edge(dvk_g, dvu, dvv, NULL);
}
}
SCEDA_vertex_succ_iterator_cleanup(&desc);
if(GDD_vertex_is_value_of_type(ku, type)) {
SCEDA_Vertex *dvku = SCEDA_hashmap_get(g_to_dvkg, ku);
SCEDA_graph_add_edge(dvk_g, dvu, dvku, NULL);
}
}
SCEDA_hashmap_iterator_cleanup(&killers);
}
SCEDA_hashmap_delete(g_to_g_extk_closure);
SCEDA_graph_delete(g_extk_closure);
SCEDA_graph_delete(g_extk);
SCEDA_hashmap_delete(g_to_dvkg);
return dvk_g;
}
/** Compute the disjoint values DAG */
/* Bugged version since it does not use G_k but G */
/* But it is really fast ! */
static SCEDA_Graph *RS_ddag_dvk_buggy(GDD_DAG *ddg, const char *type, SCEDA_HashMap *killing_map) {
SCEDA_Graph *dvk_g = SCEDA_graph_create(NULL, NULL);
SCEDA_Graph *g = GDD_dag_get_ddg(ddg);
SCEDA_HashMap *g_to_dvkg = SCEDA_vertex_map_create(NULL);
SCEDA_VerticesIterator g_vertice;
SCEDA_vertices_iterator_init(g, &g_vertice);
while(SCEDA_vertices_iterator_has_next(&g_vertice)) {
SCEDA_Vertex *v = SCEDA_vertices_iterator_next(&g_vertice);
if(GDD_vertex_is_value_of_type(v, type)) {
SCEDA_Vertex *dvv = SCEDA_graph_add_vertex(dvk_g, v);
SCEDA_hashmap_put(g_to_dvkg, v, dvv, NULL);
}
}
SCEDA_vertices_iterator_cleanup(&g_vertice);
SCEDA_HashMapIterator vertice;
SCEDA_hashmap_iterator_init(g_to_dvkg, &vertice);
while(SCEDA_hashmap_iterator_has_next(&vertice)) {
SCEDA_Vertex *u;
SCEDA_Vertex *dvu = SCEDA_hashmap_iterator_next(&vertice, &u);
SCEDA_Vertex *ku = SCEDA_hashmap_get(killing_map, u);
if(ku == NULL) {
continue;
}
GDD_DAG_UpsetIterator desc;
GDD_dag_upset_iterator_init(ddg, ku, &desc);
while(GDD_dag_upset_iterator_has_next(&desc)) {
SCEDA_Vertex *v = GDD_dag_upset_iterator_next(&desc);
if(GDD_vertex_is_value_of_type(v, type)) {
SCEDA_Vertex *dvv = SCEDA_hashmap_get(g_to_dvkg, v);
SCEDA_graph_add_edge(dvk_g, dvu, dvv, NULL);
}
}
GDD_dag_upset_iterator_cleanup(&desc);
if(GDD_vertex_is_value_of_type(ku, type)) {
SCEDA_Vertex *dvku = SCEDA_hashmap_get(g_to_dvkg, ku);
SCEDA_graph_add_edge(dvk_g, dvu, dvku, NULL);
}
}
SCEDA_hashmap_iterator_cleanup(&vertice);
SCEDA_hashmap_delete(g_to_dvkg);
return dvk_g;
}
/** Compute a maximal antichain in the disjoint value DAG
@param[in] ddg = GDD_DAG
@param[in] dvk = disjoint value DAG
@return a list of vertices of the ddg which is a maximal antichain
of dvk */
SCEDA_List *RS_ddag_amk(GDD_DAG *ddg, SCEDA_Graph *dvk) {
SCEDA_List *dv_antichain = SCEDA_graph_maximum_antichain(dvk);
SCEDA_List *antichain = SCEDA_list_create(NULL);
SCEDA_ListIterator dv_vertice;
SCEDA_list_iterator_init(dv_antichain, &dv_vertice);
while(SCEDA_list_iterator_has_next(&dv_vertice)) {
SCEDA_Vertex *dv = SCEDA_list_iterator_next(&dv_vertice);
SCEDA_Vertex *v = SCEDA_vertex_get_data(SCEDA_Vertex *, dv);
SCEDA_list_ins_next(antichain, NULL, v);
}
SCEDA_list_iterator_cleanup(&dv_vertice);
SCEDA_list_delete(dv_antichain);
return antichain;
}
/** Compute a list of saturating values of given type, when using the
given killing function.
@param[in] ddg = GDD_DAG
@param[in] type = type of values
@param[in] pkg = potential killers graph
@param[in] killing_map = killing function
@return a list of saturating values */
SCEDA_List *RS_ddag_saturating_values(GDD_DAG *ddg, const char *type, SCEDA_Graph *pkg, SCEDA_HashMap *killing_map) {
SCEDA_Graph *dvk;
/* if(fast) { */
/* dvk = RS_ddag_dvk_buggy(ddg, type, killing_map); */
/* } else { */
dvk = RS_ddag_dvk(ddg, type, pkg, killing_map);
/* } */
SCEDA_List *amk = RS_ddag_amk(ddg, dvk);
SCEDA_graph_delete(dvk);
return amk;
}
/** Compute the register need of given type, according to the given
killing function.
@param[in] ddg = GDD_DAG
@param[in] type = type of values
@param[in] pkg = potential killers graph
@param[in] killing_map = killing function
@param[in] fast = TRUE to use fast version, FALSE to use precise one
@return the register need */
int RS_ddag_register_need(GDD_DAG *ddg, const char *type, SCEDA_Graph *pkg, SCEDA_HashMap *killing_map, int fast) {
SCEDA_Graph *dvk;
if(fast) {
dvk = RS_ddag_dvk_buggy(ddg, type, killing_map);
} else {
dvk = RS_ddag_dvk(ddg, type, pkg, killing_map);
}
int n = SCEDA_graph_width(dvk);
SCEDA_graph_delete(dvk);
return n;
}