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