void LiveWLdiagram :: updateZe_ab ()
{
    int online_worms = int(mob_a.online()) + int(mob_b.online());

    // No worm in the diagram
    if (online_worms == 0) {
        // Insert the first worm:
        int    comp  = rand.choice2();
        int    site  = rand.choice (Diagram::SITEN);
        double time  = Wld::Diag::BETA * rand.uniform();
        bool   up    = rand.choice2();
        bool   creat = rand.choice2();

        Iter it_goal = Wld::Diag::find_aft (site, time);
        int ninit = it_goal->z.nbef(comp);
        // Check whether cannot creat or annihilate particle anymore
        if (check_nlimit (ninit, creat, nMAX, nMIN)) {

            Worm& mob = comp ? mob_b : mob_a;
            Iter& fix = comp ? fix_b : fix_a;
            insert (it_goal, comp, time, creat, up, mob, fix);
        }
    }
    else if (online_worms == 1) {

        Worm& mob_on = mob_a.online() ? mob_a : mob_b;
        Iter& fix_on = mob_a.online() ? fix_a : fix_b;
        // 1. Insert another worm:
        if (rand.uniform() < Pab) {

            int   comp_on  = mob_a.online() ? 0 : 1;
            int   comp_off = !comp_on;
            Worm& mob_off  = mob_a.online() ? mob_b : mob_a;
            Iter& fix_off  = mob_a.online() ? fix_b : fix_a;

            int    site  = fix_on->site();
            double time  = fix_on->time();
            bool   up    = rand.choice2();
            bool   creat = mob_on.it()->z.creat() ? !up : up; // For PSF. Opposite for SCF.

            Iter it_goal = Wld::Diag::find_aft (site, time);
            int ninit = it_goal->z.nbef (comp_off);
            if (check_nlimit (ninit, creat, nMAX, nMIN)) {

                insert (it_goal, comp_off, time, creat, up, mob_off, fix_off);
            }
        }
        // 2. Worm can global move.
        else {
            updateZe_to_halt (mob_on);
        }
    }
    else if (online_worms == 2) {
        int   comp = rand.choice2();
        Worm& mob  = (comp == 0 ? mob_a : mob_b);
        Iter& fix  = (comp == 0 ? fix_a : fix_b);
        updateZe_to_halt (mob);
    }
}
inline LiveWLdiagram::Status LiveWLdiagram :: updateZe (Worm& worm)
{
  double Ewalk = walk_energy (worm.it(), worm.up());
  double dtime = -log (rand.uniform()) / Ewalk;

  Iter it_block;
  Status stat  = walk (dtime, worm, it_block);

  #ifdef PRINT_STATUS
  cout << _printi << setw(16) << left << "  walk "+string(worm.up() ? "up" : "down")+": " << to_str(stat) << endl;
  #endif

  ActStatus astat = act (worm, stat, Ewalk, it_block);

  #ifdef PRINT_STATUS
  cout << _printi << setw(16) << left << "  act: " << to_str(astat) << endl;
  _printi++;
  #endif

  return stat;
}
LiveWLdiagram::ActStatus LiveWLdiagram :: act (Worm& worm, Status stat, double Ewalk, const Iter& it_block)
// Member-functions used in this function (like hop, relink_hop,...)
// should not specify the base class (for example: don't use WLdiagram::hop,...),
// so that the higher-level class (InfoWLdiagram) can overload them.
{
  table.clear();
  int site = worm.it()->site();
  int comp = worm.it()->z.comp();

  if (stat == FREE) {
    // 1.1 bounce
    table.add (Ewalk);
    // 1.2 insert interaction
    for(int nbi = 0; nbi < Wld::Diag::_latt(site).nbs(); ++nbi) {
      int  n     = worm.it()->assoc(nbi)->z.nbef(comp);
      bool creat = (worm.up() != worm.it()->z.creat());
      if (check_nlimit (n, creat, nMAX, nMIN)) {
        // Check whether cannot creat or annihilate particle anymore
        int dir = _latt(site).nbdir(nbi);
        double weight = BH_t(comp,dir) * (creat ? n+1 : n);
        table.add (weight, nbi);
      }
    }
    // 1.3 choose
  #ifdef LOCAL_OPTIMAL
    table.locally_optimal();
  #endif
    int choice = table.get_choice (rand.uniform());
    if (choice == 0) {
      bounce (worm);
      return ACT_BOUNCE;
    }
    else {
      hop (worm, table.nbi(choice));
      return ACT_HOP;
    }
  }
  else if (stat == HALTED) {

    Iter it_to = it_block->conj(); // 'it_to' is the to-node in remove case, or the middle-node in relink case

    // 2.1 bounce
    int dir = _latt.dir (site, it_to->site());
    double weight = BH_t(comp,dir) * (worm.it()->z.creat() ? worm.it()->z.naft(comp) : worm.it()->z.nbef(comp));
    table.add (weight);

    // 2.2 remove interaction
     double Ebef = diagonal_energy (it_to, it_to->z.nbef(0), it_to->z.nbef(1));
     double Eaft = diagonal_energy (it_to, it_to->z.naft(0), it_to->z.naft(1));
     if (worm.up())
        weight = shift_energy (Eaft, Ebef);
     else
        weight = shift_energy (Ebef, Eaft);
     table.add (weight);

    // 2.3 relink interaction
    for(int nbi = 0; nbi < Wld::Diag::_latt(it_to->site()).nbs(); ++nbi) {
      Iter it_nb = it_to->assoc(nbi);
      if (it_nb->site() != worm.it()->site()) {
        // Check whether relink to the self site
        int n = it_nb->z.nbef(comp);
        bool creat = (worm.up() == worm.it()->z.creat());
        if (check_nlimit (n, creat, nMAX, nMIN)) {
          // Check whether cannot creat or annihilate particle anymore
          int dir = _latt(site).nbdir(nbi);
          weight = BH_t(comp,dir) * (creat ? n+1 : n);
          table.add (weight, nbi);
        }
      }
    }
    // 2.4 choose
  #ifdef LOCAL_OPTIMAL
    table.locally_optimal();
  #endif
    int choice = table.get_choice (rand.uniform());
    if (choice == 0) {
      bounce (worm);
      return ACT_BOUNCE;
    }
    else if (choice == 1) {
      delete_hop (worm);
      return ACT_DELETE_HOP;
    }
    else {
      relink_hop (worm, table.nbi(choice));
      return ACT_RELINK_HOP;
    }
  }
  else if (stat == CRASH) {
    remove (worm);
    return ACT_REMOVE_WORMS;
  }

  return ACT_NOTHING;
}