flowtype Graph<captype,tcaptype,flowtype>::maxflow(bool reuse_trees, Block<node_id>* _changed_list)
{
	node *i, *j, *current_node = NULL;
	arc *a;
	nodeptr *np, *np_next;

	if (!nodeptr_block)
	{
		nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);
	}

	changed_list = _changed_list;
	if (maxflow_iteration == 0 && reuse_trees) { if (error_function) (*error_function)("reuse_trees cannot be used in the first call to maxflow()!"); exit(1); }
	if (changed_list && !reuse_trees) { if (error_function) (*error_function)("changed_list cannot be used without reuse_trees!"); exit(1); }

	if (reuse_trees) maxflow_reuse_trees_init();
	else             maxflow_init();

	// main loop
	while ( 1 )
	{
		// test_consistency(current_node);

		if ((i=current_node))
		{
			i -> next = NULL; /* remove active flag */
			if (!i->parent) i = NULL;
		}
		if (!i)
		{
			if (!(i = next_active())) break;
		}

		/* growth */
		if (!i->is_sink)
		{
			/* grow source tree */
			for (a=i->first; a; a=a->next)
			if (a->r_cap)
			{
				j = a -> head;
				if (!j->parent)
				{
					j -> is_sink = 0;
					j -> parent = a -> sister;
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
					add_to_changed_list(j);
				}
				else if (j->is_sink) break;
				else if (j->TS <= i->TS &&
				         j->DIST> i->DIST)
				{
					/* heuristic - trying to make the distance from j to the source shorter */
					j -> parent = a -> sister;
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
		}
		else
		{
			/* grow sink tree */
			for (a=i->first; a; a=a->next)
			if (a->sister->r_cap)
			{
				j = a -> head;
				if (!j->parent)
				{
					j -> is_sink = 1;
					j -> parent = a -> sister;
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
					add_to_changed_list(j);
				}
				else if (!j->is_sink) { a = a -> sister; break; }
				else if (j->TS <= i->TS &&
				         j->DIST> i->DIST)
				{
					/* heuristic - trying to make the distance from j to the sink shorter */
					j -> parent = a -> sister;
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
		}

		TIME ++;

		if (a)
		{
			i -> next = i; /* set active flag */
			current_node = i;

			/* augmentation */
			augment(a);
			/* augmentation end */

			/* adoption */
			while ((np=orphan_first))
			{
				np_next = np -> next;
				np -> next = NULL;

				while ((np=orphan_first))
				{
					orphan_first = np -> next;
					i = np -> ptr;
					nodeptr_block -> Delete(np);
					if (!orphan_first) orphan_last = NULL;
					if (i->is_sink) process_sink_orphan(i);
					else            process_source_orphan(i);
				}

				orphan_first = np_next;
			}
			/* adoption end */
		}
		else current_node = NULL;
	}
	// test_consistency();

	if (!reuse_trees || (maxflow_iteration % 64) == 0)
	{
		delete nodeptr_block; 
		nodeptr_block = NULL; 
	}

	maxflow_iteration ++;
	return flow;
}
	void Graph<captype,tcaptype,flowtype>::maxflow_reuse_trees_init()
{
	node* i;
	node* j;
	node* queue = queue_first[1];
	arc* a;
	nodeptr* np;

	queue_first[0] = queue_last[0] = NULL;
	queue_first[1] = queue_last[1] = NULL;
	orphan_first = orphan_last = NULL;

	TIME ++;

	while ((i=queue))
	{
		queue = i->next;
		if (queue == i) queue = NULL;
		i->next = NULL;
		i->is_marked = 0;
		set_active(i);

		if (i->tr_cap == 0)
		{
			if (i->parent) set_orphan_rear(i);
			continue;
		}

		if (i->tr_cap> 0)
		{
			if (!i->parent || i->is_sink)
			{
				i->is_sink = 0;
				for (a=i->first; a; a=a->next)
				{
					j = a->head;
					if (!j->is_marked)
					{
						if (j->parent == a->sister) set_orphan_rear(j);
						if (j->parent && j->is_sink && a->r_cap> 0) set_active(j);
					}
				}
				add_to_changed_list(i);
			}
		}
		else
		{
			if (!i->parent || !i->is_sink)
			{
				i->is_sink = 1;
				for (a=i->first; a; a=a->next)
				{
					j = a->head;
					if (!j->is_marked)
					{
						if (j->parent == a->sister) set_orphan_rear(j);
						if (j->parent && !j->is_sink && a->sister->r_cap> 0) set_active(j);
					}
				}
				add_to_changed_list(i);
			}
		}
		i->parent = TERMINAL;
		i -> TS = TIME;
		i -> DIST = 1;
	}

	//test_consistency();

	/* adoption */
	while ((np=orphan_first))
	{
		orphan_first = np -> next;
		i = np -> ptr;
		nodeptr_block -> Delete(np);
		if (!orphan_first) orphan_last = NULL;
		if (i->is_sink) process_sink_orphan(i);
		else            process_source_orphan(i);
	}
	/* adoption end */

	//test_consistency();
}
Exemple #3
0
Graph::flowtype Graph::maxflow()
{
	node *i, *j, *current_node = NULL, *s_start, *t_start;
	captype *cap_middle, *rev_cap_middle;
	arc_forward *a_for, *a_for_first, *a_for_last;
	arc_reverse *a_rev, *a_rev_first, *a_rev_last;
	nodeptr *np, *np_next;

	prepare_graph();
	maxflow_init();
	nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);

	while ( 1 )
	{
		if (i=current_node)
		{
			i -> next = NULL; /* remove active flag */
			if (!i->parent) i = NULL;
		}
		if (!i)
		{
			if (!(i = next_active())) break;
		}

		/* growth */
		s_start = NULL;

		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;
		a_rev_first = i -> first_in;
		if (IS_ODD(a_rev_first))
		{
			a_rev_first = (arc_reverse *) (((char *)a_rev_first) + 1);
			a_rev_last = (arc_reverse *) ((a_rev_first ++) -> sister);
		}
		else a_rev_last = (i + 1) -> first_in;

		if (!i->is_sink)
		{
			/* grow source tree */
			for (a_for=a_for_first; a_for<a_for_last; a_for++)
			if (a_for->r_cap)
			{
				j = NEIGHBOR_NODE(i, a_for -> shift);
				if (!j->parent)
				{
					j -> is_sink = 0;
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
				}
				else if (j->is_sink)
				{
					s_start = i;
					t_start = j;
					cap_middle     = & ( a_for -> r_cap );
					rev_cap_middle = & ( a_for -> r_rev_cap );
					break;
				}
				else if (j->TS <= i->TS &&
				         j->DIST > i->DIST)
				{
					/* heuristic - trying to make the distance from j to the source shorter */
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
			if (!s_start)
			for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
			{
				a_for = a_rev -> sister;
				if (a_for->r_rev_cap)
				{
					j = NEIGHBOR_NODE_REV(i, a_for -> shift);
					if (!j->parent)
					{
						j -> is_sink = 0;
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
						set_active(j);
					}
					else if (j->is_sink)
					{
						s_start = i;
						t_start = j;
						cap_middle     = & ( a_for -> r_rev_cap );
						rev_cap_middle = & ( a_for -> r_cap );
						break;
					}
					else if (j->TS <= i->TS &&
							 j->DIST > i->DIST)
					{
						/* heuristic - trying to make the distance from j to the source shorter */
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
					}
				}
			}
		}
		else
		{
			/* grow sink tree */
			for (a_for=a_for_first; a_for<a_for_last; a_for++)
			if (a_for->r_rev_cap)
			{
				j = NEIGHBOR_NODE(i, a_for -> shift);
				if (!j->parent)
				{
					j -> is_sink = 1;
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
				}
				else if (!j->is_sink)
				{
					s_start = j;
					t_start = i;
					cap_middle     = & ( a_for -> r_rev_cap );
					rev_cap_middle = & ( a_for -> r_cap );
					break;
				}
				else if (j->TS <= i->TS &&
				         j->DIST > i->DIST)
				{
					/* heuristic - trying to make the distance from j to the sink shorter */
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
			for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
			{
				a_for = a_rev -> sister;
				if (a_for->r_cap)
				{
					j = NEIGHBOR_NODE_REV(i, a_for -> shift);
					if (!j->parent)
					{
						j -> is_sink = 1;
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
						set_active(j);
					}
					else if (!j->is_sink)
					{
						s_start = j;
						t_start = i;
						cap_middle     = & ( a_for -> r_cap );
						rev_cap_middle = & ( a_for -> r_rev_cap );
						break;
					}
					else if (j->TS <= i->TS &&
							 j->DIST > i->DIST)
					{
						/* heuristic - trying to make the distance from j to the sink shorter */
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
					}
				}
			}
		}

		TIME ++;

		if (s_start)
		{
			i -> next = i; /* set active flag */
			current_node = i;

			/* augmentation */
			augment(s_start, t_start, cap_middle, rev_cap_middle);
			/* augmentation end */

			/* adoption */
			while (np=orphan_first)
			{
				np_next = np -> next;
				np -> next = NULL;

				while (np=orphan_first)
				{
					orphan_first = np -> next;
					i = np -> ptr;
					nodeptr_block -> Delete(np);
					if (!orphan_first) orphan_last = NULL;
					if (i->is_sink) process_sink_orphan(i);
					else            process_source_orphan(i);
				}

				orphan_first = np_next;
			}
			/* adoption end */
		}
		else current_node = NULL;
	}

	delete nodeptr_block;

	return flow;
}
	void QPBO<REAL>::maxflow_reuse_trees_init()
{
	Node* i;
	Node* j;
	Node* queue = queue_first[1];
	Arc* a;
	nodeptr* np;

	queue_first[0] = queue_last[0] = NULL;
	queue_first[1] = queue_last[1] = NULL;
	orphan_first = orphan_last = NULL;

	TIME ++;

	while ((i=queue))
	{
		queue = i->next;
		if (queue == i) queue = NULL;
		if (IsNode0(i))
		{
			if (i->is_removed) continue;
		}
		else
		{
			if (GetMate1(i)->is_removed) continue;
		}
		i->next = NULL;
		i->is_marked = 0;
		set_active(i);

		if (i->tr_cap == 0)
		{
			if (i->parent) set_orphan_rear(i);
			continue;
		}

		if (i->tr_cap > 0)
		{
			if (!i->parent || i->is_sink)
			{
				i->is_sink = 0;
				for (a=i->first; a; a=a->next)
				{
					j = a->head;
					if (!j->is_marked)
					{
						if (j->parent == a->sister) set_orphan_rear(j);
						if (j->parent && j->is_sink && a->r_cap > 0) set_active(j);
					}
				}
				add_to_changed_list(i);
			}
		}
		else
		{
			if (!i->parent || !i->is_sink)
			{
				i->is_sink = 1;
				for (a=i->first; a; a=a->next)
				{
					j = a->head;
					if (!j->is_marked)
					{
						if (j->parent == a->sister) set_orphan_rear(j);
						if (j->parent && !j->is_sink && a->sister->r_cap > 0) set_active(j);
					}
				}
				add_to_changed_list(i);
			}
		}
		i->parent = QPBO_MAXFLOW_TERMINAL;
		i -> TS = TIME;
		i -> DIST = 1;
	}

	code_assert(stage == 1);
	//test_consistency();

	/* adoption */
	while ((np=orphan_first))
	{
		orphan_first = np -> next;
		i = np -> ptr;
		nodeptr_block -> Delete(np);
		if (!orphan_first) orphan_last = NULL;
		if (i->is_sink) process_sink_orphan(i);
		else            process_source_orphan(i);
	}
	/* adoption end */

	//test_consistency();
}
Graph::flowtype Graph::maxflow()
{
    node *i, *j, *current_node = NULL;
    arc *a;
    nodeptr *np, *np_next;

    maxflow_init();
    nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);

    while ( 1 )
    {
        if (i=current_node)
        {
            i -> next = NULL; /* remove active flag */
            if (!i->parent) i = NULL;
        }
        if (!i)
        {
            if (!(i = next_active())) break;
        }

        /* growth */
        if (!i->is_sink)
        {
            /* grow source tree */
            for (a=i->first; a; a=a->next)
                if (a->r_cap)
                {
                    j = a -> head;
                    if (!j->parent)
                    {
                        j -> is_sink = 0;
                        j -> parent = a -> sister;
                        j -> TS = i -> TS;
                        j -> DIST = i -> DIST + 1;
                        set_active(j);
                    }
                    else if (j->is_sink) break;
                    else if (j->TS <= i->TS &&
                             j->DIST > i->DIST)
                    {
                        /* heuristic - trying to make the distance from j to the source shorter */
                        j -> parent = a -> sister;
                        j -> TS = i -> TS;
                        j -> DIST = i -> DIST + 1;
                    }
                }
        }
        else
        {
            /* grow sink tree */
            for (a=i->first; a; a=a->next)
                if (a->sister->r_cap)
                {
                    j = a -> head;
                    if (!j->parent)
                    {
                        j -> is_sink = 1;
                        j -> parent = a -> sister;
                        j -> TS = i -> TS;
                        j -> DIST = i -> DIST + 1;
                        set_active(j);
                    }
                    else if (!j->is_sink) {
                        a = a -> sister;
                        break;
                    }
                    else if (j->TS <= i->TS &&
                             j->DIST > i->DIST)
                    {
                        /* heuristic - trying to make the distance from j to the sink shorter */
                        j -> parent = a -> sister;
                        j -> TS = i -> TS;
                        j -> DIST = i -> DIST + 1;
                    }
                }
        }

        TIME ++;

        if (a)
        {
            i -> next = i; /* set active flag */
            current_node = i;

            /* augmentation */
            augment(a);
            /* augmentation end */

            /* adoption */
            while (np=orphan_first)
            {
                np_next = np -> next;
                np -> next = NULL;

                while (np=orphan_first)
                {
                    orphan_first = np -> next;
                    i = np -> ptr;
                    nodeptr_block -> Delete(np);
                    if (!orphan_first) orphan_last = NULL;
                    if (i->is_sink) process_sink_orphan(i);
                    else            process_source_orphan(i);
                }

                orphan_first = np_next;
            }
            /* adoption end */
        }
        else current_node = NULL;
    }

    delete nodeptr_block;

    return flow;
}