/**
 * A program that shows a bug in predicate solutions or in how non-deterministic predicates are handled.

 * @author Pedro Mariano
 * @version 1.0 2014/01/22
 */
:- module bugSolutions.

:- interface.

:- import_module io.

:- pred main(io.state, io.state).
:- mode main(di, uo) is det.

:- implementation.

:- import_module list, solutions.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of exported types

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Definition of private types

:- type geometry --->
	wellmixed ;
	lattice(
		xSize         :: int ,
		ySize         :: int ,
		neighbourhood :: neighbourhood ,
		boundary      :: boundary
	) .

:- type neighbourhood --->
	moore ;
	hexagonal ;
	vonNeumann .

:- type boundary --->
	torus ;
	ring ;
	closed .

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Implementation of exported predicates and functions

main(!IO) :-
	X = 2,
	Y = 3,
	io.print(solutions.solutions(latticeWorst(X, Y)) `with_type` list(geometry), !IO), io.nl(!IO),
	io.print(solutions.solutions(latticeWrong(X, Y)) `with_type` list(geometry), !IO), io.nl(!IO),
	io.print(solutions.solutions(latticeGood(X, Y)) `with_type` list(geometry), !IO), io.nl(!IO)
/*	io.nl(!IO),
	io.nl(!IO),
	solutions.solutions(latticeWorst(X, Y), SW1),
	io.print(SW1, !IO), io.nl(!IO),
	solutions.solutions(latticeWrong(X, Y), SW2),
	io.print(SW2, !IO), io.nl(!IO),
	solutions.solutions(latticeGood(X, Y), SG),
	io.print(SG, !IO), io.nl(!IO)*/
	.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Implementation of private predicates and functions


:- pred latticeWorst(int, int, geometry).
:- mode latticeWorst(in, in, out) is multi.

latticeWorst(X, Y, G) :-
	G^xSize = X,
	G^ySize = Y,
	(
		G^boundary = torus ;
		G^boundary = ring ;
		G^boundary = closed
	),
	(
		G^neighbourhood = moore ;
		G^neighbourhood = hexagonal ;
		G^neighbourhood = vonNeumann
	).

:- pred latticeWrong(int, int, geometry).
:- mode latticeWrong(in, in, out) is nondet.

latticeWrong(X, Y, G) :-
	list.member(G^boundary, [torus, ring, closed]),
	list.member(G^neighbourhood, [moore, hexagonal, vonNeumann]),
	G^xSize = X,
	G^ySize = Y.


:- pred latticeGood(int, int, geometry).
:- mode latticeGood(in, in, out) is multi.

latticeGood(X, Y, lattice(X, Y, vonNeumann, torus)).
latticeGood(X, Y, lattice(X, Y, vonNeumann, ring)).
latticeGood(X, Y, lattice(X, Y, vonNeumann, closed)).
latticeGood(X, Y, lattice(X, Y, hexagonal, torus)).
latticeGood(X, Y, lattice(X, Y, hexagonal, ring)).
latticeGood(X, Y, lattice(X, Y, hexagonal, closed)).
latticeGood(X, Y, lattice(X, Y, moore, torus)).
latticeGood(X, Y, lattice(X, Y, moore, ring)).
latticeGood(X, Y, lattice(X, Y, moore, closed)).




:- end_module bugSolutions.

%%% Local Variables: 
%%% mode: mercury
%%% mode: flyspell-prog
%%% ispell-local-dictionary: "british"
%%% End:
