Example #1
0
File: eheap.c Project: MicBosi/GTS
/**
 * gts_eheap_remove:
 * @heap: a #GtsEHeap.
 * @p: a #GtsEHeapPair.
 *
 * Removes element corresponding to @p from @heap in O(log n).
 *
 * Returns: the element just removed from @heap.
 */
gpointer gts_eheap_remove (GtsEHeap * heap, GtsEHeapPair * p)
{
  GtsEHeapPair ** pdata;
  GtsEHeapPair * parent;
  guint i, par;
  gpointer data;

  g_return_val_if_fail (heap != NULL, NULL);
  g_return_val_if_fail (p != NULL, NULL);

  pdata = (GtsEHeapPair **)heap->elts->pdata;
  i = p->pos;
  data = p->data;

  g_return_val_if_fail (i > 0 && i <= heap->elts->len, NULL);
  g_return_val_if_fail (p == pdata[i - 1], NULL);

  /* move element to the top */
  while ((par = PARENT (i))) {
    parent = pdata[par - 1];
    pdata[par - 1] = p;
    pdata[i - 1] = parent;
    p->pos = par;
    parent->pos = i;
    i = par;
  }

  gts_eheap_remove_top (heap, NULL);

  return data;
}
Example #2
0
static void surface_hf_refine (GtsSurface * s,
			       CostFunc cost_func,
			       gpointer cost_data,
			       GtsStopFunc stop_func,
			       gpointer stop_data)
{
  GtsEHeap * heap;
  gdouble top_cost;
  guint nv = 4;
  GtsListFace * f;
  gpointer data[3];

  g_return_if_fail (s != NULL);
  g_return_if_fail (cost_func != NULL);
  g_return_if_fail (stop_func != NULL);

  data[0] = heap = gts_eheap_new (NULL, NULL);
  data[1] = cost_func;
  data[2] = cost_data;
  gts_surface_foreach_face (s, (GtsFunc) list_face_update, data);
  while ((f = gts_eheap_remove_top (heap, &top_cost)) &&
	 !(*stop_func) (- top_cost, nv, stop_data)) {
    GtsVertex * v = LIST_FACE (f)->best;
    GSList * t, * i;

    LIST_FACE (f)->heap = NULL;
    gts_delaunay_add_vertex_to_face (s, v, GTS_FACE (f));
    i = t = gts_vertex_triangles (v, NULL);
    while (i) {
      list_face_update (i->data, data);
      i = i->next;
    }
    g_slist_free (t);
    nv++;
  }

  if (f)
    LIST_FACE (f)->heap = NULL;

  gts_eheap_foreach (heap, (GFunc) list_face_clear_heap, NULL);
  gts_eheap_destroy (heap);
}
Example #3
0
File: optimize.c Project: bert/gts
static void surface_optimize (GtsSurface * surface,
                              gdouble max_cost)
{
    GtsEHeap * heap;
    GtsEdge * e;
    gdouble top_cost;

    heap = gts_eheap_new ((GtsKeyFunc) edge_swap_cost, NULL);
    gts_eheap_freeze (heap);
    gts_surface_foreach_edge (surface, (GtsFunc) create_heap_optimize, heap);
    gts_eheap_thaw (heap);

    gts_allow_floating_edges = TRUE;
    while ((e = gts_eheap_remove_top (heap, &top_cost)) &&
            top_cost < max_cost)
        edge_swap (e, surface, heap);
    gts_allow_floating_edges = FALSE;

    if (e) GTS_OBJECT (e)->reserved = NULL;
    gts_eheap_foreach (heap, (GFunc) gts_object_reset_reserved, NULL);

    gts_eheap_destroy (heap);
}
Example #4
0
/**
 * gts_graph_bisection_bkl_refine:
 * @bg: a #GtsGraphBisection.
 * @mmax: the maximum number of unsuccessful successive moves.
 * @imbalance: the maximum relative imbalance allowed between the
 * weights of both halves of the partition.
 *
 * An implementation of the simplified boundary Kernighan-Lin
 * algorithm for graph bisection refinement as described in Karypis
 * and Kumar (1997).
 *
 * The algorithm stops if @mmax consecutive modes do not lead to a
 * decrease in the number of edges cut. This last @mmax moves are
 * undone.
 *
 * Returns: the decrease in the weight of the edges cut by the bisection.  
 */
