Предикаты с оператором = .. в Прологе

Вы получаете сообщение об ошибке

ValueError: setting an array element with a sequence.

, потому что вы пытаетесь установить элемент массива с последовательностью. Я не пытаюсь быть симпатичным, там - сообщение об ошибке пытается рассказать вам, в чем проблема. Не думайте об этом как о загадочной ошибке, это просто фраза. Какая строка задает проблему?

kOUT[i]=func(TempLake[i],Z)

Эта строка пытается установить элемент ith из kOUT на то, что возвращает func(TempLAke[i], Z). Глядя на случай i=0:

In [39]: kOUT[0]
Out[39]: 0.0

In [40]: func(TempLake[0], Z)
Out[40]: array([ 0.,  0.,  0.,  0.])

Вы пытаетесь загрузить 4-элементный массив в kOUT[0], который имеет только float. Следовательно, вы пытаетесь установить элемент массива (левая сторона, kOUT[i]) с последовательностью (правая сторона, func(TempLake[i], Z)).

Вероятно, func не делает что вы хотите, но я не уверен, что вы действительно хотели этого сделать (и не забывайте, что вы обычно можете использовать векторизованные операции, такие как A * B, а не цикл в numpy.) В любом случае это должно объяснить проблему.

2
задан heisenberg7584 17 January 2019 в 11:45
поделиться

3 ответа

Глядя на ответ этого поста , вы можете использовать предикат flatten_term/2, немного модифицированный для обработки свободных переменных, чтобы решить вашу проблему. Вот код для базового решения:

flatten_term(Term,[Term]):-
    (atomic(Term);var(Term)),!.
flatten_term(Term,Flat):-
    Term =.. TermList,
    flatten_term_list(TermList,Flat),!.

flatten_term_list([],[]):-!.
flatten_term_list([H|T],List):-
    flatten_term(H,HList),
    flatten_term_list(T,TList),
    append(HList,TList,List),!.

occurrences(_,[],N,N):-!.
occurrences(A,[H|T],N,Tot):-
    A \== H,!,
    occurrences(A,T,N,Tot).
occurrences(A,[H|T],N,Tot):-
    A == H,!,
    N1 is N+1,
    occurrences(A,T,N1,Tot).

count(A,Term,N):-
    flatten_term(Term,Flatten),
    occurrences(A,Flatten,0,N).

?- count(a,f(a,g(X,a),d),T).
T = 2.

?- count(X,f(a,g(X,a),d),T).
T = 1

Прежде всего вы сгладьте термин, используя flatten_term/2. Затем просто посчитайте вхождения элемента, который вы хотите найти, используя occurrences/4. Вы можете, если хотите, изменить flatten_term/2, чтобы избежать использования occurrences/4 и, таким образом, сканировать термин (список) только один раз ... Что-то вроде: flatten_term(Term,Flatten,ElementToFind,Counter,Total).

0
ответ дан damianodamiano 17 January 2019 в 11:45
поделиться

Это хорошо? Довольно? Или я что-то пропустил?

Предикат Пролога =../2 [swi-doc] может «упаковать» и «распаковать» список, содержащий Имя функтора и его аргументы в термине и наоборот. Таким образом, можно использовать это для построения термина или для анализа термина. Например:

?- f(a,g(b,a)) =.. L.
L = [f, a, g(b, a)].

Здесь f - имя функтора, а a и g(b, a) - аргументы. Эти аргументы также могут быть терминами, и тогда нам нужно распаковать эти аргументы дальше.

Например, мы можем получить все подтермы терма с помощью:

subterms(T, T) :-
    \+ var(T).
subterms(T, ST) :-
    \+ var(T),
    T =.. [_|As],
    member(A, As),
    subterms(A, ST).

Например:

?- subterms(f(a,g(X,a)),N).
N = f(a, g(X, a)) ;
N = a ;
N = g(X, a) ;
N = a ;
false.

Теперь, когда мы получили все (под) термины, мы можем немного переписать предикат, чтобы подсчитать количество подходящих элементов:

subterm_query(Q, T) :-
    Q == T.
subterm_query(Q, T) :-
    \+ var(T),
    T =.. [_|As],
    member(A, As),
    subterm_query(Q, A).

, поэтому мы получим, если запросим a:

?- subterm_query(a, f(a,g(X,a))).
true ;
true ;
false.

Если мы сможем используя библиотеку aggregate , мы можем использовать предикат aggregate_all/3 для подсчета количества раз, предикат был успешным:

?- aggregate_all(count, subterm_query(a, f(a,g(X,a))), Count).
Count = 2.

Если нет, вам нужно реализовать механизм, который возвращает 1 для совпадения и рекурсивно суммирует совпадения дочерних терминов. Я оставляю это как упражнение.

0
ответ дан Willem Van Onsem 17 January 2019 в 11:45
поделиться

Начните с решения более общей задачи подсчета членов в списке . В конце концов, обработка термина - это обработка одноэлементного списка, содержащего этот термин:

count(A,T,N):- count(A, [T|Z],Z, 0,N).

count(_, [],  [], C,N):- N is C, !.
count(A, [T|B],Z, C,N):- ?=(A,T), A=T, !, count(A, B,Z, C+1,N).
count(A, [T|B],Z, C,N):- ?=(A,T), T=..[_|S], !, append(S,Y,Z), count(A, B,Y, C,N).
count(A, [_|B],Z, C,N):- count(A, B,Z, C,N).

Это открывает каждый главный термин в списке подряд и добавляет к нему свои аргументные термины [116 ] list , таким образом используя его как очередь ... таким образом обрабатывая второй аргумент предиката T способом в ширину .

Предполагается, что аргумент A является атомом, а ?= используется, чтобы избежать создания экземпляров свободных переменных, с которыми мы можем столкнуться, и вместо этого пропустить их, как, кажется, указывают ваши примеры.

0
ответ дан Will Ness 17 January 2019 в 11:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: