Example #1
1
INLINE_IF_HEADER_ONLY void MorseDecomposition::
assign ( Digraph const& digraph, 
         Components const& components ) {
  data_ . reset ( new MorseDecomposition_ );
  data_ -> components_ = components;

  uint64_t C = components . size ();
  uint64_t R = components . recurrentComponents () . size ();
  std::vector<std::vector<uint64_t>> reachability ( R );
  std::vector<uint64_t> recurrent_indices;
  for ( uint64_t i = 0; i < C; ++ i ) {
    if ( components . isRecurrent ( i ) ) {
      recurrent_indices . push_back ( i );
    }
  }
  // Proceed in cohorts of 64 recurrent components. There are ceil(R/64) cohorts
  uint64_t num_cohorts = R / 64;
  if ( R % 64 != 0 ) ++ num_cohorts; // Round up for ceiling
  std::vector<uint64_t> reach_info ( C, 0 );
  for ( uint64_t cohort = 0; cohort < num_cohorts; ++ cohort ) {
    if ( cohort > 0 ) std::fill ( reach_info.begin(), reach_info.end(), 0);
    uint64_t source = 64LL*cohort;
    // Give each recurrent component in the cohort a unique bit signature
    // e.g. the 5th component gets 000...00010000
    for ( uint64_t i = 0; i < 64; ++ i, ++ source ) {
      if ( source == R ) break;
      reach_info [ recurrent_indices [ source ] ] = (1LL << i);
    }
    // Propagate reachability information by bitwise-oring bit signatures
    uint64_t parent_comp = 0;
    for ( auto const& component : components ) { 
      for ( uint64_t u : component ) {
        std::vector<uint64_t> const& children = digraph . adjacencies ( u );
        for ( uint64_t v : children ) {
          uint64_t child_comp = components . whichComponent ( v );
          reach_info [ child_comp ] |= reach_info [ parent_comp ];
        }
      }
      ++ parent_comp;
    }
    for ( uint64_t i = 0; i < R; ++ i ) {
      uint64_t code = reach_info [ recurrent_indices [ i ] ];
      uint64_t ancestor = 64*cohort;
      while ( code != 0 ) {
        if ( code & 1 ) reachability[ancestor].push_back(i);
        code >>= 1;
        ++ ancestor;
      }
    }
  } 
  data_ -> poset_ = Poset(reachability);
  _canonicalize ();
}
Example #2
0
INLINE_IF_HEADER_ONLY void MorseDecomposition::
assign ( Digraph const& digraph, 
         Components const& components ) {
  data_ . reset ( new MorseDecomposition_ );
  data_ -> poset_ = Poset ();
  data_ -> components_ = components;

  uint64_t C = components . size ();
  uint64_t R = components . recurrentComponents () . size ();
  std::vector<uint64_t> recurrent_indices;
  for ( uint64_t i = 0; i < C; ++ i ) {
    if ( components . isRecurrent ( i ) ) {
      recurrent_indices . push_back ( i );
      data_ -> poset_ . add_vertex ();
    }
  }
  // Proceed in cohorts of 64
  uint64_t num_cohorts = R / 64;
  if ( R % 64 != 0 ) ++ num_cohorts;
  std::vector<uint64_t> reach_info ( C, 0 );
  for ( uint64_t cohort = 0; cohort < num_cohorts; ++ cohort ) {
    if ( cohort > 0 ) std::fill ( reach_info.begin(), reach_info.end(), 0);
    uint64_t source = 64LL*cohort;
    for ( uint64_t i = 0; i < 64; ++ i, ++ source ) {
      if ( source == R ) break;
      reach_info [ recurrent_indices [ source ] ] = (1LL << i);
    }
    uint64_t parent_comp = 0;
    for ( auto const& component : components ) { 
      for ( uint64_t u : component ) {
        std::vector<uint64_t> const& children = digraph . adjacencies ( u );
        for ( uint64_t v : children ) {
          uint64_t child_comp = components . whichComponent ( v );
          reach_info [ child_comp ] |= reach_info [ parent_comp ];
        }
      }
      ++ parent_comp;
    }
    for ( uint64_t i = 0; i < R; ++ i ) {
      uint64_t code = reach_info [ recurrent_indices [ i ] ];
      uint64_t ancestor = 64*cohort;
      while ( code != 0 ) {
        if ( code & 1 ) data_ -> poset_ . add_edge ( ancestor, i );
        code >>= 1;
        ++ ancestor;
      }
    }
  } 
  data_ -> poset_ . reduction ();
  _canonicalize ();
}