gdouble gts_graph_bisection_bkl_refine (GtsGraphBisection * bg,
					guint mmax,
					gfloat imbalance)
{
  GtsEHeap * h1, * h2;
  GtsGNode * n;
  guint nm = 0, i;
  GtsGNode ** moves;
  gdouble bestcost = 0., totalcost = 0., best_balance;
  gboolean balanced = FALSE;

  g_return_val_if_fail (bg != NULL, 0.);
  g_return_val_if_fail (mmax > 0, 0.);
  g_return_val_if_fail (imbalance >= 0. && imbalance <= 1., 0.);

  h1 = gts_eheap_new ((GtsKeyFunc) node_move_cost1, bg);
  gts_eheap_freeze (h1);
  g_hash_table_foreach (bg->bg1, (GHFunc) build_bheap, h1);
  gts_eheap_thaw (h1);

  h2 = gts_eheap_new ((GtsKeyFunc) node_move_cost2, bg);
  gts_eheap_freeze (h2);
  g_hash_table_foreach (bg->bg2, (GHFunc) build_bheap, h2);
  gts_eheap_thaw (h2);

  moves = g_malloc (sizeof (GtsGNode *)*mmax);
  imbalance *= gts_graph_weight (bg->g);
  best_balance = fabs (gts_graph_weight (bg->g1) - gts_graph_weight (bg->g2));
  if (best_balance <= imbalance)
    balanced = TRUE;

  do {
    GtsGraph * g1, * g2;
    GHashTable * bg1, * bg2;
    gdouble cost;

    if (gts_graph_weight (bg->g1) > gts_graph_weight (bg->g2)) {
      n = gts_eheap_remove_top (h1, &cost);
      g1 = bg->g1;
      g2 = bg->g2;
      bg1 = bg->bg1;
      bg2 = bg->bg2;
    }
    else {
      n = gts_eheap_remove_top (h2, &cost);
      g1 = bg->g2;
      g2 = bg->g1;
      bg1 = bg->bg2;
      bg2 = bg->bg1;
    }
    if (n) {
      gdouble balance;
	
      GTS_OBJECT (n)->reserved = n;
      gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n));
      gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n));
      g_hash_table_remove (bg1, n);
      if (gts_gnode_degree (n, g1))
	g_hash_table_insert (bg2, n, n);

      update_neighbors (n, bg, h1, h2);

      totalcost += cost;
      balance = fabs (gts_graph_weight (g1) - gts_graph_weight (g2));
      
      if (!balanced && balance <= imbalance) {
	bestcost = totalcost;
	best_balance = balance;
	balanced = TRUE;
	nm = 0;
      }
      else if (totalcost < bestcost && 
	       (balance < best_balance || balance <= imbalance)) {
	bestcost = totalcost;
	best_balance = balance;
	nm = 0;
      }
      else if (totalcost == bestcost && balance < best_balance) {
	best_balance = balance;
	nm = 0;
      }
      else
	moves[nm++] = n;
    }
  } while (n && nm < mmax);

  gts_container_foreach (GTS_CONTAINER (bg->g), 
			 (GtsFunc) gts_object_reset_reserved, NULL);
  gts_eheap_destroy (h1);
  gts_eheap_destroy (h2);

  /* undo last nm moves */
  for (i = 0; i < nm; i++) {
    GtsGNode * n = moves[i];
    GtsGraph * g1, * g2;
    GHashTable * bg1, * bg2;

    if (gts_containee_is_contained (GTS_CONTAINEE (n),
				    GTS_CONTAINER (bg->g1))) {
      g1 = bg->g1;
      g2 = bg->g2;
      bg1 = bg->bg1;
      bg2 = bg->bg2;
    }
    else {
      g1 = bg->g2;
      g2 = bg->g1;
      bg1 = bg->bg2;
      bg2 = bg->bg1;
    }
    
    gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n));
    gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n));
    g_hash_table_remove (bg1, n);
    if (gts_gnode_degree (n, g1))
      g_hash_table_insert (bg2, n, n);

    update_neighbors (n, bg, NULL, NULL);
  }
  g_free (moves);

  return bestcost;
}
Example #5
0
/**
 * gts_graph_bisection_kl_refine:
 * @bg: a #GtsGraphBisection.
 * @mmax: the maximum number of unsuccessful successive moves.
 *
 * An implementation of the simplified Kernighan-Lin algorithm for
 * graph bisection refinement as described in Karypis and Kumar
 * (1997).
 *
 * The algorithm stops if @mmax consecutive modes do not lead to a
 * decrease in the number of edges cut. This last @mmax moves are
 * undone.
 *
 * Returns: the decrease in the weight of the edges cut by the bisection.  
 */
