text: /****************************************************************************
   * Copyright (C) from 2009 to Present EPAM Systems.
   *
   * This file is part of Indigo toolkit.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   ***************************************************************************/
  
  #ifndef __embedding_enumerator__
  #define __embedding_enumerator__
  
  #ifdef _WIN32
  #pragma warning(push)
  #pragma warning(disable : 4251)
  #endif
  
  #include "base_cpp/list.h"
  #include "base_cpp/obj_array.h"
  #include "base_cpp/red_black.h"
  #include "base_cpp/tlscont.h"
  #include "graph/graph_fast_access.h"
  
  namespace indigo
  {
  
      class Graph;
      class GraphVertexEquivalence;
      class CancellationHandler;
  
      class DLLEXPORT EmbeddingEnumerator
      {
      public:
          enum
          {
              UNMAPPED = -1,
              TERM_OUT = -2,
              IGNORE = -3
          };
  
          bool allow_many_to_one;
  
          EmbeddingEnumerator(Graph& supergraph);
  
          ~EmbeddingEnumerator();
  
          // when cb_embedding returns zero, enumeration stops
          int (*cb_embedding)(Graph& subgraph, Graph& supergraph, int* core_sub, int* core_super, void* userdata);
  
          bool (*cb_match_vertex)(Graph& subgraph, Graph& supergraph, const int* core_sub, int sub_idx, int super_idx, void* userdata);
          bool (*cb_match_edge)(Graph& subgraph, Graph& supergraph, int self_idx, int other_idx, void* userdata);
  
          void (*cb_vertex_remove)(Graph& subgraph, int sub_idx, void* userdata);
          void (*cb_edge_add)(Graph& subgraph, Graph& supergraph, int sub_idx, int super_idx, void* userdata);
          void (*cb_vertex_add)(Graph& subgraph, Graph& supergraph, int sub_idx, int super_idx, void* userdata);
          bool (*cb_allow_many_to_one)(Graph& subgraph, int sub_idx, void* userdata);
  
          void* userdata;
  
          void setSubgraph(Graph& subgraph);
  
          void ignoreSubgraphVertex(int idx);
          void ignoreSupergraphVertex(int idx);
  
          int countUnmappedSubgraphVertices();
          int countUnmappedSupergraphVertices();
  
          int countUnmappedSubgraphEdges();
          int countUnmappedSupergraphEdges();
  
          void setEquivalenceHandler(GraphVertexEquivalence* equivalence_handler);
  
          bool fix(int node1, int node2);
          bool unsafeFix(int node1, int node2);
  
          // returns 0 if cb_embedding returned 0, 1 otherwise
          int process();
          void processStart();
          bool processNext();
  
          const int* getSubgraphMapping();
  
          const int* getSupergraphMapping();
  
          // Update internal structures to fit all target vertices that might be added
          void validate();
  
          DECL_ERROR;
          DECL_TIMEOUT_EXCEPTION;
  
      protected:
          // digit 1 relates to the subgraph, 2 relates to the supergraph.
  
          Graph* _g1;
          Graph* _g2;
  
          GraphVertexEquivalence* _equivalence_handler;
  
          CP_DECL;
  
          TL_CP_DECL(Array<int>, _core_1);
          TL_CP_DECL(Array<int>, _core_2);
  
          TL_CP_DECL(Array<int>, _term2);
          TL_CP_DECL(Array<int>, _unterm2);
  
          TL_CP_DECL(Pool<RedBlackSet<int>::Node>, _s_pool);
  
          TL_CP_DECL(GraphFastAccess, _g1_fast);
          TL_CP_DECL(GraphFastAccess, _g2_fast);
  
          void _terminatePreviousMatch();
  
          //
          // Query nodes sequence calculation
          //
  
          struct _QuertMatchState
          {
              _QuertMatchState(int atom_index, int parent_index, int t1_len) : atom_index(atom_index), parent_index(parent_index), t1_len(t1_len)
              {
              }
              int atom_index, parent_index, t1_len;
          };
          TL_CP_DECL(Array<_QuertMatchState>, _query_match_state);
  
          void _fixNode1(int node1, int node2);
          int _getNextNode1();
          int _t1_len_pre;
  
          enum
          {
              _RETURN0 = 0,
              _NOWAY = 1,
              _ADD_PAIR = 2
          };
  
          class _Enumerator
          {
          public:
              _Enumerator(EmbeddingEnumerator& context);
              _Enumerator(const _Enumerator& other);
  
              bool fix(int node1, int node2, bool safe);
              void setUseEquivalence(bool use);
              void reset();
  
              int nextPair();
              void addPair(int node1, int node2);
              void restore();
  
              void initForFirstSearch(int t1_len);
  
              int _current_node1, _current_node2;
  
          protected:
              EmbeddingEnumerator& _context;
  
              bool _use_equivalence;
              RedBlackSet<int> _mapped_orbit_ids;
              int _term2_begin;
              int _unterm2_begin;
  
              int _core_len;
              int _t1_len, _t2_len;
              int _selected_node1, _selected_node2;
              int _node1_prev_value, _node2_prev_value;
  
              int _current_node1_idx, _current_node2_idx;
              int _current_node2_parent;
              int _current_node2_nei_index;
  
              bool _checkNode1(int node1);
              bool _checkNode2(int node2, int for_node1);
              bool _checkPair(int node1, int node2);
  
              void _initState();
  
              void _addPairNode2(int node1, int node2);
              void _fixPair(int node1, int node2);
          };
  
          TL_CP_DECL(ObjArray<_Enumerator>, _enumerators);
  
          int _cancellation_check_number;
          CancellationHandler* _cancellation_handler;
      };
  
  } // namespace indigo
  
  #ifdef _WIN32
  #pragma warning(pop)
  #endif
  
  #endif
  