This is a real, recurring, error prone job with no free tool for it, and the errors it produces are quiet ones. A PCI collision does not throw an exception, it degrades handovers in one part of the network. A PRACH root reused too close does not fail outright, it makes random access intermittent for some users some of the time. Both are the kind of fault that gets blamed on coverage for months.
Most of the time the job is not greenfield. A systems integrator is handed a network that is already on air and asked to add a site, or to check that what is configured is sound. So the planner takes the existing plan as fact. A cell pasted with its PCI and root keeps them, the new cells are placed around them, and a conflict that was already there is reported as pre-existing rather than blamed on the new plan. Paste the whole network locked and the tool audits it instead of planning it.
Every rule is a statement about neighbours, so the neighbour graph decides the plan. On a live network it should be the eNB's own neighbour relation table or a drive-test overlap list, pasted as pairs and used as given. Without one, geometry stands in, two cells being neighbours when their separation is within a threshold times the sum of their radii, and the result says which source was used wherever it matters.
PCI allocation runs over the 504 identities that TS 36.211 clause 6.11 defines as 168 cell groups times three identities. Five rules can be enabled independently: no collision, where neighbours share a PCI and a UE cannot resolve them; no confusion, where two neighbours of the same cell share one and the serving cell cannot resolve them; and avoiding the same PCI mod 3, mod 6 and mod 30 between neighbours. Those last three are not arbitrary conventions. Mod 3 selects the primary synchronisation sequence. Mod 6 is the cell specific reference signal frequency shift v_shift from clause 6.10.1.2. Mod 30 selects the uplink demodulation reference signal base sequence group from clause 5.5.1.3. Each is explained on the panel rather than just named, including that mod 3 subsumes mod 6, so enabling both is not twice the constraint.
The allocator orders cells by neighbour degree and backtracks. When the rules cannot all be met it gives them up one at a time, never collision, and says which ones it gave up and between which cells. Twelve cells that all hear each other cannot avoid sharing a PCI mod 3, because mod 3 has only three classes, and a tool that returns twelve PCIs for that input without saying so has quietly dropped the rule it was asked to hold. The finished allocation is then re-checked by code that did not produce it, against the rules that were asked for, so a bug in the allocator cannot certify itself.
The PRACH side follows a chain where every link can be got wrong. The largest cell fixes the smallest usable cyclic shift N_CS. N_CS fixes how many preambles come from one root sequence, as the floor of 839 over N_CS. That fixes how many roots each cell needs to reach its 64 preambles. And that fixes how many cells the 838 logical root indices can serve before one has to be reused. Reuse that cannot be avoided is placed between cells that are not neighbours, and any that remains between neighbours is named. The result is shown in three groups, what TS 36.211 specifies, what was assumed and what was derived, so the one assumption in the chain, the multipath allowance, cannot be mistaken for a 3GPP value.