gdouble gts_graph_bisection_kl_refine (GtsGraphBisection * bg,
				       guint mmax)
{
  GtsEHeap * h1, * h2;
  GtsGNode * n;
  guint nm = 0, i;
  GtsGNode ** moves;
  gdouble bestcost = 0., totalcost = 0., best_balance;

  g_return_val_if_fail (bg != NULL, 0.);
  g_return_val_if_fail (mmax > 0, 0.);

  h1 = gts_eheap_new ((GtsKeyFunc) node_move_cost1, bg);
  gts_eheap_freeze (h1);
  gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) build_heap, h1);
  gts_eheap_thaw (h1);

  h2 = gts_eheap_new ((GtsKeyFunc) node_move_cost2, bg);
  gts_eheap_freeze (h2);
  gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) build_heap, h2);
  gts_eheap_thaw (h2);

  moves = g_malloc (sizeof (GtsGNode *)*mmax);
  best_balance = fabs (gts_graph_weight (bg->g1) - gts_graph_weight (bg->g2));

  do {
    GtsGraph * g1, * g2;
    gdouble cost;

    if (gts_graph_weight (bg->g1) > gts_graph_weight (bg->g2)) {
      n = gts_eheap_remove_top (h1, &cost);
      g1 = bg->g1;
      g2 = bg->g2;
    }
    else {
      n = gts_eheap_remove_top (h2, &cost);
      g1 = bg->g2;
      g2 = bg->g1;
    }
    if (n) {
      GSList * i;

      GTS_OBJECT (n)->reserved = NULL;
      gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n));
      gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n));

      totalcost += cost;
      if (totalcost < bestcost) {
	bestcost = totalcost;
	nm = 0;
      }
      else if (totalcost == bestcost) {
	gdouble balance = fabs (gts_graph_weight (g1) - gts_graph_weight (g2));

	if (balance < best_balance) {
	  best_balance = balance;
	  nm = 0;
	}
      }	       
      else
	moves[nm++] = n;

      i = GTS_SLIST_CONTAINER (n)->items;
      while (i) {
	GtsGNode * n1 = GTS_GNODE_NEIGHBOR (n, i->data);
	if (GTS_OBJECT (n1)->reserved && 
	    gts_containee_is_contained (GTS_CONTAINEE (n1), 
					GTS_CONTAINER (bg->g))) {
	  GtsEHeap * h = 
	    gts_containee_is_contained (GTS_CONTAINEE (n1), 
					GTS_CONTAINER (bg->g1)) ? h1 : h2;
	  gts_eheap_remove (h, GTS_OBJECT (n1)->reserved);
	  GTS_OBJECT (n1)->reserved = gts_eheap_insert (h, n1);
	}
	i = i->next;
      }
    }
  } while (n && nm < mmax);

  gts_eheap_foreach (h1, (GFunc) gts_object_reset_reserved, NULL);
  gts_eheap_foreach (h2, (GFunc) gts_object_reset_reserved, NULL);
  gts_eheap_destroy (h1);
  gts_eheap_destroy (h2);

  /* undo last nm moves */
  for (i = 0; i < nm; i++) {
    GtsGNode * n = moves[i];
    GtsGraph * g1 = 
      gts_containee_is_contained (GTS_CONTAINEE (n),
				  GTS_CONTAINER (bg->g1)) ? bg->g1 : bg->g2;
    GtsGraph * g2 = g1 == bg->g1 ? bg->g2 : bg->g1;
    
    gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n));
    gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n));
  }
  g_free (moves);

  return bestcost;
}
Example #6
0
/**
 * gts_graph_bfgg_bisection:
 * @g: a #GtsGraph.
 * @ntry: the number of randomly selected initial seeds.
 *
 * An implementation of a "Breadth-First Graph Growing" algorithm.
 *
 * @ntry randomly chosen seeds are used and the best partition is retained.
 *
 * Returns: a new #GtsGraphBisection of @g.
 */
