Как изменить код на Prolog, чтобы устранить ошибку "Free variable in expression" при выполнении программы?

У меня возникла проблема: при выполнении приведённого ниже кода в Prolog 5.1 появляется ошибка "E;Test Goal, pos: 822, 707 Free variable in expression". Ранее, до добавления предиката рядом (правило 3), программа работала корректно; после добавления этой части меню интерпретатор стал указывать на ошибку в правиле 2-1, связанном с предикатом занято. Подскажите, как это исправить. <br/> <br/> <pre><code>Predicates
  • 19 апреля 2026 г. 12:01
Ответы на вопрос 1
Ошибка "Free variable in expression" в Про́логe появляется, когда вы пытаетесь выполнить арифметическую операцию или сравнение над переменной, которая ещё не связана (неinstantiated). Типичные примеры: использовать is/2, =:=, >, < и т.п. до того, как операнды будут известны.

Что нужно сделать — два варианта:

1) Исправить порядок целей / добавить проверки, чтобы арифметические операции выполнялись только тогда, когда переменные связаны.  
   - Например, вместо
     X is Y + 1, …
     нужно гарантировать, что Y уже привязан: …, Y = 5, X is Y + 1.
   - Или явно проверить nonvar(Y) перед вычислением:
     nonvar(Y), X is Y + 1, …

2) Если вы хотите работать с не связными переменными (решать уравнения, генерировать решения), используйте библиотеку ограничений по целым (CLP(FD)) и операторы #=, #\=, #<, #> и т.д. Они допускают неопределённые переменные и ставят на них ограничения:
   :- use_module(library(clpfd)).
   рядом(R,C,R1,C1) :-
       (R1 #= R,  C1 #= C+1) ;
       (R1 #= R,  C1 #= C-1) ;
       (R1 #= R+1,C1 #= C) ;
       (R1 #= R-1,C1 #= C).

Пример конкретной ошибки и её исправления. Частая ситуация: вы добавили правило рядом/… и теперь предикат занято/… вызывает арифметику с незвязанной переменной:

Неправильно:
занято(R,C) :- рядом(R,C,R2,C2), поле(R2,C2,1), ….
рядом(R,C,R2,C2) :- R2 is R, C2 is C+1 ; …        % вызовет ошибку если R,C не заданы

Правильно (гарантируя связывание перед is) — либо вызывать рядом только когда R,C известны, либо использовать CLP(FD):
:- use_module(library(clpfd)).
рядом(R,C,R2,C2) :-
    (R2 #= R, C2 #= C+1) ;
    (R2 #= R, C2 #= C-1) ;
    (R2 #= R+1, C2 #= C) ;
    (R2 #= R-1, C2 #= C).

Советы для отладки
- Посмотрите трассировку (trace) и определите, где именно стоит незвязанная переменная. Сообщение вида pos: 822,707 подсказывает позицию в файле.  
- Используйте var/1 и nonvar/1 для диагностики и защиты.  
- Не пытайтесь вычислять X is Expr, когда Expr содержит свободные переменные.

Если хотите, пришлите фрагменты ваших правил рядом/… и занято/…, я покажу точную правку.
Похожие вопросы