2015-01-23 5 views
3

Я знаю, что у Prolog есть свой предикат для обработки наследников, но я хочу сделать свой собственный для упражнений.Реализация моего предиката преемника

Вот код моего текущего положительного преемника:

successor(0,1). 
successor(X,Y) :- 
    X > 0, 
    Xx is X-1; 
    successor(Xx,Yx), 
    Y is Yx + 1. 

Когда я типа successor(O,1), У меня есть true successor(O,X) возвращается X = 1 successor(X,1) возвращает X = 0 successor(2,X) возвращает X = 3

Последнее, что мне не удастся делать это

successor(X,2) 

Он бросает и ошибка:

ERROR: >/2: Arguments are not sufficiently instantiated 

Я сделал свой след, и выяснил, что это сравнение неинициализированный переменной (X) для 0

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

+2

У вас возникнут проблемы с '>/2' и' is/2' при создании реляционного преемника-преемника/2'. '>/2' ожидает * оба * аргументы должны быть созданы. Поэтому, если 'X' является переменной,' X> 2' выдаст ошибку. Предикат 'is/2' ожидает, что все с правой стороны будет создано.Таким образом, даже если 'X> 2' работал,' Xx is X-1' будет вызывать ошибку, если 'X' является переменной, потому что ему нужно вычислить выражение справа от' is'. Пути вокруг него (clunky): используйте 'var/1' или' nonvar/1' для проверки переменных или (лучше): используйте операции CLPFD, такие как 'X #> 0' и' Xx # = X - 1 '. – lurker

+0

Кроме того, нет необходимости, чтобы 'successor/2' был рекурсивным, если вы не ищете все' Y', такие как 'X lurker

+1

В качестве первого шага при изучении Prolog сосредоточьтесь на [тег: преемник -arithmetics]. Вы используете '(is)/2' и' (>)/2', который слишком моден для ваших первых попыток. – false

ответ

1

Почему ваш код заботится о знаке? У вас есть 3 основных случаев здесь, ни один из которых особенно обеспокоены, где вы стоите относительно нуля на числовой прямой:

  • связанного X; связанный Y.
  • bound X; unbound Y,
  • unbound X; связанный Y.

С этой целью ...

successor(X,Y) :- int(X), int(Y), Y =:= X+1 . 
successor(X,Y) :- int(X), var(Y), successor_x(X,Y) . 
successor(X,Y) :- var(X), int(Y), predecessor_y(X,Y) . 

successor_x(X,Y) :- T is X+1 , (Y = T ; successor_x(T,Y)) . 

predecessor_y(X,Y) :- T is Y-1 , (X = T ; predecessor_y(X,Y)) . 
+1

«int/1' должно быть« целое/1 », я думаю. – repeat

+1

И это неверно терпит неудачу для 'successor (X, Y)', подразумевая, что решения нет. – false

3

Использование !

:- use_module(library(clpfd)). 

Определим successor/2 так:

successor(X0,X1) :- 
    X0 #>= 0, 
    X1 #= X0 + 1. 

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

?- successor(_,0). 
false. 

?- N #< 0, successor(N,_). 
false. 

?- successor(X,1). 
X = 0. 

?- successor(X,2). 
X = 1. 

?- successor(2,X). 
X = 3. 

?- successor(X,Y). 
X in 0..sup, X+1 #= Y. 
+1

Идеальное решение: Элегантный, декларативный, общий, эффективный. Я буду называть это * EDGE * решением. – mat

+1

@false. Не на моем металле: '? - преемник (X, X) .' дает ' false.' – repeat

+0

Должно быть * отлично * металл! – mat

0

Используйте этот код

successor(X,Y) :- var(X) -> X is Y - 1 ; Y is X + 1. 

сначала проверяет, если X связан, то Х экземпляр Y-1, иначе непосредственно распечатать Y как X + 1.

?- successor(90,L). 
    L = 91. 

    ?- successor(L,90). 
    L = 89. 

    ?- successor(L,-90). 
    L = -91. 

    ?- successor(-90,L). 
    L = -89. 
+1

Как правило, вы начинаете с тестов для безопасного, инстанцированного случая. Таким образом, '(nonvar (X) -> ...' – false

Смежные вопросы