Implementing often-occuring determinism patterns in Prolog

You should experiment with double negation as failure. Yes a ground goal can only be true or false, so it should not leave any choice points. Lets assume we have an acyclic graph, to make matters simple:

enter image description here

If I use this code:

edge(a, b).         edge(a, c).
edge(a, d).         edge(b, c).
edge(c, d).         edge(c, e).
edge(d, e).

path(X,X).
path(X,Y) :- edge(X,Z), path(Z,Y).

The Prolog system will now leave choice points for closed queries:

?- path(a, e).
true ;
true ;
true ;
true ;
true ;
false.

In my opinion the recommended approach, to eliminate these choice points and nevertheless have a multi-moded predicate, is to use so called meta-programming in Prolog.

meta-programming is also sometimes derogeratively called non-logical programming, since it is based on non-logical predicates such as ground/1, !/0 or (+)/1. But lets call it meta-programming when declarativity is not impacted.

You could write a wrapper smart/1 as follows, doing the same as your call_ground_as_semidet/1, but with a small nuance:

smart(G) :- ground(G), !, \+ \+ G.
smart(G) :- G.

The Prolog system will not anymore leave a choice point for closed queries:

?- smart(path(a,e)).
true.

The advantage of \+ \+ over once, is that the former does not only leave no choice points, but also removes the trail. It is sometimes called the garbage collection meta-predicate of Prolog.