The typical top-level structure of a constraint program is
solve(Variables) :- read_data(Data), setup_constraints(Data, Variables), labeling(Variables).
setup_constraints/2 contains the problem model. It creates the
variables and the constraints over the variables.
This is often, but not necessarily, deterministic.
labeling/1 predicate is the search part of the program that
attempts to find solutions by trying all instantiations for the
variables. This search is constantly pruned by constraint propagation.
The above program will find all solutions. If the best solution is wanted, a branch-and-bound procedure can be wrapped around the search component of the program:
solve(Variables) :- read_data(Data), setup_constraints(Data, Variables, Objective), branch_and_bound:minimize(labeling(Variables), Objective).