**Algorithm 2** Soft-collision M\*.

**Input:** *vs*: source joint vertex; *vd*: destination joint vertex; {*V*, *E*}: joint configuration graph; *A*: list of resources **Output:** Path finding results 1: **for** all *vk* in *V* **do** 2: *vk*.cost ← +∞ 3: *vk*.exp ← all zero experience 4: *Ck* ← ∅ 5: *vk*.traceBack ← ∅ 6: **end for** 7: *vs*.cost ← 0 8: open ← {*vs*} 9: **while** open= ∅ **do** 10: open.sort() by *v*.cost+heuristic[*v*] //i.e., sort the open list from small to large 11: *vk* ← open.pop() 12: **if** *vk* = *vd* **then** 13: **return** back\_track\_path[*vk*] //optimal path found 14: **end if** 15: **if** *ψ*(*vk*) = ∅ **then** 16: **continue** //skip the vertex in collisions 17: **end if** 18: conduct the construction of *Vnbh <sup>k</sup>* using Equation (4) 19: **for** *vl* in *Vnbh <sup>k</sup>* **do** 20: add *vl* to *Vk* //note *Vk* <sup>=</sup> {*vq*|∃*π*(*vk*, *vq*) <sup>⊆</sup> *<sup>G</sup>exp*} 21: *vl* ← experience(*vk*, *vl*, *A*) //update experience using Algorithm 1 22: *Cl* ← *Cl* ∪ *ψ*(*vl*) 23: backpro\_update(*vk*, *Cl*, open) // 1) update all the affected soft-collision sets using Eq.(3) //2) add all affected vertexes back to open list (see reference [6] for details) 24: **if** *ψ*(*vl*) = ∅ **and** *vk*.cost+*ekl*.cost < *vl*.cost **then** 25: *vl*.cost ← *vk*.cost+*ekl*.cost 26: *vl*.traceBack← *vk* 27: open.add(*vl*) 28: **end if** 29: **end for** 30: **end while** 31: **return** no path exists

SC-M\* can make a transition from a decoupled individual A\* (*T* = 1) to a standard hard-collision constrained M\* (*T* = 0), providing more flexibility to the performance of the algorithm with bounded soft-collision scores.
