text: /* mockturtle: C++ logic network library
   * Copyright (C) 2018-2021  EPFL
   *
   * Permission is hereby granted, free of charge, to any person
   * obtaining a copy of this software and associated documentation
   * files (the "Software"), to deal in the Software without
   * restriction, including without limitation the rights to use,
   * copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following
   * conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
   * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
   * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
   * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   * OTHER DEALINGS IN THE SOFTWARE.
   */
  
  /*!
    \file mf_cut.hpp
    \brief Cut enumeration for MF mapping (see giaMf.c)
  
    \author Heinz Riener
    \author Mathias Soeken
  */
  
  #pragma once
  
  #include <algorithm>
  #include <cstdint>
  #include <iomanip>
  #include <iostream>
  
  #include "../cut_enumeration.hpp"
  
  namespace mockturtle
  {
  
  /*! \brief Cut implementation based on ABC's giaMf.c
  
    See <a href="https://github.com/berkeley-abc/abc/blob/master/src/aig/gia/giaMf.c">giaMf.c</a> in ABC's repository.
  */
  struct cut_enumeration_mf_cut
  {
    uint32_t delay{0};
    float flow{0};
    float cost{0};
  };
  
  template<bool ComputeTruth>
  bool operator<( cut_type<ComputeTruth, cut_enumeration_mf_cut> const& c1, cut_type<ComputeTruth, cut_enumeration_mf_cut> const& c2 )
  {
    constexpr auto eps{0.005f};
    if ( c1->data.flow < c2->data.flow - eps )
      return true;
    if ( c1->data.flow > c2->data.flow + eps )
      return false;
    if ( c1->data.delay < c2->data.delay )
      return true;
    if ( c1->data.delay > c2->data.delay )
      return false;
    return c1.size() < c2.size();
  }
  
  template<>
  struct cut_enumeration_update_cut<cut_enumeration_mf_cut>
  {
    template<typename Cut, typename NetworkCuts, typename Ntk>
    static void apply( Cut& cut, NetworkCuts const& cuts, Ntk const& ntk, node<Ntk> const& n )
    {
      uint32_t delay{0};
      float flow = cut->data.cost = cut.size() < 2 ? 0.0f : 1.0f;
  
      for ( auto leaf : cut )
      {
        const auto& best_leaf_cut = cuts.cuts( leaf )[0];
        delay = std::max( delay, best_leaf_cut->data.delay );
        flow += best_leaf_cut->data.flow;
      }
  
      cut->data.delay = 1 + delay;
      cut->data.flow = flow / ntk.fanout_size( n );
    }
  };
  
  template<int MaxLeaves>
  std::ostream& operator<<( std::ostream& os, cut<MaxLeaves, cut_data<false, cut_enumeration_mf_cut>> const& c )
  {
    os << "{ ";
    std::copy( c.begin(), c.end(), std::ostream_iterator<uint32_t>( os, " " ) );
    os << "}, D = " << std::setw( 3 ) << c->data.delay << " A = " << c->data.flow;
    return os;
  }
  
  } // namespace mockturtle