GtsGraphBisection * gts_graph_bfgg_bisection (GtsGraph * g, guint ntry)
{
  gfloat size, bestcost = G_MAXFLOAT, smin;
  GtsGraph * bestg1 = NULL, * bestg2 = NULL;
  GtsEHeap * degree_heap;
  GtsGNode * seed;
  GtsGraphBisection * bg;

  g_return_val_if_fail (g != NULL, NULL);

  bg = g_malloc (sizeof (GtsGraphBisection));
  bg->g = g;

  size = gts_graph_weight (g)/2.;
  smin = 0.9*size;

  degree_heap = gts_eheap_new ((GtsKeyFunc) degree_cost, g);
  gts_eheap_freeze (degree_heap);
  gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_seed, degree_heap);
  gts_eheap_thaw (degree_heap);

  while (ntry && ((seed = gts_eheap_remove_top (degree_heap, NULL)))) {
    GtsGraph * g1, * g2;
    GtsGNode * n;
    gdouble cost;
    GtsGraphTraverse * t = gts_graph_traverse_new (g, seed, 
						   GTS_BREADTH_FIRST, TRUE);
    
    g1 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass),
			g->node_class, g->edge_class);
    g2 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass),
			g->node_class, g->edge_class);

    while ((n = gts_graph_traverse_next (t)))
      if (gts_graph_weight (g1) + gts_gnode_weight (n) <= size) {
	gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (n));
	GTS_OBJECT (n)->reserved = n;
      }
    gts_graph_traverse_destroy (t);
    
    gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_unused, g2);

    cost = gts_graph_edges_cut_weight (g1);
    if (!bestg1 || (cost < bestcost && gts_graph_weight (g1) >= smin)) {
      if (bestg1)
	bestcost = cost;
      if (bestg1)
	gts_object_destroy (GTS_OBJECT (bestg1));
      if (bestg2)
	gts_object_destroy (GTS_OBJECT (bestg2));
      bestg1 = g1;
      bestg2 = g2;
    }
    else {
      gts_object_destroy (GTS_OBJECT (g1));
      gts_object_destroy (GTS_OBJECT (g2));
    }

    ntry--;
  }
  gts_eheap_destroy (degree_heap);

#ifdef DEBUG
  fprintf (stderr, "bestcost: %5g g1: %5g|%5d g2: %5g|%5d\n",
	   bestcost, 
	   gts_graph_weight (bestg1), 
	   gts_container_size (GTS_CONTAINER (bestg1)),
	   gts_graph_weight (bestg2), 
	   gts_container_size (GTS_CONTAINER (bestg2)));
#endif

  bg->g1 = bestg1;
  bg->g2 = bestg2;
  
  /* boundary nodes */
  bg->bg1 = g_hash_table_new (NULL, NULL);
  gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) boundary_node1, bg);
  bg->bg2 = g_hash_table_new (NULL, NULL);
  gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) boundary_node2, bg);

  return bg;
}
Example #7
0
/**
 * gts_graph_ggg_bisection:
 * @g: a #GtsGraph.
 * @ntry: the number of randomly selected initial seeds.
 *
 * An implementation of the "Greedy Graph Growing" algorithm of
 * Karypis and Kumar (1997).  
 *
 * @ntry randomly chosen seeds are used and the best partition is retained.
 *
 * Returns: a new #GtsGraphBisection of @g.
 */
