Welcome to Prolog programming! It's very cool that you're coming at it from the hardware, almost as far from this as you can get.
I think I see two problems.
The first one is that your definition leaves out the defining characteristic of the AND gate, which is that when both inputs are 1 the output will be 1. Your translation into Prolog is a little odd-looking but certainly should take this into account. So I think in Prolog what you're trying to say is this:
signal(R, 0) :-
gate(X), gate_type(X, and),
terminal_type(R, X, out),
terminal_type(R1, X, in), signal(R1, 0).
This isn't the whole story though. You'll need this too:
signal(R, 1) :-
gate(X), gate_type(X, and),
terminal_type(R, X, out),
terminal_type(R1, X, in), terminal_type(R2, X, in), R1 \= R2,
signal(R1, 1), signal(R2, 1).
This might be correct, but the second problem is that signal(t7, 1)
is not an assertion, so it doesn't wind up in your fact database. It's just a bald structure, so it doesn't add anything to your query. The simplest solution would be to just add it to your database directly:
signal(t7, 1).
signal(t8, 1).
Then do your query:
signal(t9, X).
Or, you could assertz/1
it:
assertz(signal(t7, 1)), assertz(signal(t8, 1)), signal(t9, X).
But that's kind of sloppy, because assert
is a side-effect that isn't undone on backtracking.
In practice, most of the time you either make something part of the dynamic query by passing it along, or you make it part of the fact database. Mixing the two gets hard to reason about.
If I were you, I would probably simplify things by reducing the number of different fact "types" to something more like this:
% gate(Name, Type, Input1, Input2, Output)
gate(a1, and, t7, t8, t9).
Then you could really simplify the predicates by quite a bit:
signal(Out, 0) :-
gate(_, and, R1, R2, Out),
( signal(R1, 0) ; signal(R2, 0)).
signal(Out, 1) :-
gate(_, and, R1, R2, Out),
signal(R1, 1),
signal(R2, 1).