//===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// PBQP Graph class.
//
//===----------------------------------------------------------------------===//


#ifndef LLVM_CODEGEN_PBQP_GRAPH_H
#define LLVM_CODEGEN_PBQP_GRAPH_H

#include "Math.h"

#include <list>
#include <map>

namespace PBQP {

  /// PBQP Graph class.
  /// Instances of this class describe PBQP problems.
  class Graph {
  private:

    // ----- TYPEDEFS -----
    class NodeEntry;
    class EdgeEntry;

    typedef std::list<NodeEntry> NodeList;
    typedef std::list<EdgeEntry> EdgeList;

  public:

    typedef NodeList::iterator NodeItr;
    typedef NodeList::const_iterator ConstNodeItr;

    typedef EdgeList::iterator EdgeItr;
    typedef EdgeList::const_iterator ConstEdgeItr;

  private:

    typedef std::list<EdgeItr> AdjEdgeList;
  
  public:

    typedef AdjEdgeList::iterator AdjEdgeItr;

  private:

    class NodeEntry {
    private:
      Vector costs;      
      AdjEdgeList adjEdges;
      unsigned degree;
      void *data;
    public:
      NodeEntry(const Vector &costs) : costs(costs), degree(0) {}
      Vector& getCosts() { return costs; }
      const Vector& getCosts() const { return costs; }
      unsigned getDegree() const { return degree; }
      AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
      AdjEdgeItr edgesEnd() { return adjEdges.end(); }
      AdjEdgeItr addEdge(EdgeItr e) {
        ++degree;
        return adjEdges.insert(adjEdges.end(), e);
      }
      void removeEdge(AdjEdgeItr ae) {
        --degree;
        adjEdges.erase(ae);
      }
      void setData(void *data) { this->data = data; }
      void* getData() { return data; }
    };

