https://hal.archives-ouvertes.fr/hal-03445821
Raw File
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;
}
back to top