00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00071
00072
00073 #ifndef __ENERGY_H__
00074 #define __ENERGY_H__
00075
00076 #include <assert.h>
00077 #include "graph.h"
00078
00079 template <typename captype, typename tcaptype, typename flowtype> class Energy: public Graph<captype,tcaptype,flowtype>
00080 {
00081 typedef Graph<captype,tcaptype,flowtype> GraphT;
00082 public:
00083 typedef typename GraphT::node_id Var;
00084
00085
00086
00087
00088
00089
00090 typedef captype Value;
00091 typedef flowtype TotalValue;
00092
00093
00094
00095
00096
00097
00098
00099 Energy(int var_num_max, int edge_num_max, void (*err_function)(char *) = NULL);
00100
00101
00102 ~Energy();
00103
00104
00105 Var add_variable(int num=1);
00106
00107
00108 void add_constant(Value E);
00109
00110
00111
00112
00113
00114 void add_term1(Var x,
00115 Value E0, Value E1);
00116
00117
00118
00119
00120
00121
00122 void add_term2(Var x, Var y,
00123 Value E00, Value E01,
00124 Value E10, Value E11);
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 void add_term3(Var x, Var y, Var z,
00139 Value E000, Value E001,
00140 Value E010, Value E011,
00141 Value E100, Value E101,
00142 Value E110, Value E111);
00143
00144
00145
00146
00147 TotalValue minimize();
00148
00149
00150
00151
00152
00153 int get_var(Var x);
00154
00155
00156
00157
00158
00159 private:
00160
00161
00162 TotalValue Econst;
00163 void (*error_function)(char *);
00164
00165
00166 };
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 template <typename captype, typename tcaptype, typename flowtype>
00187 inline Energy<captype,tcaptype,flowtype>::Energy(int var_num_max, int edge_num_max, void (*err_function)(char *)) : Graph<captype,tcaptype,flowtype>(var_num_max, edge_num_max, err_function)
00188 {
00189 Econst = 0;
00190 error_function = err_function;
00191 }
00192
00193 template <typename captype, typename tcaptype, typename flowtype>
00194 inline Energy<captype,tcaptype,flowtype>::~Energy() {}
00195
00196 template <typename captype, typename tcaptype, typename flowtype>
00197 inline typename Energy<captype,tcaptype,flowtype>::Var Energy<captype,tcaptype,flowtype>::add_variable(int num)
00198 { return GraphT::add_node(num); }
00199
00200 template <typename captype, typename tcaptype, typename flowtype>
00201 inline void Energy<captype,tcaptype,flowtype>::add_constant(Value A) { Econst += A; }
00202
00203 template <typename captype, typename tcaptype, typename flowtype>
00204 inline void Energy<captype,tcaptype,flowtype>::add_term1(Var x,
00205 Value A, Value B)
00206 {
00207 add_tweights(x, B, A);
00208 }
00209
00210 template <typename captype, typename tcaptype, typename flowtype>
00211 inline void Energy<captype,tcaptype,flowtype>::add_term2(Var x, Var y,
00212 Value A, Value B,
00213 Value C, Value D)
00214 {
00215
00216
00217
00218
00219
00220 add_tweights(x, D, A);
00221 B -= A; C -= D;
00222
00223
00224
00225
00226
00227
00228 assert(B + C >= 0);
00229 if (B < 0)
00230 {
00231
00232
00233
00234
00235 add_tweights(x, 0, B);
00236 add_tweights(y, 0, -B);
00237 add_edge(x, y, 0, B+C);
00238 }
00239 else if (C < 0)
00240 {
00241
00242
00243
00244
00245 add_tweights(x, 0, -C);
00246 add_tweights(y, 0, C);
00247 add_edge(x, y, B+C, 0);
00248 }
00249 else
00250 {
00251 add_edge(x, y, B, C);
00252 }
00253 }
00254
00255 template <typename captype, typename tcaptype, typename flowtype>
00256 inline void Energy<captype,tcaptype,flowtype>::add_term3(Var x, Var y, Var z,
00257 Value E000, Value E001,
00258 Value E010, Value E011,
00259 Value E100, Value E101,
00260 Value E110, Value E111)
00261 {
00262 register Value pi = (E000 + E011 + E101 + E110) - (E100 + E010 + E001 + E111);
00263 register Value delta;
00264 register Var u;
00265
00266 if (pi >= 0)
00267 {
00268 Econst += E111 - (E011 + E101 + E110);
00269
00270 add_tweights(x, E101, E001);
00271 add_tweights(y, E110, E100);
00272 add_tweights(z, E011, E010);
00273
00274 delta = (E010 + E001) - (E000 + E011);
00275 assert(delta >= 0);
00276 add_edge(y, z, delta, 0);
00277
00278 delta = (E100 + E001) - (E000 + E101);
00279 assert(delta >= 0);
00280 add_edge(z, x, delta, 0);
00281
00282 delta = (E100 + E010) - (E000 + E110);
00283 assert(delta >= 0);
00284 add_edge(x, y, delta, 0);
00285
00286 if (pi > 0)
00287 {
00288 u = add_variable();
00289 add_edge(x, u, pi, 0);
00290 add_edge(y, u, pi, 0);
00291 add_edge(z, u, pi, 0);
00292 add_tweights(u, 0, pi);
00293 }
00294 }
00295 else
00296 {
00297 Econst += E000 - (E100 + E010 + E001);
00298
00299 add_tweights(x, E110, E010);
00300 add_tweights(y, E011, E001);
00301 add_tweights(z, E101, E100);
00302
00303 delta = (E110 + E101) - (E100 + E111);
00304 assert(delta >= 0);
00305 add_edge(z, y, delta, 0);
00306
00307 delta = (E110 + E011) - (E010 + E111);
00308 assert(delta >= 0);
00309 add_edge(x, z, delta, 0);
00310
00311 delta = (E101 + E011) - (E001 + E111);
00312 assert(delta >= 0);
00313 add_edge(y, x, delta, 0);
00314
00315 u = add_variable();
00316 add_edge(u, x, -pi, 0);
00317 add_edge(u, y, -pi, 0);
00318 add_edge(u, z, -pi, 0);
00319 add_tweights(u, -pi, 0);
00320 }
00321 }
00322
00323 template <typename captype, typename tcaptype, typename flowtype>
00324 inline typename Energy<captype,tcaptype,flowtype>::TotalValue Energy<captype,tcaptype,flowtype>::minimize() {
00325 return Econst + GraphT::maxflow(); }
00326
00327 template <typename captype, typename tcaptype, typename flowtype>
00328 inline int Energy<captype,tcaptype,flowtype>::get_var(Var x) { return (int) what_segment(x); }
00329
00330 #endif