    class EdgeEntry {
    private:
      NodeItr node1, node2;
      Matrix costs;
      AdjEdgeItr node1AEItr, node2AEItr;
      void *data;
    public:
      EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs)
        : node1(node1), node2(node2), costs(costs) {}
      NodeItr getNode1() const { return node1; }
      NodeItr getNode2() const { return node2; }
      Matrix& getCosts() { return costs; }
      const Matrix& getCosts() const { return costs; }
      void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
      AdjEdgeItr getNode1AEItr() { return node1AEItr; }
      void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; }
      AdjEdgeItr getNode2AEItr() { return node2AEItr; }
      void setData(void *data) { this->data = data; }
      void *getData() { return data; }
    };

    // ----- MEMBERS -----

    NodeList nodes;
    unsigned numNodes;

    EdgeList edges;
    unsigned numEdges;

    // ----- INTERNAL METHODS -----

    NodeEntry& getNode(NodeItr nItr) { return *nItr; }
    const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; }

    EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; }
    const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; }

    NodeItr addConstructedNode(const NodeEntry &n) {
      ++numNodes;
      return nodes.insert(nodes.end(), n);
    }

    EdgeItr addConstructedEdge(const EdgeEntry &e) {
      assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() &&
             "Attempt to add duplicate edge.");
      ++numEdges;
      EdgeItr edgeItr = edges.insert(edges.end(), e);
      EdgeEntry &ne = getEdge(edgeItr);
      NodeEntry &n1 = getNode(ne.getNode1());
      NodeEntry &n2 = getNode(ne.getNode2());
      // Sanity check on matrix dimensions:
      assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
             (n2.getCosts().getLength() == ne.getCosts().getCols()) &&
             "Edge cost dimensions do not match node costs dimensions.");
      ne.setNode1AEItr(n1.addEdge(edgeItr));
      ne.setNode2AEItr(n2.addEdge(edgeItr));
      return edgeItr;
    }

    inline void copyFrom(const Graph &other);
  public:

    /// \brief Construct an empty PBQP graph.
    Graph() : numNodes(0), numEdges(0) {}

    /// \brief Copy construct this graph from "other". Note: Does not copy node
    ///        and edge data, only graph structure and costs.
    /// @param other Source graph to copy from.
    Graph(const Graph &other) : numNodes(0), numEdges(0) {
      copyFrom(other);
    }

    /// \brief Make this graph a copy of "other". Note: Does not copy node and
    ///        edge data, only graph structure and costs.
    /// @param other The graph to copy from.
    /// @return A reference to this graph.
    ///
    /// This will clear the current graph, erasing any nodes and edges added,
    /// before copying from other.
    Graph& operator=(const Graph &other) {
      clear();      
      copyFrom(other);
      return *this;
    }

    /// \brief Add a node with the given costs.
    /// @param costs Cost vector for the new node.
    /// @return Node iterator for the added node.
    NodeItr addNode(const Vector &costs) {
      return addConstructedNode(NodeEntry(costs));
    }

    /// \brief Add an edge between the given nodes with the given costs.
    /// @param n1Itr First node.
    /// @param n2Itr Second node.
    /// @return Edge iterator for the added edge.
    EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr,
                    const Matrix &costs) {
      assert(getNodeCosts(n1Itr).getLength() == costs.getRows() &&
             getNodeCosts(n2Itr).getLength() == costs.getCols() &&
             "Matrix dimensions mismatch.");
      return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); 
    }

    /// \brief Get the number of nodes in the graph.
    /// @return Number of nodes in the graph.
    unsigned getNumNodes() const { return numNodes; }

    /// \brief Get the number of edges in the graph.
    /// @return Number of edges in the graph.
    unsigned getNumEdges() const { return numEdges; }

    /// \brief Get a node's cost vector.
    /// @param nItr Node iterator.
    /// @return Node cost vector.
    Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); }

    /// \brief Get a node's cost vector (const version).
    /// @param nItr Node iterator.
    /// @return Node cost vector.
    const Vector& getNodeCosts(ConstNodeItr nItr) const {
      return getNode(nItr).getCosts();
    }

    /// \brief Set a node's data pointer.
    /// @param nItr Node iterator.
    /// @param data Pointer to node data.
    ///
    /// Typically used by a PBQP solver to attach data to aid in solution.
    void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); }

    /// \brief Get the node's data pointer.
    /// @param nItr Node iterator.
    /// @return Pointer to node data.
    void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); }
    
    /// \brief Get an edge's cost matrix.
    /// @param eItr Edge iterator.
    /// @return Edge cost matrix.
    Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); }

    /// \brief Get an edge's cost matrix (const version).
    /// @param eItr Edge iterator.
    /// @return Edge cost matrix.
    const Matrix& getEdgeCosts(ConstEdgeItr eItr) const {
      return getEdge(eItr).getCosts();
    }

    /// \brief Set an edge's data pointer.
    /// @param eItr Edge iterator.
    /// @param data Pointer to edge data.
    ///
    /// Typically used by a PBQP solver to attach data to aid in solution.
    void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); }

    /// \brief Get an edge's data pointer.
    /// @param eItr Edge iterator.
    /// @return Pointer to edge data. 
    void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); }

    /// \brief Get a node's degree.
    /// @param nItr Node iterator.
    /// @return The degree of the node.
    unsigned getNodeDegree(NodeItr nItr) const {
      return getNode(nItr).getDegree();
    }

    /// \brief Begin iterator for node set.
    NodeItr nodesBegin() { return nodes.begin(); }

    /// \brief Begin const iterator for node set.
    ConstNodeItr nodesBegin() const { return nodes.begin(); }

    /// \brief End iterator for node set.
    NodeItr nodesEnd() { return nodes.end(); }

    /// \brief End const iterator for node set.
    ConstNodeItr nodesEnd() const { return nodes.end(); }

    /// \brief Begin iterator for edge set.
    EdgeItr edgesBegin() { return edges.begin(); }

    /// \brief End iterator for edge set.
    EdgeItr edgesEnd() { return edges.end(); }

    /// \brief Get begin iterator for adjacent edge set.
    /// @param nItr Node iterator.
    /// @return Begin iterator for the set of edges connected to the given node.
    AdjEdgeItr adjEdgesBegin(NodeItr nItr) {
      return getNode(nItr).edgesBegin();
    }

    /// \brief Get end iterator for adjacent edge set.
    /// @param nItr Node iterator.
    /// @return End iterator for the set of edges connected to the given node.
    AdjEdgeItr adjEdgesEnd(NodeItr nItr) {
      return getNode(nItr).edgesEnd();
    }

    /// \brief Get the first node connected to this edge.
    /// @param eItr Edge iterator.
    /// @return The first node connected to the given edge. 
    NodeItr getEdgeNode1(EdgeItr eItr) {
      return getEdge(eItr).getNode1();
    }

    /// \brief Get the second node connected to this edge.
    /// @param eItr Edge iterator.
    /// @return The second node connected to the given edge. 
    NodeItr getEdgeNode2(EdgeItr eItr) {
      return getEdge(eItr).getNode2();
    } 

    /// \brief Get the "other" node connected to this edge.
    /// @param eItr Edge iterator.
    /// @param nItr Node iterator for the "given" node.
    /// @return The iterator for the "other" node connected to this edge. 
    NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) {
      EdgeEntry &e = getEdge(eItr);
      if (e.getNode1() == nItr) {
        return e.getNode2();
      } // else
      return e.getNode1();
    }

    /// \brief Get the edge connecting two nodes.
    /// @param n1Itr First node iterator.
    /// @param n2Itr Second node iterator.
    /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists,
    ///         otherwise returns edgesEnd(). 
    EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) {
      for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr);
         aeItr != aeEnd; ++aeItr) {
        if ((getEdgeNode1(*aeItr) == n2Itr) ||
            (getEdgeNode2(*aeItr) == n2Itr)) {
          return *aeItr;
        }
      }
      return edges.end();
    }

    /// \brief Remove a node from the graph.
    /// @param nItr Node iterator.
    void removeNode(NodeItr nItr) {
      NodeEntry &n = getNode(nItr);
      for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) {
        EdgeItr eItr = *itr;
        ++itr;
        removeEdge(eItr); 
      }
      nodes.erase(nItr);
      --numNodes;
    }

    /// \brief Remove an edge from the graph.
    /// @param eItr Edge iterator.
    void removeEdge(EdgeItr eItr) {
      EdgeEntry &e = getEdge(eItr);
      NodeEntry &n1 = getNode(e.getNode1());
      NodeEntry &n2 = getNode(e.getNode2());
      n1.removeEdge(e.getNode1AEItr());
      n2.removeEdge(e.getNode2AEItr());
      edges.erase(eItr);
      --numEdges;
    }

    /// \brief Remove all nodes and edges from the graph.
    void clear() {
      nodes.clear();
      edges.clear();
      numNodes = numEdges = 0;
    }

    /// \brief Print a representation of this graph in DOT format.
    /// @param os Output stream to print on.
    template <typename OStream>
    void printDot(OStream &os) {
    
      os << "graph {\n";

      for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
           nodeItr != nodeEnd; ++nodeItr) {

        os << "  node" << nodeItr << " [ label=\""
           << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n";
      }

      os << "  edge [ len=" << getNumNodes() << " ]\n";

      for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
           edgeItr != edgeEnd; ++edgeItr) {

        os << "  node" << getEdgeNode1(edgeItr)
           << " -- node" << getEdgeNode2(edgeItr)
           << " [ label=\"";

        const Matrix &edgeCosts = getEdgeCosts(edgeItr);

        for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
          os << edgeCosts.getRowAsVector(i) << "\\n";
        }
        os << "\" ]\n";
      }
      os << "}\n";
    }

  };

  class NodeItrComparator {
  public:
    bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const {
      return &*n1 < &*n2;
    }

    bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const {
      return &*n1 < &*n2;
    }
  };

  class EdgeItrCompartor {
  public:
    bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const {
      return &*e1 < &*e2;
    }

    bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const {
      return &*e1 < &*e2;
    }
  };

  void Graph::copyFrom(const Graph &other) {
    std::map<Graph::ConstNodeItr, Graph::NodeItr,
             NodeItrComparator> nodeMap;

     for (Graph::ConstNodeItr nItr = other.nodesBegin(),
                             nEnd = other.nodesEnd();
         nItr != nEnd; ++nItr) {
      nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
    }
      
  }

}

#endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
