I want to implement a very simple automaton that restrict the number of consecutive 1s in a list of ones and zeros (e.g. [0,1,1,0,1,1,1]).

My automaton looks like this:

% 'Day' is a list of clpfd variables
% 'Allowed' is an integer
%
% consecutiveOnes(+Day, +Allowed)
consecutiveOnes(Day, Allowed) :-

    automaton(Day, _, Day,
        [source(n)],
        [
         arc(n, 0, n, [0]  ),
         arc(n, 1, n, [C+1])
        ],
        [C],
        [0],
        [_N]
    ).



% example 1:
%   consecutiveOnes([0,0,0,1,1,1], 2)  -> there are three consecutive 1s and we allow only 2 -> Fail.

% example 2:
%   consecutiveOnes([0,1,1,1,0,0], 2)  -> there are three consecutive 1s and we allow only 2 -> Fail.


% example 3:
%   consecutiveOnes([0,1,1,0,0,0], 2)  -> there are only two consecutive 1s and we allow 2 -> OK

How can I add the constraint for counter C specifying C <= Allowed to the Prolog code above?

有帮助吗?

解决方案

It may be best to formulate this with additional states. For example, for at most two consecutive 1s:

:- use_module(library(clpfd)).

at_most_two_consecutive_ones(Day) :-
    automaton(Day,
        [source(n),sink(n),sink(n1),sink(n2)],
        [arc(n, 0, n),
         arc(n, 1, n1),
         arc(n1, 1, n2),
         arc(n1, 0, n),
         arc(n2, 1, false),
         arc(n2, 0, n)
        ]).

Example queries:

?- at_most_two_consecutive_ones([0,0,0,1,1,1]).
false.

?- at_most_two_consecutive_ones([0,1,1,0,1,1]).
true.

?- at_most_two_consecutive_ones([0,1,1,0,1,0]).
true.

For a more general solution, you have to build an automaton on demand when given the maximal length of a run.

其他提示

I believe the following code is what you're looking for:

:- use_module(library(clpfd)).

consecutiveOnes(Day, Allowed) :-
    automaton(Day, _, Day,
        [source(n),sink(n)],
        [
         arc(n, 0, n, [0]  ),
         arc(n, 1, n, (C #< Allowed -> [C+1]))
        ],
        [C],[0],[_N]
    ).

Please note the two changes to your original code: (1) I added a sink(n) to the list of sources and sinks. Otherwise it will reject every sequence. (2) I added the condition that C < Allowed. If the condition is not satisfied, there is no else, so it fails.

Some example queries:

| ?- consecutiveOnes([0,1,1,0],1).                                              
no                                 
| ?- consecutiveOnes([0,1,1,0],2).
yes
| ?- consecutiveOnes([0,1,1,0,1,1,1],2).
no
| ?- consecutiveOnes([0,1,1,0,1,1,0],2).
yes
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top