    // Copyright (C) 2012  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #ifndef DLIB_GENERAL_POTTS_PRoBLEM_H__
    #define DLIB_GENERAL_POTTS_PRoBLEM_H__

    #include "../graph_utils.h"
    #include "min_cut.h"
    #include <vector>

    namespace dlib
    {

    // ----------------------------------------------------------------------------------------

        namespace impl
        {
            template <
                typename graph_type
                >
            class general_potts_problem
            {

                const graph_type& g;
                std::vector<node_label>& labels;
            public:
                general_potts_problem (
                    const graph_type& g_,
                    std::vector<node_label>& labels_
                ) : g(g_), labels(labels_)
                {
                    labels.resize(g.number_of_nodes());
                }

                unsigned long number_of_nodes (
                ) const { return g.number_of_nodes(); }

                unsigned long number_of_neighbors (
                    unsigned long idx
                ) const { return g.node(idx).number_of_neighbors(); }

                unsigned long get_neighbor (
                    unsigned long idx,
                    unsigned long n
                ) const { return g.node(idx).neighbor(n).index(); }

                unsigned long get_neighbor_idx (
                    unsigned long idx1,
                    unsigned long idx2
                ) const
                {
                    for (unsigned long i = 0; i < g.node(idx1).number_of_neighbors(); ++i)
                    {
                        if (g.node(idx1).neighbor(i).index() == idx2)
                            return i;
                    }

                    // This should never ever execute
                    return 0;
                }

                void set_label (
                    const unsigned long& idx,
                    node_label value
                )
                {
                    labels[idx] = value;
                }

                node_label get_label (
                    const unsigned long& idx
                ) const { return labels[idx]; }

                typedef typename graph_type::edge_type value_type;

                value_type factor_value (
                    unsigned long idx
                ) const
                {
                    return g.node(idx).data;
                }

                value_type factor_value_disagreement (
                    unsigned long idx1,
                    unsigned long idx2
                ) const
                {
                    return edge(g, idx1, idx2);
                }

            };
        }

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_GENERAL_POTTS_PRoBLEM_H__