Генерация случайных значений, когда ограничение выполняется и не выполняется

У меня есть следующее:

:-use_module(library(clpfd)).

list_index_value(List,Index,Value):-
  nth0(Index,List,Value).

length_conindexes_conrandomvector(Length,Conindexs,Randomvector):-
  length(Randomvector,Length),
  same_length(Conindexs,Ones),
  maplist(=(1),Ones),
  maplist(list_index_value(Randomvector),Conindexs,Ones),
  term_variables(Randomvector,Vars),
  maplist(random_between(0,1),Vars).

length_conindexes_notconrandomvector(Length,Conindexes,Randomvector):-
  length(Randomvector,Length),
  length(Conindexes,NumberOfCons),
  same_length(Conindexes,Values),
  sum(Values,#\=,NumberOfCons),
  maplist(list_index_value(Randomvector),Conindexes,Values),
  term_variables(Randomvector,Vars),
  repeat,
  maplist(random_between(0,1),Vars).

length_conindexes_conrandomvector/3 используется для генерации случайного вектора из единиц и нулей, где элементы в позициях конидексов равны 1 с.

 ?-length_conindexes_conrandomvector(4,[0,1],R).
 R = [1, 1, 0, 1].

length_conindexes_notconrandomvector/3 используется для генерации случайного вектора, где НЕ ВСЕ кониндексы являются единицами.

?- length_conindexes_notconrandomvector(3,[0,1,2],R).
R = [1, 0, 1] ;
R = [0, 1, 1] ;
R = [1, 1, 0] 

Это я чувствую, что "взломан" с repeat команда. Каков наилучший способ сделать это? Если я использую маркировку, то значения не будут случайными? Если ограничение часто нарушается, то поиск будет очень неэффективным. Каков наилучший способ сделать это?

1 ответ

Решение

В SWI-Prolog я бы делал все это с ограничениями CLP(B).

Например 1:

:- use_module(library(clpb)).

length_conindices_notconrandomvector(L, Cs, Rs):-
        L #> 0,
        LMax #= L - 1,
        numlist(0, LMax, Is),
        pairs_keys_values(Pairs, Is, _),
        list_to_assoc(Pairs, A),
        maplist(assoc_index_value(A), Cs, Vs),
        sat(~ *(Vs)),
        assoc_to_values(A, Rs).

assoc_index_value(A, I, V) :- get_assoc(I, A, V).

Обратите внимание, что я также взял на себя смелость превратить метод O (N 2) для извлечения необходимых элементов в O (N × log N).

Пример запроса:

? - length_conindices_notconrandomvector (4, [0,1], Rs).
Rs = [X1, X2, X3, X4],
СБ (1# Х1* Х2).

Всегда желательно разделить часть моделирования на собственный предикат, который мы называем основным отношением. Чтобы получить конкретные решения, вы можете, например, использовать random_labeling/2:

? - length_conindices_notconrandomvector (4, [0,1], Rs),
   длина (_, семя),
   random_labeling(Семя, рупий).
Rs = [0, 1, 1, 1],
Семя = 0;
Rs = [1, 0, 0, 1],
Семя = 1;
Rs = [1, 0, 1, 1],
Семя = 2;
Rs = [1, 0, 0, 1],
Семя = 3.

CLP (В)'ы random_labeling/2 реализован таким образом, что каждое решение одинаково вероятно.


1 Я, конечно, предполагаю, что у вас есть :- use_module(library(clpfd)). уже в вашем ~/.swiplrc ,

Другие вопросы по тегам