void Mutate()

in analytical_engine/core/fragment/dynamic_fragment.h [259:413]


  void Mutate(mutation_t& mutation) {
    vertex_t v;
    if (!mutation.vertices_to_remove.empty() &&
        static_cast<double>(mutation.vertices_to_remove.size()) /
                static_cast<double>(this->GetVerticesNum()) <
            0.1) {
      std::set<vertex_t> sparse_set;
      for (auto gid : mutation.vertices_to_remove) {
        if (Gid2Vertex(gid, v) && IsAliveVertex(v)) {
          if (IsInnerVertex(v)) {
            if (load_strategy_ == grape::LoadStrategy::kBothOutIn) {
              ie_.remove_vertex(v.GetValue());
            }
            oe_.remove_vertex(v.GetValue());
            iv_alive_.reset_bit(v.GetValue());
            --alive_ivnum_;
            is_selfloops_.reset_bit(v.GetValue());
          } else {
            ov_alive_.reset_bit(outerVertexLidToIndex(v.GetValue()));
          }
          sparse_set.insert(v);
        }
      }
      if (!sparse_set.empty()) {
        auto func = [&sparse_set](vid_t i, const nbr_t& e) {
          return sparse_set.find(e.neighbor) != sparse_set.end();
        };
        if (load_strategy_ == grape::LoadStrategy::kBothOutIn) {
          ie_.remove_if(func);
        }
        oe_.remove_if(func);
      }
    } else if (!mutation.vertices_to_remove.empty()) {
      grape::DenseVertexSet<vertices_t> dense_bitset(Vertices());
      for (auto gid : mutation.vertices_to_remove) {
        if (Gid2Vertex(gid, v) && IsAliveVertex(v)) {
          if (IsInnerVertex(v)) {
            if (load_strategy_ == grape::LoadStrategy::kBothOutIn) {
              ie_.remove_vertex(v.GetValue());
            }
            oe_.remove_vertex(v.GetValue());
            iv_alive_.reset_bit(v.GetValue());
            --alive_ivnum_;
            is_selfloops_.reset_bit(v.GetValue());
          } else {
            ov_alive_.reset_bit(outerVertexLidToIndex(v.GetValue()));
          }
          dense_bitset.Insert(v);
        }
      }
      auto func = [&dense_bitset](vid_t i, const nbr_t& e) {
        return dense_bitset.Exist(e.neighbor);
      };
      if (!dense_bitset.Empty()) {
        if (load_strategy_ == grape::LoadStrategy::kBothOutIn) {
          ie_.remove_if(func);
        }
        oe_.remove_if(func);
      }
    }
    if (!mutation.edges_to_remove.empty()) {
      removeEdges(mutation.edges_to_remove);
    }
    if (!mutation.edges_to_update.empty()) {
      for (auto& e : mutation.edges_to_update) {
        if (IsInnerVertexGid(e.src)) {
          e.src = id_parser_.get_local_id(e.src);
        } else {
          e.src = parseOuterVertexGid(e.src);
        }
        if (IsInnerVertexGid(e.dst)) {
          e.dst = id_parser_.get_local_id(e.dst);
        } else {
          e.dst = parseOuterVertexGid(e.dst);
        }
      }
      updateEdges(mutation.edges_to_update);
    }
    {
      auto& edges_to_add = mutation.edges_to_add;
      static constexpr vid_t invalid_vid = std::numeric_limits<vid_t>::max();
      vid_t old_ovnum = ovgid_.size();

      // parseOrAddOuterVertexGid will update ovnum_
      for (auto& e : edges_to_add) {
        if (IsInnerVertexGid(e.src)) {
          e.src = id_parser_.get_local_id(e.src);
          if (IsInnerVertexGid(e.dst)) {
            e.dst = id_parser_.get_local_id(e.dst);
          } else {
            mutation.vertices_to_add.emplace_back(e.dst);
            e.dst = parseOrAddOuterVertexGid(e.dst);
          }
        } else {
          if (IsInnerVertexGid(e.dst)) {
            mutation.vertices_to_add.emplace_back(e.src);
            e.src = parseOrAddOuterVertexGid(e.src);
            e.dst = id_parser_.get_local_id(e.dst);
          } else {
            e.src = invalid_vid;
          }
        }
      }
      vid_t new_ivnum = vm_ptr_->GetInnerVertexSize(fid_);
      vid_t new_ovnum = ovgid_.size();
      assert(new_ovnum == ovnum_);
      assert(new_ivnum >= ivnum_ && new_ovnum >= old_ovnum);
      is_selfloops_.resize(new_ivnum);
      oe_.add_vertices(new_ivnum - ivnum_, new_ovnum - old_ovnum);
      ie_.add_vertices(new_ivnum - ivnum_, new_ovnum - old_ovnum);
      this->ivnum_ = new_ivnum;
      if (old_ovnum != new_ovnum) {
        initOuterVerticesOfFragment();
      }
      if (!edges_to_add.empty()) {
        addEdges(edges_to_add);
      }

      this->inner_vertices_.SetRange(0, new_ivnum);
      this->outer_vertices_.SetRange(id_parser_.max_local_id() - new_ovnum,
                                     id_parser_.max_local_id());
      this->vertices_.SetRange(0, new_ivnum,
                               id_parser_.max_local_id() - new_ovnum,
                               id_parser_.max_local_id());
    }
    ivdata_.resize(this->ivnum_, dynamic::Value(rapidjson::kObjectType));
    iv_alive_.resize(this->ivnum_);
    ov_alive_.resize(this->ovnum_);
    alive_ovnum_ = this->ovnum_;
    for (auto& v : mutation.vertices_to_add) {
      vid_t lid;
      if (IsInnerVertexGid(v.vid)) {
        this->InnerVertexGid2Lid(v.vid, lid);
        ivdata_[lid].Update(v.vdata);
        if (iv_alive_.get_bit(lid) == false) {
          iv_alive_.set_bit(lid);
          ++alive_ivnum_;
        }
      } else {
        if (this->OuterVertexGid2Lid(v.vid, lid)) {
          auto index = outerVertexLidToIndex(lid);
          if (ov_alive_.get_bit(index) == false) {
            ov_alive_.set_bit(index);
          }
        }
      }
    }
    for (auto& v : mutation.vertices_to_update) {
      vid_t lid;
      if (IsInnerVertexGid(v.vid)) {
        this->InnerVertexGid2Lid(v.vid, lid);
        ivdata_[lid] = std::move(v.vdata);
      }
    }
  }