#ifndef NO_CS2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <limits.h>
#include <float.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <assert.h>
#include "snaphu.h"
extern FILE *sp0, *sp1, *sp2, *sp3;
#define PRICE_MAX 1e30
#define BIGGEST_FLOW LARGESHORT
int cs2mcfparse(
signed char **residue,
short **rowcost,
short **colcost,
long nNrow,
long nNcol,
long *n_ad,
long *m_ad,
node **nodes_ad,
arc **arcs_ad,
long *node_min_ad,
double *m_c_ad,
short **cap_ad
)
{
#define ABS( x ) ( (x) >= 0 ) ? (x) : -(x)
unsigned int row, col, dir;
unsigned long narcs, nnodes, nodectr, arcctr, nresidues;
long cumsupply, temp;
long inf_cap = 0;
long n,
node_min,
node_max,
*arc_first,
*arc_tail,
head, tail, i;
long m,
last, arc_num, arc_new_num;
node *nodes,
*head_p,
*ndp,
*in,
*jn;
arc *arcs,
*arc_current,
*arc_new,
*arc_tmp;
long excess,
low,
acap;
long cost;
double dcost,
m_c;
short *cap;
double total_p,
total_n,
cap_out,
cap_in;
long no_lines=0,
no_alines=0,
pos_current=0;
int
err_no;
#define EN1 0
#define EN2 1
#define EN3 2
#define EN4 3
#define EN6 4
#define EN10 5
#define EN7 6
#define EN8 7
#define EN9 8
#define EN11 9
#define EN12 10
#define EN13 11
#define EN14 12
#define EN16 13
#define EN15 14
#define EN17 15
#define EN18 16
#define EN21 17
#define EN19 18
#define EN20 19
#define EN22 20
static char *err_message[] =
{
"more than one problem line",
"wrong number of parameters in the problem line",
"it is not a Min-cost problem line",
"bad value of a parameter in the problem line",
"can't obtain enough memory to solve this problem",
"",
"can't read problem name",
"problem description must be before node description",
"wrong capacity bounds",
"wrong number of parameters in the node line",
"wrong value of parameters in the node line",
"unbalanced problem",
"node descriptions must be before arc descriptions",
"too many arcs in the input",
"wrong number of parameters in the arc line",
"wrong value of parameters in the arc line",
"unknown line type in the input",
"read error",
"not enough arcs in the input",
"warning: capacities too big - excess overflow possible",
"can't read anything from the input file",
"warning: infinite capacity replaced by BIGGEST_FLOW"
};
nnodes=nNrow*nNcol+1;
narcs=2*((nNrow+1)*nNcol+nNrow*(nNcol+1));
cumsupply=0;
nresidues=0;
fprintf(sp2,"Setting up data structures for cs2 MCF solver\n");
n=nnodes;
m=narcs;
if ( n <= 0 || m <= 0 )
{ err_no = EN4; goto error; }
nodes = (node*) CAlloc ( n+2, sizeof(node) );
arcs = (arc*) CAlloc ( 2*m+1, sizeof(arc) );
cap = (short*) CAlloc ( 2*m, sizeof(short) );
arc_tail = (long*) CAlloc ( 2*m, sizeof(long) );
arc_first= (long*) CAlloc ( n+2, sizeof(long) );
for ( in = nodes; in <= nodes + n; in ++ )
in -> excess = 0;
if ( nodes == NULL || arcs == NULL ||
arc_first == NULL || arc_tail == NULL )
{ err_no = EN6; goto error; }
arc_current = arcs;
node_max = 0;
node_min = n;
m_c = 0;
total_p = total_n = 0;
for ( ndp = nodes; ndp < nodes + n; ndp ++ )
ndp -> excess = 0;
for(col=0; col<nNcol; col++){
for(row=0; row<nNrow; row++){
if(residue[row][col]){
i=(col*nNrow + row + 1);
excess=residue[row][col];
( nodes + i ) -> excess = excess;
if ( excess > 0 ) total_p += (double)excess;
if ( excess < 0 ) total_n -= (double)excess;
nresidues++;
cumsupply+=residue[row][col];
}
}
}
( nodes + nnodes ) -> excess = -cumsupply;
if (cumsupply < 0) total_p -= (double)cumsupply;
if (cumsupply > 0) total_n += (double)cumsupply;
low=0;
acap=ARCUBOUND;
for(arcctr=1;arcctr<=2*nNrow*nNcol+nNrow+nNcol;arcctr++){
if(arcctr<=nNrow*(nNcol+1)){
nodectr=arcctr;
if(nodectr<=nNrow*nNcol){
tail=nodectr;
}else{
tail=nnodes;
}
if(nodectr<=nNrow){
head=nnodes;
}else{
head=nodectr-nNrow;
}
cost=rowcost[((nodectr-1) % nNrow)][(int )((nodectr-1)/nNrow)];
}else{
nodectr=arcctr-nNrow*(nNcol+1);
if(nodectr % (nNrow+1)==0){
tail=nnodes;
}else{
tail=(int )(nodectr-ceil(nodectr/(nNrow+1.0))+1);
}
if(nodectr % (nNrow+1)==1){
head=nnodes;
}else{
head=(int )(nodectr-ceil(nodectr/(nNrow+1.0)));
}
cost=colcost[((nodectr-1) % (nNrow+1))][(int )((nodectr-1)/(nNrow+1))];
}
if ( tail < 0 || tail > n ||
head < 0 || head > n
)
{ err_no = EN17; goto error; }
if ( acap < 0 ) {
acap = BIGGEST_FLOW;
if (!inf_cap) {
inf_cap = 1;
fprintf ( sp0, "\ncs2 solver: %s\n", err_message[21] );
}
}
if ( low < 0 || low > acap )
{ err_no = EN9; goto error; }
for(dir=0;dir<=1;dir++){
if(dir){
temp=tail;
tail=head;
head=temp;
}
arc_first[tail + 1] ++;
arc_first[head + 1] ++;
in = nodes + tail;
jn = nodes + head;
dcost = (double)cost;
arc_tail[pos_current] = tail;
arc_tail[pos_current+1] = head;
arc_current -> head = jn;
arc_current -> r_cap = acap - low;
cap[pos_current] = acap;
arc_current -> cost = dcost;
arc_current -> sister = arc_current + 1;
( arc_current + 1 ) -> head = nodes + tail;
( arc_current + 1 ) -> r_cap = 0;
cap[pos_current+1] = 0;
( arc_current + 1 ) -> cost = -dcost;
( arc_current + 1 ) -> sister = arc_current;
in -> excess -= low;
jn -> excess += low;
if ( head < node_min ) node_min = head;
if ( tail < node_min ) node_min = tail;
if ( head > node_max ) node_max = head;
if ( tail > node_max ) node_max = tail;
if ( dcost < 0 ) dcost = -dcost;
if ( dcost > m_c && acap > 0 ) m_c = dcost;
no_alines ++;
arc_current += 2;
pos_current += 2;
}
}
if ( ABS( total_p - total_n ) > 0.5 )
{ err_no = EN13; goto error; }
( nodes + node_min ) -> first = arcs;
for ( i = node_min + 1; i <= node_max + 1; i ++ )
{
arc_first[i] += arc_first[i-1];
( nodes + i ) -> first = arcs + arc_first[i];
}
for ( i = node_min; i < node_max; i ++ )
{
last = ( ( nodes + i + 1 ) -> first ) - arcs;
for ( arc_num = arc_first[i]; arc_num < last; arc_num ++ )
{ tail = arc_tail[arc_num];
while ( tail != i )
{ arc_new_num = arc_first[tail];
arc_current = arcs + arc_num;
arc_new = arcs + arc_new_num;
head_p = arc_new -> head;
arc_new -> head = arc_current -> head;
arc_current -> head = head_p;
acap = cap[arc_new_num];
cap[arc_new_num] = cap[arc_num];
cap[arc_num] = acap;
acap = arc_new -> r_cap;
arc_new -> r_cap = arc_current -> r_cap;
arc_current -> r_cap = acap;
dcost = arc_new -> cost;
arc_new -> cost = arc_current -> cost;
arc_current -> cost = dcost;
if ( arc_new != arc_current -> sister )
{
arc_tmp = arc_new -> sister;
arc_new -> sister = arc_current -> sister;
arc_current -> sister = arc_tmp;
( arc_current -> sister ) -> sister = arc_current;
( arc_new -> sister ) -> sister = arc_new;
}
arc_tail[arc_num] = arc_tail[arc_new_num];
arc_tail[arc_new_num] = tail;
arc_first[tail] ++ ;
tail = arc_tail[arc_num];
}
}
}
for ( ndp = nodes + node_min; ndp <= nodes + node_max; ndp ++ )
{
cap_in = ( ndp -> excess );
cap_out = - ( ndp -> excess );
for ( arc_current = ndp -> first; arc_current != (ndp+1) -> first;
arc_current ++ )
{
arc_num = arc_current - arcs;
if ( cap[arc_num] > 0 ) cap_out += cap[arc_num];
if ( cap[arc_num] == 0 )
cap_in += cap[( arc_current -> sister )-arcs];
}
}
*m_ad = m;
*n_ad = node_max - node_min + 1;
*node_min_ad = node_min;
*nodes_ad = nodes + node_min;
*arcs_ad = arcs;
*m_c_ad = m_c;
*cap_ad = cap;
free ( arc_first ); free ( arc_tail );
return (0);
error:
fprintf ( sp0, "\ncs2 solver: line %ld of input - %s\n",
no_lines, err_message[err_no] );
exit (ABNORMAL_EXIT);
return(1);
}
#define N_NODE( i ) ( ( (i) == NULL ) ? -1 : ( (i) - ndp + nmin ) )
#define N_ARC( a ) ( ( (a) == NULL )? -1 : (a) - arp )
#define UNFEASIBLE 2
#define ALLOCATION_FAULT 5
#define PRICE_OFL 6
#define UPDT_FREQ 0.4
#define UPDT_FREQ_S 30
#define SCALE_DEFAULT 12.0
#define PRICE_OUT_START 1
#define CUT_OFF_POWER 0.44
#define CUT_OFF_COEF 1.5
#define CUT_OFF_POWER2 0.75
#define CUT_OFF_COEF2 1
#define CUT_OFF_GAP 0.8
#define CUT_OFF_MIN 12
#define CUT_OFF_INCREASE 4
#define TIME_FOR_PRICE_IN1 2
#define TIME_FOR_PRICE_IN2 4
#define TIME_FOR_PRICE_IN3 6
#define EMPTY_PUSH_COEF 1.0
#define MAX_CYCLES_CANCELLED 0
#define START_CYCLE_CANCEL 100
#define GREATEROF( x, y ) ( ( (x) > (y) ) ? x : y )
#define LESSEROF( x, y ) ( ( (x) < (y) ) ? x : y )
#define OPEN( a ) ( a -> r_cap > 0 )
#define CLOSED( a ) ( a -> r_cap <= 0 )
#define REDUCED_COST( i, j, a ) ( (i->price) + dn*(a->cost) - (j->price) )
#define FEASIBLE( i, j, a ) ( (i->price) + dn*(a->cost) < (j->price) )
#define ADMISSIBLE( i, j, a ) ( OPEN(a) && FEASIBLE( i, j, a ) )
#define INCREASE_FLOW( i, j, a, df )\
{\
(i) -> excess -= df;\
(j) -> excess += df;\
(a) -> r_cap -= df;\
((a) -> sister) -> r_cap += df;\
}\
#define RESET_EXCESS_Q \
{\
for ( ; excq_first != NULL; excq_first = excq_last )\
{\
excq_last = excq_first -> q_next;\
excq_first -> q_next = sentinel_node;\
}\
}
#define OUT_OF_EXCESS_Q( i ) ( i -> q_next == sentinel_node )
#define EMPTY_EXCESS_Q ( excq_first == NULL )
#define NONEMPTY_EXCESS_Q ( excq_first != NULL )
#define INSERT_TO_EXCESS_Q( i )\
{\
if ( NONEMPTY_EXCESS_Q )\
excq_last -> q_next = i;\
else\
excq_first = i;\
\
i -> q_next = NULL;\
excq_last = i;\
}
#define INSERT_TO_FRONT_EXCESS_Q( i )\
{\
if ( EMPTY_EXCESS_Q )\
excq_last = i;\
\
i -> q_next = excq_first;\
excq_first = i;\
}
#define REMOVE_FROM_EXCESS_Q( i )\
{\
i = excq_first;\
excq_first = i -> q_next;\
i -> q_next = sentinel_node;\
}
#define EMPTY_STACKQ EMPTY_EXCESS_Q
#define NONEMPTY_STACKQ NONEMPTY_EXCESS_Q
#define RESET_STACKQ RESET_EXCESS_Q
#define STACKQ_PUSH( i )\
{\
i -> q_next = excq_first;\
excq_first = i;\
}
#define STACKQ_POP( i ) REMOVE_FROM_EXCESS_Q( i )
node dnd, *dnode;
#define RESET_BUCKET( b ) ( b -> p_first ) = dnode;
#define INSERT_TO_BUCKET( i, b )\
{\
i -> b_next = ( b -> p_first );\
( b -> p_first ) -> b_prev = i;\
( b -> p_first ) = i;\
}
#define NONEMPTY_BUCKET( b ) ( ( b -> p_first ) != dnode )
#define GET_FROM_BUCKET( i, b )\
{\
i = ( b -> p_first );\
( b -> p_first ) = i -> b_next;\
}
#define REMOVE_FROM_BUCKET( i, b )\
{\
if ( i == ( b -> p_first ) )\
( b -> p_first ) = i -> b_next;\
else\
{\
( i -> b_prev ) -> b_next = i -> b_next;\
( i -> b_next ) -> b_prev = i -> b_prev;\
}\
}
#define UPDATE_CUT_OFF \
{\
if (n_bad_pricein + n_bad_relabel == 0) \
{\
cut_off_factor = CUT_OFF_COEF2 * pow ( (double)n, CUT_OFF_POWER2 );\
cut_off_factor = GREATEROF ( cut_off_factor, CUT_OFF_MIN );\
cut_off = cut_off_factor * epsilon;\
cut_on = cut_off * CUT_OFF_GAP;\
}\
else\
{\
cut_off_factor *= CUT_OFF_INCREASE;\
cut_off = cut_off_factor * epsilon;\
cut_on = cut_off * CUT_OFF_GAP;\
}\
}
#define TIME_FOR_UPDATE \
( n_rel > n * UPDT_FREQ + n_src * UPDT_FREQ_S )
#define FOR_ALL_NODES_i for ( i = nodes; i != sentinel_node; i ++ )
#define FOR_ALL_ARCS_a_FROM_i \
for ( a = i -> first, a_stop = ( i + 1 ) -> suspended; a != a_stop; a ++ )
#define FOR_ALL_CURRENT_ARCS_a_FROM_i \
for ( a = i -> current, a_stop = ( i + 1 ) -> suspended; a != a_stop; a ++ )
#define WHITE 0
#define GREY 1
#define BLACK 2
arc *sa, *sb;
long d_cap;
#define EXCHANGE( a, b )\
{\
if ( a != b )\
{\
sa = a -> sister;\
sb = b -> sister;\
\
d_arc.r_cap = a -> r_cap;\
d_arc.cost = a -> cost;\
d_arc.head = a -> head;\
\
a -> r_cap = b -> r_cap;\
a -> cost = b -> cost;\
a -> head = b -> head;\
\
b -> r_cap = d_arc.r_cap;\
b -> cost = d_arc.cost;\
b -> head = d_arc.head;\
\
if ( a != sb )\
{\
b -> sister = sa;\
a -> sister = sb;\
sa -> sister = b;\
sb -> sister = a;\
}\
\
d_cap = cap[a-arcs];\
cap[a-arcs] = cap[b-arcs];\
cap[b-arcs] = d_cap;\
}\
}
#define SUSPENDED( i, a ) ( a < i -> first )
long n_push =0,
n_relabel =0,
n_discharge =0,
n_refine =0,
n_update =0,
n_scan =0,
n_prscan =0,
n_prscan1 =0,
n_prscan2 =0,
n_bad_pricein = 0,
n_bad_relabel = 0,
n_prefine =0;
long n,
m;
short *cap;
node *nodes,
*sentinel_node,
*excq_first,
*excq_last;
arc *arcs,
*sentinel_arc;
bucket *buckets,
*l_bucket;
long linf;
double dlinf;
int time_for_price_in;
double epsilon,
low_bound,
price_min,
f_scale,
dn,
mmc,
cut_off_factor,
cut_on,
cut_off;
double total_excess;
long n_rel,
n_ref,
n_src;
int flag_price = 0,
flag_updt = 0;
long empty_push_bound;
int snc_max;
arc d_arc;
node d_node,
*dummy_node;
static void err_end ( cc )
int cc;
{
fprintf ( sp0, "\ncs2 solver: Error %d ", cc );
if(cc==ALLOCATION_FAULT){
fprintf(sp0,"(allocation fault)\n");
}else if(cc==UNFEASIBLE){
fprintf(sp0,"(problem infeasible)\n");
}else if(cc==PRICE_OFL){
fprintf(sp0,"(price overflow)\n");
}
exit(ABNORMAL_EXIT);
}
static void cs_init ( n_p, m_p, nodes_p, arcs_p, f_sc, max_c, cap_p )
long n_p,
m_p;
node *nodes_p;
arc *arcs_p;
long f_sc;
double max_c;
short *cap_p;
{
node *i;
bucket *b;
n = n_p;
nodes = nodes_p;
sentinel_node = nodes + n;
m = m_p;
arcs = arcs_p;
sentinel_arc = arcs + m;
cap = cap_p;
f_scale = f_sc;
low_bound = 1.00001;
dn = (double) n ;
mmc = max_c * dn;
linf = n * f_scale + 2;
dlinf = (double)linf;
buckets = (bucket*) CAlloc ( linf, sizeof (bucket) );
if ( buckets == NULL )
err_end ( ALLOCATION_FAULT );
l_bucket = buckets + linf;
dnode = &dnd;
for ( b = buckets; b != l_bucket; b ++ )
RESET_BUCKET ( b );
epsilon = mmc;
if ( epsilon < 1 )
epsilon = 1;
price_min = - PRICE_MAX;
FOR_ALL_NODES_i
{
i -> price = 0;
i -> suspended = i -> first;
i -> q_next = sentinel_node;
}
sentinel_node -> first = sentinel_node -> suspended = sentinel_arc;
cut_off_factor = CUT_OFF_COEF * pow ( (double)n, CUT_OFF_POWER );
cut_off_factor = GREATEROF ( cut_off_factor, CUT_OFF_MIN );
n_ref = 0;
flag_price = 0;
dummy_node = &d_node;
excq_first = NULL;
empty_push_bound = n * EMPTY_PUSH_COEF;
}
static void up_node_scan ( i )
node *i;
{
node *j;
arc *a,
*a_stop,
*ra;
bucket *b_old,
*b_new;
long i_rank,
j_rank,
j_new_rank;
double rc,
dr;
n_scan ++;
i_rank = i -> rank;
FOR_ALL_ARCS_a_FROM_i
{
ra = a -> sister;
if ( OPEN ( ra ) )
{
j = a -> head;
j_rank = j -> rank;
if ( j_rank > i_rank )
{
if ( ( rc = REDUCED_COST ( j, i, ra ) ) < 0 )
j_new_rank = i_rank;
else
{
dr = rc / epsilon;
j_new_rank = ( dr < dlinf ) ? i_rank + (long)dr + 1
: linf;
}
if ( j_rank > j_new_rank )
{
j -> rank = j_new_rank;
j -> current = ra;
if ( j_rank < linf )
{
b_old = buckets + j_rank;
REMOVE_FROM_BUCKET ( j, b_old )
}
b_new = buckets + j_new_rank;
INSERT_TO_BUCKET ( j, b_new )
}
}
}
}
i -> price -= i_rank * epsilon;
i -> rank = -1;
}
static void price_update ()
{
register node *i;
double remain;
bucket *b;
double dp;
n_update ++;
FOR_ALL_NODES_i
{
if ( i -> excess < 0 )
{
INSERT_TO_BUCKET ( i, buckets );
i -> rank = 0;
}
else
{
i -> rank = linf;
}
}
remain = total_excess;
if ( remain < 0.5 ) return;
for ( b = buckets; b != l_bucket; b ++ )
{
while ( NONEMPTY_BUCKET ( b ) )
{
GET_FROM_BUCKET ( i, b )
up_node_scan ( i );
if ( i -> excess > 0 )
{
remain -= (double)(i -> excess);
if ( remain <= 0 ) break;
}
}
if ( remain <= 0 ) break;
}
if ( remain > 0.5 ) flag_updt = 1;
dp = ( b - buckets ) * epsilon;
FOR_ALL_NODES_i
{
if ( i -> rank >= 0 )
{
if ( i -> rank < linf )
REMOVE_FROM_BUCKET ( i, (buckets + i -> rank) );
if ( i -> price > price_min )
i -> price -= dp;
}
}
}
static int relabel ( i )
register node *i;
{
register arc *a,
*a_stop,
*a_max;
register double p_max,
i_price,
dp;
p_max = price_min;
i_price = i -> price;
for (
a = i -> current + 1, a_stop = ( i + 1 ) -> suspended;
a != a_stop;
a ++
)
{
if ( OPEN ( a )
&&
( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max )
)
{
if ( i_price < dp )
{
i -> current = a;
return ( 1 );
}
p_max = dp;
a_max = a;
}
}
for (
a = i -> first, a_stop = ( i -> current ) + 1;
a != a_stop;
a ++
)
{
if ( OPEN ( a )
&&
( ( dp = ( ( a -> head ) -> price ) - dn*( a -> cost ) ) > p_max )
)
{
if ( i_price < dp )
{
i -> current = a;
return ( 1 );
}
p_max = dp;
a_max = a;
}
}
if ( p_max != price_min )
{
i -> price = p_max - epsilon;
i -> current = a_max;
}
else
{
if ( i -> suspended == i -> first )
{
if ( i -> excess == 0 )
{
i -> price = price_min;
}
else
{
if ( n_ref == 1 )
{
err_end ( UNFEASIBLE );
}
else
{
err_end ( PRICE_OFL );
}
}
}
else
{
flag_price = 1;
}
}
n_relabel ++;
n_rel ++;
return ( 0 );
}
static void discharge ( i )
register node *i;
{
register arc *a;
arc *b,
*ra;
register node *j;
register long df;
excess_t j_exc;
int empty_push;
n_discharge ++;
empty_push = 0;
a = i -> current;
j = a -> head;
if ( !ADMISSIBLE ( i, j, a ) )
{
relabel ( i );
a = i -> current;
j = a -> head;
}
while ( 1 )
{
j_exc = j -> excess;
if ( j_exc >= 0 )
{
b = j -> current;
if ( ADMISSIBLE ( j, b -> head, b ) || relabel ( j ) )
{
df = LESSEROF ( i -> excess, a -> r_cap );
if (j_exc == 0) n_src++;
INCREASE_FLOW ( i, j, a, df )
n_push ++;
if ( OUT_OF_EXCESS_Q ( j ) )
{
INSERT_TO_EXCESS_Q ( j );
}
}
else
{
ra = a -> sister;
df = LESSEROF ( j -> excess, ra -> r_cap );
if ( df > 0 )
{
INCREASE_FLOW ( j, i, ra, df );
if (j->excess == 0) n_src--;
n_push ++;
}
if ( empty_push ++ >= empty_push_bound )
{
flag_price = 1;
return;
}
}
}
else
{
df = LESSEROF ( i -> excess, a -> r_cap );
INCREASE_FLOW ( i, j, a, df )
n_push ++;
if ( j -> excess >= 0 )
{
if ( j -> excess > 0 )
{
n_src++;
relabel ( j );
INSERT_TO_EXCESS_Q ( j );
}
total_excess += j_exc;
}
else
total_excess -= df;
}
if (i -> excess <= 0)
n_src--;
if ( i -> excess <= 0 || flag_price ) break;
relabel ( i );
a = i -> current;
j = a -> head;
}
i -> current = a;
}
static int price_in ()
{
node *i,
*j;
arc *a,
*a_stop,
*b,
*ra,
*rb;
double rc;
int n_in_bad,
bad_found;
excess_t i_exc,
df;
bad_found = 0;
n_in_bad = 0;
restart:
FOR_ALL_NODES_i
{
for ( a = ( i -> first ) - 1, a_stop = ( i -> suspended ) - 1;
a != a_stop; a -- )
{
rc = REDUCED_COST ( i, a -> head, a );
if ( (rc < 0) && ( a -> r_cap > 0) )
{
if ( bad_found == 0 )
{
bad_found = 1;
UPDATE_CUT_OFF;
goto restart;
}
df = a -> r_cap;
INCREASE_FLOW ( i, a -> head, a, df );
ra = a -> sister;
j = a -> head;
b = -- ( i -> first );
EXCHANGE ( a, b );
if ( SUSPENDED ( j, ra ) )
{
rb = -- ( j -> first );
EXCHANGE ( ra, rb );
}
n_in_bad ++;
}
else
if ( ( rc < cut_on ) && ( rc > -cut_on ) )
{
b = -- ( i -> first );
EXCHANGE ( a, b );
}
}
}
if ( n_in_bad != 0 )
{
n_bad_pricein ++;
total_excess = 0;
n_src=0;
RESET_EXCESS_Q;
FOR_ALL_NODES_i
{
i -> current = i -> first;
i_exc = i -> excess;
if ( i_exc > 0 )
{
total_excess += i_exc;
n_src++;
INSERT_TO_EXCESS_Q ( i );
}
}
INSERT_TO_EXCESS_Q ( dummy_node );
}
if (time_for_price_in == TIME_FOR_PRICE_IN2)
time_for_price_in = TIME_FOR_PRICE_IN3;
if (time_for_price_in == TIME_FOR_PRICE_IN1)
time_for_price_in = TIME_FOR_PRICE_IN2;
return ( n_in_bad );
}
static void refine ()
{
node *i;
excess_t i_exc;
int pr_in_int;
n_refine ++;
n_ref ++;
n_rel = 0;
pr_in_int = 0;
total_excess = 0;
n_src=0;
RESET_EXCESS_Q
time_for_price_in = TIME_FOR_PRICE_IN1;
FOR_ALL_NODES_i
{
i -> current = i -> first;
i_exc = i -> excess;
if ( i_exc > 0 )
{
total_excess += i_exc;
n_src++;
INSERT_TO_EXCESS_Q ( i )
}
}
if ( total_excess <= 0 ) return;
while ( 1 )
{
if ( EMPTY_EXCESS_Q )
{
if ( n_ref > PRICE_OUT_START )
{
price_in ();
}
if ( EMPTY_EXCESS_Q ) break;
}
REMOVE_FROM_EXCESS_Q ( i );
if ( i -> excess > 0 )
{
discharge ( i );
if ( TIME_FOR_UPDATE || flag_price )
{
if ( i -> excess > 0 )
{
INSERT_TO_EXCESS_Q ( i );
}
if ( flag_price && ( n_ref > PRICE_OUT_START ) )
{
pr_in_int = 0;
price_in ();
flag_price = 0;
}
price_update();
while ( flag_updt )
{
if ( n_ref == 1 )
{
err_end ( UNFEASIBLE );
}
else
{
flag_updt = 0;
UPDATE_CUT_OFF;
n_bad_relabel++;
pr_in_int = 0;
price_in ();
price_update ();
}
}
n_rel = 0;
if ( n_ref > PRICE_OUT_START &&
(pr_in_int ++ > time_for_price_in)
)
{
pr_in_int = 0;
price_in ();
}
}
}
}
return;
}
static int price_refine ()
{
node *i,
*j,
*ir,
*is;
arc *a,
*a_stop,
*ar;
long bmax;
long i_rank,
j_rank,
j_new_rank;
bucket *b,
*b_old,
*b_new;
double rc,
dr,
dp;
int cc;
long df;
int nnc,
snc;
n_prefine ++;
cc=1;
snc=0;
snc_max = ( n_ref >= START_CYCLE_CANCEL )
? MAX_CYCLES_CANCELLED
: 0;
while ( 1 )
{
nnc=0;
FOR_ALL_NODES_i
{
i -> rank = 0;
i -> inp = WHITE;
i -> current = i -> first;
}
RESET_STACKQ
FOR_ALL_NODES_i
{
if ( i -> inp == BLACK ) continue;
i -> b_next = NULL;
while ( 1 )
{
i -> inp = GREY;
FOR_ALL_CURRENT_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
if ( REDUCED_COST ( i, j, a ) < 0 )
{
if ( j -> inp == WHITE )
{
i -> current = a;
j -> b_next = i;
i = j;
a = j -> current;
a_stop = (j+1) -> suspended;
break;
}
if ( j -> inp == GREY )
{
cc = 0;
nnc++;
i -> current = a;
is = ir = i;
df = BIGGEST_FLOW;
while ( 1 )
{
ar = ir -> current;
if ( ar -> r_cap <= df )
{
df = ar -> r_cap;
is = ir;
}
if ( ir == j ) break;
ir = ir -> b_next;
}
ir = i;
while ( 1 )
{
ar = ir -> current;
INCREASE_FLOW( ir, ar -> head, ar, df)
if ( ir == j ) break;
ir = ir -> b_next;
}
if ( is != i )
{
for ( ir = i; ir != is; ir = ir -> b_next )
ir -> inp = WHITE;
i = is;
a = (is -> current) + 1;
a_stop = (is+1) -> suspended;
break;
}
}
}
}
}
if ( a == a_stop )
{
i -> inp = BLACK;
n_prscan1++;
j = i -> b_next;
STACKQ_PUSH ( i );
if ( j == NULL ) break;
i = j;
i -> current ++;
}
}
}
snc += nnc;
if ( snc<snc_max ) cc = 1;
if ( cc == 0 ) break;
bmax = 0;
while ( NONEMPTY_STACKQ )
{
n_prscan2++;
STACKQ_POP ( i );
i_rank = i -> rank;
FOR_ALL_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
rc = REDUCED_COST ( i, j, a );
if ( rc < 0 )
{
dr = ( - rc - 0.5 ) / epsilon;
if (( j_rank = dr + i_rank ) < dlinf )
{
if ( j_rank > j -> rank )
j -> rank = j_rank;
}
}
}
}
if ( i_rank > 0 )
{
if ( i_rank > bmax ) bmax = i_rank;
b = buckets + i_rank;
INSERT_TO_BUCKET ( i, b )
}
}
if ( bmax == 0 )
{ break; }
for ( b = buckets + bmax; b != buckets; b -- )
{
i_rank = b - buckets;
dp = (double)i_rank * epsilon;
while ( NONEMPTY_BUCKET( b ) )
{
GET_FROM_BUCKET ( i, b );
n_prscan++;
FOR_ALL_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
j_rank = j -> rank;
if ( j_rank < i_rank )
{
rc = REDUCED_COST ( i, j, a );
if ( rc < 0 )
j_new_rank = i_rank;
else
{
dr = rc / epsilon;
j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 )
: 0;
}
if ( j_rank < j_new_rank )
{
if ( cc == 1 )
{
j -> rank = j_new_rank;
if ( j_rank > 0 )
{
b_old = buckets + j_rank;
REMOVE_FROM_BUCKET ( j, b_old )
}
b_new = buckets + j_new_rank;
INSERT_TO_BUCKET ( j, b_new )
}
else
{
df = a -> r_cap;
INCREASE_FLOW ( i, j, a, df )
}
}
}
}
}
i -> price -= dp;
}
}
if ( cc == 0 ) break;
}
if ( cc == 0 )
{
FOR_ALL_NODES_i
{
FOR_ALL_ARCS_a_FROM_i
{
if ( REDUCED_COST ( i, a -> head, a ) < -epsilon )
{
if ( ( df = a -> r_cap ) > 0 )
{
INCREASE_FLOW ( i, a -> head, a, df )
}
}
}
}
}
return ( cc );
}
void compute_prices ()
{
node *i,
*j;
arc *a,
*a_stop;
long bmax;
long i_rank,
j_rank,
j_new_rank;
bucket *b,
*b_old,
*b_new;
double rc,
dr,
dp;
int cc;
n_prefine ++;
cc=1;
while ( 1 )
{
FOR_ALL_NODES_i
{
i -> rank = 0;
i -> inp = WHITE;
i -> current = i -> first;
}
RESET_STACKQ
FOR_ALL_NODES_i
{
if ( i -> inp == BLACK ) continue;
i -> b_next = NULL;
while ( 1 )
{
i -> inp = GREY;
FOR_ALL_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
if ( REDUCED_COST ( i, j, a ) < 0 )
{
if ( j -> inp == WHITE )
{
i -> current = a;
j -> b_next = i;
i = j;
a = j -> current;
a_stop = (j+1) -> suspended;
break;
}
if ( j -> inp == GREY )
{
cc = 0;
}
}
}
}
if ( a == a_stop )
{
i -> inp = BLACK;
n_prscan1++;
j = i -> b_next;
STACKQ_PUSH ( i );
if ( j == NULL ) break;
i = j;
i -> current ++;
}
}
}
if ( cc == 0 ) break;
bmax = 0;
while ( NONEMPTY_STACKQ )
{
n_prscan2++;
STACKQ_POP ( i );
i_rank = i -> rank;
FOR_ALL_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
rc = REDUCED_COST ( i, j, a );
if ( rc < 0 )
{
dr = - rc;
if (( j_rank = dr + i_rank ) < dlinf )
{
if ( j_rank > j -> rank )
j -> rank = j_rank;
}
}
}
}
if ( i_rank > 0 )
{
if ( i_rank > bmax ) bmax = i_rank;
b = buckets + i_rank;
INSERT_TO_BUCKET ( i, b )
}
}
if ( bmax == 0 )
{ break; }
for ( b = buckets + bmax; b != buckets; b -- )
{
i_rank = b - buckets;
dp = (double) i_rank;
while ( NONEMPTY_BUCKET( b ) )
{
GET_FROM_BUCKET ( i, b )
n_prscan++;
FOR_ALL_ARCS_a_FROM_i
{
if ( OPEN ( a ) )
{
j = a -> head;
j_rank = j -> rank;
if ( j_rank < i_rank )
{
rc = REDUCED_COST ( i, j, a );
if ( rc < 0 )
j_new_rank = i_rank;
else
{
dr = rc;
j_new_rank = ( dr < dlinf ) ? i_rank - ( (long)dr + 1 )
: 0;
}
if ( j_rank < j_new_rank )
{
if ( cc == 1 )
{
j -> rank = j_new_rank;
if ( j_rank > 0 )
{
b_old = buckets + j_rank;
REMOVE_FROM_BUCKET ( j, b_old )
}
b_new = buckets + j_new_rank;
INSERT_TO_BUCKET ( j, b_new )
}
}
}
}
}
i -> price -= dp;
}
}
if ( cc == 0 ) break;
}
}
static void price_out ()
{
node *i;
arc *a,
*a_stop,
*b;
double n_cut_off,
rc;
n_cut_off = - cut_off;
FOR_ALL_NODES_i
{
FOR_ALL_ARCS_a_FROM_i
{
rc = REDUCED_COST ( i, a -> head, a );
if (((rc > cut_off) && (CLOSED(a -> sister)))
||
((rc < n_cut_off) && (CLOSED(a)))
)
{
b = ( i -> first ) ++ ;
EXCHANGE ( a, b );
}
}
}
}
static int update_epsilon()
{
if ( epsilon <= low_bound ) return ( 1 );
epsilon = ceil ( epsilon / f_scale );
cut_off = cut_off_factor * epsilon;
cut_on = cut_off * CUT_OFF_GAP;
return ( 0 );
}
static void finishup ( obj_ad )
double *obj_ad;
{
arc *a;
long na;
double obj_internal;
double cs;
long flow;
obj_internal = 0;
for ( a = arcs, na = 0; a != sentinel_arc ; a ++, na ++ )
{
cs = a -> cost;
if ( cap[na] > 0 && ( flow = cap[na] - (a -> r_cap) ) != 0 )
obj_internal += cs * (double) flow;
}
*obj_ad = obj_internal;
}
static void cs2 ( n_p, m_p, nodes_p, arcs_p, f_sc, max_c, cap_p, obj_ad)
long n_p,
m_p;
node *nodes_p;
arc *arcs_p;
long f_sc;
double max_c;
short *cap_p;
double *obj_ad;
{
int cc;
cs_init ( n_p, m_p, nodes_p, arcs_p, f_sc, max_c, cap_p );
cc = 0;
update_epsilon ();
do{
refine ();
if ( n_ref >= PRICE_OUT_START )
{
price_out ( );
}
if ( update_epsilon () ) break;
while ( 1 )
{
if ( ! price_refine () ) break;
if ( n_ref >= PRICE_OUT_START )
{
if ( price_in () )
{
break;
}
}
if ((cc = update_epsilon ())) break;
}
} while ( cc == 0 );
finishup ( obj_ad );
}
void SolveCS2(signed char **residue, short **mstcosts, long nrow, long ncol,
long cs2scalefactor, short ***flowsptr)
{
arc *arp;
node *ndp;
long n, m, m2, nmin;
node *i;
long ni;
arc *a;
long nNrow, nNcol;
long to, from, num, flow, ground;
long f_sc;
double cost, c_max;
short *cap;
short **rowcost, **colcost;
short **rowflow, **colflow;
nNrow=nrow-1;
nNcol=ncol-1;
ground=nNrow*nNcol+1;
rowcost=mstcosts;
colcost=&(mstcosts[nrow-1]);
f_sc=cs2scalefactor;
cs2mcfparse( residue,rowcost,colcost,nNrow,nNcol,
&n,&m,&ndp,&arp,&nmin,&c_max,&cap );
Free2DArray((void **)residue,nrow-1);
Free2DArray((void **)mstcosts,2*nrow-1);
fprintf(sp2,"Running cs2 MCF solver\n");
m2 = 2 * m;
cs2 ( n, m2, ndp, arp, f_sc, c_max, cap, &cost );
(*flowsptr)=(short **)Get2DRowColZeroMem(nrow,ncol,
sizeof(short *),sizeof(short));
rowflow=(*flowsptr);
colflow=&((*flowsptr)[nrow-1]);
for ( i = ndp; i < ndp + n; i ++ ){
ni = N_NODE ( i );
for ( a = i -> suspended; a != (i+1)->suspended; a ++ ){
if ( cap[ N_ARC (a) ] > 0 && (cap[ N_ARC (a) ] - ( a -> r_cap ) ) ){
from=ni;
to=N_NODE( a -> head );
flow=cap[ N_ARC (a) ] - ( a -> r_cap );
if(flow>LARGESHORT || flow<-LARGESHORT){
fprintf(sp0,"Flow will overflow short data type\nAbort\n");
exit(ABNORMAL_EXIT);
}
if((from==ground) || (to==ground)){
if(to==ground){
num=to;
to=from;
from=num;
flow=-flow;
}
if(!((to-1) % nNrow)){
colflow[0][(int )((to-1)/nNrow)]+=flow;
}else if(to<=nNrow){
rowflow[to-1][0]+=flow;
}else if(to>=(ground-nNrow-1)){
rowflow[(to-1) % nNrow][nNcol]-=flow;
}else if(!(to % nNrow)){
colflow[nNrow][(int )((to/nNrow)-1)]-=flow;
}else{
fprintf(sp0,"Unassigned ground arc parsing cs2 solution\nAbort\n");
exit(ABNORMAL_EXIT);
}
}else if(from==(to+1)){
num=from+(int )((from-1)/nNrow);
colflow[(num-1) % (nNrow+1)][(int )(num-1)/(nNrow+1)]-=flow;
}else if(from==(to-1)){
num=from+(int )((from-1)/nNrow)+1;
colflow[(num-1) % (nNrow+1)][(int )(num-1)/(nNrow+1)]+=flow;
}else if(from==(to-nNrow)){
num=from+nNrow;
rowflow[(num-1) % nNrow][(int )((num-1)/nNrow)]+=flow;
}else if(from==(to+nNrow)){
num=from;
rowflow[(num-1) % nNrow][(int )((num-1)/nNrow)]-=flow;
}else{
fprintf(sp0,"Non-grid arc parsing cs2 solution\nAbort\n");
exit(ABNORMAL_EXIT);
}
}
}
}
free(ndp-nmin);
free(arp);
free(cap);
free(buckets);
}
#endif