123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- /* graph.cpp */
- /*
- Copyright 2001 Vladimir Kolmogorov (vnk@cs.cornell.edu), Yuri Boykov (yuri@csd.uwo.ca).
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program 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 General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <stdio.h>
- #include <iostream>
- #include "graph.h"
- using namespace OBJREC;
- Graph::Graph(void (*err_function)(char *))
- {
- error_function = err_function;
- node_block_first = NULL;
- arc_for_block_first = NULL;
- arc_rev_block_first = NULL;
- flow = 0;
- }
- Graph::~Graph()
- {
- while (node_block_first)
- {
- node_block *next = node_block_first -> next;
- delete node_block_first;
- node_block_first = next;
- }
- while (arc_for_block_first)
- {
- arc_for_block *next = arc_for_block_first -> next;
- delete [] arc_for_block_first -> start;
- arc_for_block_first = next;
- }
- while (arc_rev_block_first)
- {
- arc_rev_block *next = arc_rev_block_first -> next;
- delete [] arc_rev_block_first -> start;
- arc_rev_block_first = next;
- }
- }
- Graph::node_id Graph::add_node()
- {
- node *i;
- if (!node_block_first || node_block_first->current + 1 > &node_block_first->nodes[NODE_BLOCK_SIZE-1])
- {
- node_block *next = node_block_first;
- node_block_first = (node_block *) new node_block;
- if (!node_block_first) {
- if (error_function) (*error_function)("Not enough memory!");
- exit(1);
- }
- node_block_first -> current = & ( node_block_first -> nodes[0] );
- node_block_first -> next = next;
- }
- i = node_block_first -> current ++;
- i -> first_out = (arc_forward *) 0;
- i -> first_in = (arc_reverse *) 0;
- i -> tr_cap = 0;
- return (node_id) i;
- }
- void Graph::add_edge(node_id from, node_id to, captype cap, captype rev_cap)
- {
- arc_forward *a_for;
- arc_reverse *a_rev;
- if (!arc_for_block_first || arc_for_block_first->current + 1 > &arc_for_block_first->arcs_for[ARC_BLOCK_SIZE])
- {
- arc_for_block *next = arc_for_block_first;
- char *ptr = new char[sizeof(arc_for_block)+1];
- if (!ptr) {
- if (error_function) (*error_function)("Not enough memory!");
- exit(1);
- }
- if ((PTR_CAST)ptr & 1) arc_for_block_first = (arc_for_block *) (ptr + 1);
- else arc_for_block_first = (arc_for_block *) ptr;
- arc_for_block_first -> start = ptr;
- arc_for_block_first -> current = & ( arc_for_block_first -> arcs_for[0] );
- arc_for_block_first -> next = next;
- }
- if (!arc_rev_block_first || arc_rev_block_first->current + 1 > &arc_rev_block_first->arcs_rev[ARC_BLOCK_SIZE])
- {
- arc_rev_block *next = arc_rev_block_first;
- char *ptr = new char[sizeof(arc_rev_block)+1];
- if (!ptr) {
- if (error_function) (*error_function)("Not enough memory!");
- exit(1);
- }
- if ((PTR_CAST)ptr & 1) arc_rev_block_first = (arc_rev_block *) (ptr + 1);
- else arc_rev_block_first = (arc_rev_block *) ptr;
- arc_rev_block_first -> start = ptr;
- arc_rev_block_first -> current = & ( arc_rev_block_first -> arcs_rev[0] );
- arc_rev_block_first -> next = next;
- }
- a_for = arc_for_block_first -> current ++;
- a_rev = arc_rev_block_first -> current ++;
- a_rev -> sister = (arc_forward *) from;
- a_for -> shift = (PTR_CAST) to;
- a_for -> r_cap = cap;
- a_for -> r_rev_cap = rev_cap;
- ((node *)from) -> first_out =
- (arc_forward *) ((PTR_CAST)(((node *)from) -> first_out) + 1);
- ((node *)to) -> first_in =
- (arc_reverse *) ((PTR_CAST)(((node *)to) -> first_in) + 1);
- }
- void Graph::set_tweights(node_id i, captype cap_source, captype cap_sink)
- {
- flow += (cap_source < cap_sink) ? cap_source : cap_sink;
- ((node*)i) -> tr_cap = cap_source - cap_sink;
- }
- void Graph::add_tweights(node_id i, captype cap_source, captype cap_sink)
- {
- register captype delta = ((node*)i) -> tr_cap;
- if (delta > 0) cap_source += delta;
- else cap_sink -= delta;
- flow += (cap_source < cap_sink) ? cap_source : cap_sink;
- ((node*)i) -> tr_cap = cap_source - cap_sink;
- }
- /*
- Converts arcs added by 'add_edge()' calls
- to a forward star graph representation.
- Linear time algorithm.
- No or little additional memory is allocated
- during this process
- (it may be necessary to allocate additional
- arc blocks, since arcs corresponding to the
- same node must be contiguous, i.e. be in one
- arc block.)
- */
- void Graph::prepare_graph()
- {
- node *i;
- arc_for_block *ab_for, *ab_for_first;
- arc_rev_block *ab_rev, *ab_rev_first, *ab_rev_scan;
- arc_forward *a_for;
- arc_reverse *a_rev, *a_rev_scan, a_rev_tmp;
- node_block *nb;
- bool for_flag = false, rev_flag = false;
- PTR_CAST k;
- if (!arc_rev_block_first)
- {
- node_id from = add_node(), to = add_node();
- add_edge(from, to, 1, 0);
- }
- /* FIRST STAGE */
- a_rev_tmp.sister = NULL;
- for (a_rev = arc_rev_block_first->current; a_rev < &arc_rev_block_first->arcs_rev[ARC_BLOCK_SIZE]; a_rev++)
- {
- a_rev -> sister = NULL;
- }
- ab_for = ab_for_first = arc_for_block_first;
- ab_rev = ab_rev_first = ab_rev_scan = arc_rev_block_first;
- a_for = &ab_for->arcs_for[0];
- a_rev = a_rev_scan = &ab_rev->arcs_rev[0];
- for (nb = node_block_first; nb; nb = nb->next)
- {
- for (i = &nb->nodes[0]; i < nb->current; i++)
- {
- /* outgoing arcs */
- k = (PTR_CAST) i -> first_out;
- if (a_for + k > &ab_for->arcs_for[ARC_BLOCK_SIZE])
- {
- if (k > ARC_BLOCK_SIZE) {
- if (error_function) (*error_function)("# of arcs per node exceeds block size!");
- exit(1);
- }
- if (for_flag) ab_for = NULL;
- else {
- ab_for = ab_for -> next;
- ab_rev_scan = ab_rev_scan -> next;
- }
- if (ab_for == NULL)
- {
- arc_for_block *next = arc_for_block_first;
- char *ptr = new char[sizeof(arc_for_block)+1];
- if (!ptr) {
- if (error_function) (*error_function)("Not enough memory!");
- exit(1);
- }
- if ((PTR_CAST)ptr & 1) arc_for_block_first = (arc_for_block *) (ptr + 1);
- else arc_for_block_first = (arc_for_block *) ptr;
- arc_for_block_first -> start = ptr;
- arc_for_block_first -> current = & ( arc_for_block_first -> arcs_for[0] );
- arc_for_block_first -> next = next;
- ab_for = arc_for_block_first;
- for_flag = true;
- }
- else a_rev_scan = &ab_rev_scan->arcs_rev[0];
- a_for = &ab_for->arcs_for[0];
- }
- if (ab_rev_scan)
- {
- a_rev_scan += k;
- i -> parent = (arc_forward *) a_rev_scan;
- }
- else i -> parent = (arc_forward *) & a_rev_tmp;
- a_for += k;
- i -> first_out = a_for;
- ab_for -> last_node = i;
- /* incoming arcs */
- k = (PTR_CAST) i -> first_in;
- if (a_rev + k > &ab_rev->arcs_rev[ARC_BLOCK_SIZE])
- {
- if (k > ARC_BLOCK_SIZE) {
- if (error_function) (*error_function)("# of arcs per node exceeds block size!");
- exit(1);
- }
- if (rev_flag) ab_rev = NULL;
- else ab_rev = ab_rev -> next;
- if (ab_rev == NULL)
- {
- arc_rev_block *next = arc_rev_block_first;
- char *ptr = new char[sizeof(arc_rev_block)+1];
- if (!ptr) {
- if (error_function) (*error_function)("Not enough memory!");
- exit(1);
- }
- if ((PTR_CAST)ptr & 1) arc_rev_block_first = (arc_rev_block *) (ptr + 1);
- else arc_rev_block_first = (arc_rev_block *) ptr;
- arc_rev_block_first -> start = ptr;
- arc_rev_block_first -> current = & ( arc_rev_block_first -> arcs_rev[0] );
- arc_rev_block_first -> next = next;
- ab_rev = arc_rev_block_first;
- rev_flag = true;
- }
- a_rev = &ab_rev->arcs_rev[0];
- }
- a_rev += k;
- i -> first_in = a_rev;
- ab_rev -> last_node = i;
- }
- /* i is the last node in block */
- i -> first_out = a_for;
- i -> first_in = a_rev;
- }
- /* SECOND STAGE */
- for (ab_for = arc_for_block_first; ab_for; ab_for = ab_for->next)
- {
- ab_for -> current = ab_for -> last_node -> first_out;
- }
- for ( ab_for = ab_for_first, ab_rev = ab_rev_first;
- ab_for;
- ab_for = ab_for->next, ab_rev = ab_rev->next )
- for ( a_for = &ab_for->arcs_for[0], a_rev = &ab_rev->arcs_rev[0];
- a_for < &ab_for->arcs_for[ARC_BLOCK_SIZE];
- a_for++, a_rev++ )
- {
- arc_forward *af;
- arc_reverse *ar;
- node *from;
- PTR_CAST shift = 0, shift_new;
- captype r_cap, r_rev_cap, r_cap_new, r_rev_cap_new;
- if (!(from = (node *)(a_rev->sister))) continue;
- af = a_for;
- ar = a_rev;
- do
- {
- ar -> sister = NULL;
- shift_new = ((char *)(af->shift)) - (char *)from;
- r_cap_new = af -> r_cap;
- r_rev_cap_new = af -> r_rev_cap;
- if (shift)
- {
- af -> shift = shift;
- af -> r_cap = r_cap;
- af -> r_rev_cap = r_rev_cap;
- }
- shift = shift_new;
- r_cap = r_cap_new;
- r_rev_cap = r_rev_cap_new;
- af = -- from -> first_out;
- if ((arc_reverse *)(from->parent) != &a_rev_tmp)
- {
- from -> parent = (arc_forward *)(((arc_reverse *)(from -> parent)) - 1);
- ar = (arc_reverse *)(from -> parent);
- }
- } while (from = (node *)(ar->sister));
- af -> shift = shift;
- af -> r_cap = r_cap;
- af -> r_rev_cap = r_rev_cap;
- }
- for (ab_for = arc_for_block_first; ab_for; ab_for = ab_for->next)
- {
- i = ab_for -> last_node;
- a_for = i -> first_out;
- ab_for -> current -> shift = a_for -> shift;
- ab_for -> current -> r_cap = a_for -> r_cap;
- ab_for -> current -> r_rev_cap = a_for -> r_rev_cap;
- a_for -> shift = (PTR_CAST) (ab_for -> current + 1);
- i -> first_out = (arc_forward *) (((char *)a_for) - 1);
- }
- /* THIRD STAGE */
- for (ab_rev = arc_rev_block_first; ab_rev; ab_rev = ab_rev->next)
- {
- ab_rev -> current = ab_rev -> last_node -> first_in;
- }
- for (nb = node_block_first; nb; nb = nb->next)
- for (i = &nb->nodes[0]; i < nb->current; i++)
- {
- arc_forward *a_for_first, *a_for_last;
- a_for_first = i -> first_out;
- if (IS_ODD(a_for_first))
- {
- a_for_first = (arc_forward *) (((char *)a_for_first) + 1);
- a_for_last = (arc_forward *) ((a_for_first ++) -> shift);
- }
- else a_for_last = (i + 1) -> first_out;
- for (a_for = a_for_first; a_for < a_for_last; a_for++)
- {
- node *to = NEIGHBOR_NODE(i, a_for -> shift);
- a_rev = -- to -> first_in;
- a_rev -> sister = a_for;
- }
- }
- for (ab_rev = arc_rev_block_first; ab_rev; ab_rev = ab_rev->next)
- {
- i = ab_rev -> last_node;
- a_rev = i -> first_in;
- ab_rev -> current -> sister = a_rev -> sister;
- a_rev -> sister = (arc_forward *) (ab_rev -> current + 1);
- i -> first_in = (arc_reverse *) (((char *)a_rev) - 1);
- }
- }
|