GtsGraphBisection * gts_graph_ggg_bisection (GtsGraph * g, guint ntry)
{
  gfloat size, bestcost = G_MAXFLOAT, smin;
  GtsGraph * bestg1 = NULL, * bestg2 = NULL;
  gboolean balanced = FALSE;
  GtsEHeap * degree_heap;
  GtsGNode * seed;
  GtsGraphBisection * bg;

  g_return_val_if_fail (g != NULL, NULL);

  bg = g_malloc (sizeof (GtsGraphBisection));
  bg->g = g;

  size = gts_graph_weight (g)/2.;
  smin = 0.9*size;

  degree_heap = gts_eheap_new ((GtsKeyFunc) degree_cost, g);
  gts_eheap_freeze (degree_heap);
  gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_seed, degree_heap);
  gts_eheap_thaw (degree_heap);

  while (ntry && ((seed = gts_eheap_remove_top (degree_heap, NULL)))) {
    GtsGraph * g1, * g2;
    GtsGNode * n;
    gdouble cost;
    gpointer data[2];
    GtsEHeap * heap;
  
    g1 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass),
			g->node_class, g->edge_class);
    g2 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass),
			g->node_class, g->edge_class);
    
    data[0] = g;
    data[1] = g1;
    heap = gts_eheap_new ((GtsKeyFunc) node_cost, data);

    gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (seed));
    GTS_OBJECT (seed)->reserved = seed;
    gts_gnode_foreach_neighbor (seed, g, (GtsFunc) add_neighbor, heap);

    while ((n = gts_eheap_remove_top (heap, &cost)))
      if (gts_graph_weight (g1) + gts_gnode_weight (n) <= size) {
	gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (n));
	GTS_OBJECT (n)->reserved = n;
	gts_gnode_foreach_neighbor (n, g, (GtsFunc) add_neighbor, heap);
      }
      else
	GTS_OBJECT (n)->reserved = NULL;
    gts_eheap_destroy (heap);
    
    gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_unused, g2);

    cost = gts_graph_edges_cut_weight (g1);
    if (!bestg1 || 
	(!balanced && gts_graph_weight (g1) >= smin) ||
	(cost < bestcost && gts_graph_weight (g1) >= smin)) {
      if (bestg1)
	bestcost = cost;
      if (bestg1)
	gts_object_destroy (GTS_OBJECT (bestg1));
      if (bestg2)
	gts_object_destroy (GTS_OBJECT (bestg2));
      bestg1 = g1;
      bestg2 = g2;
      if (gts_graph_weight (g1) >= smin)
	balanced = TRUE;
    }
    else {
      gts_object_destroy (GTS_OBJECT (g1));
      gts_object_destroy (GTS_OBJECT (g2));
    }

    ntry--;
  }
  gts_eheap_destroy (degree_heap);

#ifdef DEBUG
  fprintf (stderr, "bestcost: %5g g1: %5g|%5d g2: %5g|%5d\n",
	   bestcost, 
	   gts_graph_weight (bestg1), 
	   gts_container_size (GTS_CONTAINER (bestg1)),
	   gts_graph_weight (bestg2), 
	   gts_container_size (GTS_CONTAINER (bestg2)));
#endif

  g_assert (bestg1 != NULL);
  bg->g1 = bestg1;
  g_assert (bestg2 != NULL);
  bg->g2 = bestg2;
  
  /* boundary nodes */
  bg->bg1 = g_hash_table_new (NULL, NULL);
  gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) boundary_node1, bg);
  bg->bg2 = g_hash_table_new (NULL, NULL);
  gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) boundary_node2, bg);

  return bg;
}