stlab.adobe.com Adobe Systems Incorporated

dancing_links.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /****************************************************************************************************/
00008 
00009 #ifndef ADOBE_dancing_links_t_HPP
00010 #define ADOBE_dancing_links_t_HPP
00011 
00012 /****************************************************************************************************/
00013 
00014 #include <adobe/config.hpp>
00015 
00016 #include <vector>
00017 
00018 #if ADOBE_STD_SERIALIZATION
00019 #include <iostream>
00020 #endif
00021 
00022 #include <boost/function.hpp>
00023 #include <boost/noncopyable.hpp>
00024 
00025 #include <adobe/implementation/toroid.hpp>
00026 
00027 #define ADOBE_DLX_VERBOSE 0
00028 
00029 #if ADOBE_STD_SERIALIZATION && ADOBE_DLX_VERBOSE
00030 #include <adobe/iomanip.hpp>
00031 #endif
00032 
00033 /****************************************************************************************************/
00034 
00035 namespace adobe {
00036 
00037 /****************************************************************************************************/
00038 
00039 #ifndef ADOBE_NO_DOCUMENTATION
00040 
00041 /****************************************************************************************************/
00042 
00043 namespace implementation {
00044 
00045 /****************************************************************************************************/
00046 
00047 struct do_nothing_callback_t
00048 {
00049     inline void operator () (std::size_t, bool) const
00050     { }
00051 };
00052 
00053 /****************************************************************************************************/
00054 
00055 struct select_right_heuristic_t
00056 {
00057     inline toroid_header_t* operator () (byte_toroid_t& toroid) const
00058         { return toroid.right_of(&toroid.header_m); }
00059 };
00060 
00061 /****************************************************************************************************/
00062 
00063 struct select_most_constrained_heuristic_t
00064 {
00065     inline toroid_header_t* operator () (byte_toroid_t& toroid) const
00066     {
00067         toroid_header_t* c(toroid.right_of(&toroid.header_m));
00068         std::size_t      sz(c->size_m);
00069 
00070         for (toroid_header_t* p(toroid.right_of(c)); p != &toroid.header_m; p = toroid.right_of(p))
00071         {
00072             if (p->size_m < sz)
00073             {
00074                 c = p;
00075                 sz = p->size_m;
00076             }
00077 
00078             if (sz == 1) break;
00079         }
00080 
00081         return c;
00082     }
00083 };
00084 
00085 /****************************************************************************************************/
00086 
00087 } // namespace implementation
00088 
00089 /****************************************************************************************************/
00090 
00091 #endif
00092 
00093 /****************************************************************************************************/
00094 
00095 class dancing_links_t : boost::noncopyable
00096 {
00097 public:
00098 #ifndef ADOBE_NO_DOCUMENTATION
00099     dancing_links_t(std::size_t row_count, std::size_t column_count) :
00100         toroid_m(row_count, column_count),
00101         output_m(column_count, 0),
00102         solutions_m(0)
00103 #if ADOBE_DLX_VERBOSE
00104         , tab_count_m(0)
00105 #endif
00106     { }
00107 #endif
00108 
00109     inline void set(std::size_t row, std::size_t col, char color = 0)
00110         { toroid_m.set(row, col, color); }
00111 
00112     inline void set_secondary_column(std::size_t col)
00113         { toroid_m.set_secondary_column(col); }
00114 
00115     template <typename ResultCallback, typename SearchHeuristic>
00116     inline std::size_t search(std::size_t     max_solutions,
00117                               ResultCallback  callback,
00118                               SearchHeuristic heuristic)
00119     {
00120         max_solutions_m = max_solutions;
00121 
00122         toroid_m.finalize();
00123 
00124         do_search(0, callback, heuristic);
00125 
00126         return solutions_m;
00127     }
00128 
00129     inline std::size_t search(std::size_t max_solutions)
00130     {
00131         return search(max_solutions,
00132                       implementation::do_nothing_callback_t(),
00133                       implementation::select_most_constrained_heuristic_t());
00134     }
00135 
00136 #if ADOBE_STD_SERIALIZATION
00137     friend std::ostream& operator<<(std::ostream& s, const dancing_links_t& dancing_links_t)
00138         { return s << dancing_links_t.toroid_m; }
00139 #endif
00140 
00141 private:
00142     template <typename ResultCallback, typename SearchHeuristic>
00143     void do_search(std::size_t k, ResultCallback callback, SearchHeuristic heuristic)
00144     {
00145         if (toroid_m.right_of(&toroid_m.header_m) == &toroid_m.header_m)
00146         {
00147             ++solutions_m;
00148 
00149             #if ADOBE_DLX_VERBOSE
00150             std::cout << adobe::indents(tab_count_m) << "<solved/>" << std::endl;
00151             #endif
00152 
00153             for (std::size_t i(0); i < k; ++i)
00154                 callback(toroid_m.row_index_of(output_m[i]), i + 1 == k);
00155 
00156             return;
00157         }
00158 
00159         std::size_t next_k(k + 1);
00160 
00161         toroid_header_t* c(heuristic(toroid_m));
00162 
00163         #if ADOBE_DLX_VERBOSE
00164         ++tab_count_m;
00165         std::cout << adobe::indents(tab_count_m) << "<c" << toroid_m.column_index_of(toroid_m.down_of(c)) << ">" << std::endl;
00166         #endif
00167 
00168         toroid_m.cover_column(c);
00169 
00170         // branch on each node in this column
00171         for (toroid_node_t* r(toroid_m.down_of(c)); r != c; r = toroid_m.down_of(r))
00172         {
00173             #if ADOBE_DLX_VERBOSE
00174             std::cout << adobe::indents(tab_count_m) << "<r" << toroid_m.row_index_of(r) << ">" << std::endl;
00175             #endif
00176 
00177             output_m[k] = r;
00178 
00179             // cover or purify each node on the same row as the node we're branching on
00180             for (toroid_node_t* j(toroid_m.right_of(r)); j != r; j = toroid_m.right_of(j))
00181             {
00182                 if (j->color_m == 0)
00183                 {
00184                     #if ADOBE_DLX_VERBOSE
00185                     std::cout << adobe::indents(tab_count_m) << "<c" << toroid_m.column_index_of(j) << ">" << std::endl;
00186                     #endif
00187                     toroid_m.cover_column(toroid_m.column_of(j));
00188                 }
00189                 else if (j->color_m > 0)
00190                 {
00191                     #if ADOBE_DLX_VERBOSE
00192                     std::cout << adobe::indents(tab_count_m) << "<p" << toroid_m.column_index_of(j) << ">" << std::endl;
00193                     #endif
00194                     toroid_m.purify(j);
00195                 }
00196             }
00197 
00198             #if ADOBE_DLX_VERBOSE
00199             // std::cout << *this << std::endl;
00200             #endif
00201 
00202             do_search(next_k, callback, heuristic);
00203 
00204             if (solutions_m >= max_solutions_m)
00205                 return;
00206 
00207             r = output_m[k];
00208 
00209             c = toroid_m.column_of(r);
00210 
00211             // undo the cover/purify
00212             for (toroid_node_t* j(toroid_m.left_of(r)); j != r; j = toroid_m.left_of(j))
00213             {
00214                 if (j->color_m == 0)
00215                 {
00216                     #if ADOBE_DLX_VERBOSE
00217                     std::cout << adobe::indents(tab_count_m) << "</c" << toroid_m.column_index_of(j) << ">" << std::endl;
00218                     #endif
00219                     toroid_m.uncover_column(toroid_m.column_of(j));
00220                 }
00221                 else if (j->color_m > 0)
00222                 {
00223                     #if ADOBE_DLX_VERBOSE
00224                     std::cout << adobe::indents(tab_count_m) << "</p" << toroid_m.column_index_of(j) << ">" << std::endl;
00225                     #endif
00226                     toroid_m.unpurify(j);
00227                 }
00228             }
00229 
00230             #if ADOBE_DLX_VERBOSE
00231             std::cout << adobe::indents(tab_count_m) << "</r" << toroid_m.row_index_of(r) << ">" << std::endl;
00232             #endif
00233         }
00234 
00235         toroid_m.uncover_column(c);
00236 
00237         #if ADOBE_DLX_VERBOSE
00238         std::cout << adobe::indents(tab_count_m) << "</c" << toroid_m.column_index_of(toroid_m.down_of(c)) << ">" << std::endl;
00239         --tab_count_m;
00240         #endif
00241     };
00242 
00243     byte_toroid_t               toroid_m;
00244     std::vector<toroid_node_t*> output_m;
00245     std::size_t                 solutions_m;
00246     std::size_t                 max_solutions_m;
00247 #if ADOBE_DLX_VERBOSE
00248     std::size_t                 tab_count_m;
00249 #endif
00250 };
00251 
00252 /****************************************************************************************************/
00253 
00254 } // namespace adobe
00255 
00256 /****************************************************************************************************/
00257 
00258 #endif
00259 
00260 /****************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google