Executing multiple self-avoiding walks, recursively

Self-avoiding walks has been studied at least since the 1960s and there's a vast literature on them. Fortunately, the problem you face belong to the simplest ones (walks' length is fixed at a relatively small value).

1

The first thing you should be aware of is that your question is too broad to have a unique answer. That is, if you plant many polymers in the system, the result you're going to get depends on the dynamics of the polymer planting and growing. There are two major cases. Either you plant a number of seeds and start growing polymers from them, or you grow each polymer "elsewhere" and then try to plant them in the system at a random location, one by one, keeping the condition of self-avoidance. The two methods will result in statistically different distributions of polymers, and there's nothing you can do about it, except to specify the system dynamics in more detail.

I believe the second approach is a bit easier, as it saves you from deciding what to do if some polymers cannot grow to the desired length (restart the simulation?), so let's focus just on it.

The general algorithm might look like this:

  • Set maximum_number_of_attempts to reasonably large, but not too large a value, say a million
  • Set required_number_of_polymers to the required value
  • Set number_of_attempts to 0
  • Set number_of_planted_polymers to 0
  • While number_of_attempts < maximum_number_of_attempts AND number_of_planted_polymers < required_number_of_polymers
    • increase number_of_attempts by 1
    • generate the next random polymer
    • chose a random position (lattice site) in the system
    • check if the polymer can be planted at this position without intersections
    • if and only if yes,
      • accept the polymer (add it to the list of polymers; update the list of occupied lattice nodes)
      • increase number_of_planted_polymers by 1

To speed thing up, you can be choosing the initial positions only from unoccupied sites (e.g. in a while loop). Another idea is to try and use a polymer, on its first plating failure, several times (but not too many, you'd need to experiment) at different positions.

2

Now the next step: how to generate a self-avoiding random walk. Your code is almost OK, except for a few misconceptions.

In function void Grid::plant_polymer there's one grave error: it always performs the search in the space of possible polymer shapes in exactly the same order. In other words, it is deterministic. For Monte Carlo methods it sounds like a disaster. One thing you might do to handle it is to randomly shuffle the directions.

  auto directions = drns;
  std::shuffle(begin(directions), end(directions), random_generator); // c++17
  for (const auto & v: directions)
  {
    ...

For this to work, you'll need a random number generator already defined and initialized, e.g.

    std::random_device rd;
    std::mt19937 random_generator(rd());

somewhere much earlier, and only once, in the program.

If you don't use C++17, use std::random_shuffle instead of std::shuffle, but be warned that the former has been depreciated, see https://en.cppreference.com/w/cpp/algorithm/random_shuffle for the discussion why.


As a side remark, when asking a specific software-related question, please try and provide a Minimal, reproducible example. Answering questions based only on reading code is almost always more time-consuming, and the answers tend to be more sketchy and less accurate.