Консультация № 180302
13.10.2010, 04:55
0.00 руб.
0 21 1
Дорогие эксперты!
Помогите разработать модуль, способный находить значение формулы(представленной в нормальной форме) на данной интерпретации, и разработать на его основе программу, способную считывать формулу логики высказываний в одной из нормальных форм(по выбору пользователя) и находить её значение.

Обсуждение

Неизвестный
13.10.2010, 16:54
общий
Сказанного слишком мало для того, чтобы решить задачу. Опишите алгоритмы, "данную интерпретацию", "одну из формальных норм", "выбор пользователя"
Неизвестный
13.10.2010, 17:26
общий
Нужно ввести КНФ или ДНФ .....интерпретацию можно подобрать любую для проверки.....
Неизвестный
13.10.2010, 20:29
общий
Ну и ответ! Вам ответ нужен - напишите поподробнее. Напишите пример того, что нужно ввести и что получить
Неизвестный
13.10.2010, 20:38
общий
Такс.. нужно ввести формулу(КНФ или ДНФ, полученные при ручном преобразовании) пример тому
X->Z&Y=(не Х)&Z&Y
Подчеркнутое(помоему) КНФ....вот нужно этой формулы вывести на экран таблицу истинности для значенией(интерпретаций)
Z Y X
0 0 0
0 0 1
0 1 0
1 0 0
1 0 1
1 1 0
1 1 1

Неизвестный
13.10.2010, 21:01
общий
И как подчеркнутое на текстовом экране будем реализовывать?
Неизвестный
13.10.2010, 22:54
общий
ну мы должны ввести в строку формулу эту и модуль должен понять её(формула может быть различна)
Неизвестный
14.10.2010, 00:02
общий
Модули ничего не понимают. Понимает программист и реализует понятия, а я не пойму, что Вы хотите. Опишите, ЧТО должен "понимать модуль" и т.д. (см. выше)
Неизвестный
14.10.2010, 00:34
общий
он должен считать строку в которой хранится формула КНФ или ДНФ и выдать этой формулы таблицу истинности при всех возможных значениях X,y,z
Неизвестный
14.10.2010, 08:24
общий
То есть, как я понимаю, Вы ничего делать не хотите? И я не хочу бесплатно заниматься таким неинтересным мне проектом. Давайте подождем, может кто и согласится, но, судя по всему, ...
Неизвестный
14.10.2010, 18:00
общий
lamed:
Зря
Неизвестный
14.10.2010, 18:13
общий
Ясно..спасибо дорогие эксперты!
давно
Академик
320937
2216
14.10.2010, 19:16
общий
Юдин Евгений Сергеевич:
Все же некоторые соображения на этот счет. У К&R в п.4.3 "Внешние переменные" полностью разбирается калькулятор на основе ПОЛИЗ. Кроме того, есть смысл обратить внимание на Упражнение 4.6. там же (его решение у Тондо&Гимпела).
В Вашем случае, например, при переменных a,b,c и ДНФ abc+(~a)b(~c) будет выглядеть
Код:
a b & c & a ~ b ~ & c ~ & +
Функцию, возвращающую результат этого выражения, нужно будет запустить 2^3=8 раз, то есть для каждой строки.
Неизвестный
15.10.2010, 15:20
общий
Юдин Евгений Сергеевич:
Скоро выходные, когда можно и порешать... Как? Хотите оплатить работу?
давно
Академик
320937
2216
21.10.2010, 11:15
общий
Юдин Евгений Сергеевич:
Здесь я выложил calc.zip (25.9 кб) Пока это Си-шный вариант, причем, работает только с константами.

Пример заданий
Код:
И v И
И & (~И)
(И V И)& (И & Л)
И & (~Л)

Ввод
Код:
1 1 +
1 1 - *
1 1 + 1 0 * *
1 0 - *

Вывод
Код:

1
0
0
1
Good luck!

давно
Мастер-Эксперт
17387
18346
21.10.2010, 12:26
общий
lamed:
Благодарю! Вы, как всегда, обстоятельны.

Но я понимаю условие задачи
Помогите разработать модуль, способный находить значение формулы(представленной в нормальной форме)

так: "Имеется КНФ или ДНФ, для которой требуется разработать модуль". А там могут присутствовать только конъюнкции и дизъюнкции (и если не ошибаюсь, отрицания). Если преобразовать нормальные формы в минимальные, то всё ещё больше упрощается...
Об авторе:
Facta loquuntur.
давно
Академик
320937
2216
21.10.2010, 21:53
общий
это ответ
Здравствуйте, Юдин Евгений Сергеевич!
Код в приложении. ABC

Программа обрабатывает строки не более, чем с 10-ю переменными. Переменные обозначаются строчными буквами латинского алфавита. Используется обратная польская запись.
Обозначения:
дизъюнкция +
конъюнкция *
отрицание ~

При разработке использованы примеры Брайана Кернигана & Денниса Ритчи, Кловиса Тондо & Скотта Гимпела, а также идеи Эллиота Мендельсона.
Код:
program Logic;
{
Разработчик: lamed. RFPRO, 2010
ABC Pascal
Идея использования префиксной нотации для логических выражений описана в [2], с.27, упр.3
В программе используется постфиксная нотация (обратная польская запись)
Подробное описание построения калькулятора арифметических выражений
можно получить в главе 4, п.4.1,4.2,4.3,4.4 [1].
и в решение задач 4.6, 4.10, [3]
Использованные источники.
1. Керниган, Брайан У., Ритчи, Деннис М. Язык программирования C. 2-е издание.:
Пер. с англ. - М.: Издательский дом "Вильямс", 2006.
2. Мендельсон Э. Введение в математическую логику.
Пер. с англ./Под ред. С. И. Адяна - 3-е изд. - М.:Наука, 1984
3. Тондо К., Гимпел С. Книга ответов: Пер. с англ. - М. Финансы и статистика, 1994
Вместо булевых значений ИСТИНА и ЛОЖЬ обрабатывются 1 и 0 соответсвенно.

В настоящей версии добавлены:
- обработка импликации
- печать эквивалентной СДНФ
}
const
MAXVAL=100;
TotalRows = 1024; // программа рассчитана на 10 переменных
type
TBit = 0..1;

var
MaxLetter: integer;
MaxRow : integer;
letters : array[char] of integer;
cond : array[1..TotalRows, 1..26] of TBit; // таблица условий

var
vals : array[1..MAXVAL] of TBit;
sp : integer;
ctype : char;
variable: array['a'..'z'] of TBit;

function bit(x: word; n: integer): TBit;
// получение n-го бита числа
begin
bit := (x shr n ) and 1;
end;

procedure CreateTable(s: string);
// создание таблицы переменных
// и таблицы значений переменных
var
len : integer;
used: set of char;
i,j : integer;
num : word;
c : char;
begin
len := length(s);
used := [];

for c:= 'a' to 'z' do
letters[c] := 0;

// Не все 26 букв используются в качестве переменных
// Множество использованных букв
for i:= 1 to len do
if (s[i] in ['a'..'z']) then
used := used+[s[i]];

// Использованные буквы должны быть лексикографически упорядочены
// при печати, нумеруем каждую использованную букву, начиная с 1
MaxLetter:= 0;
for c:= 'a' to 'z' do
if (c in used) then
begin
inc(MaxLetter);
letters[c] := MaxLetter;
end;

MaxRow := 1 shl MaxLetter;
num:= 0;
for j:= 1 to MaxRow do
begin
for i:= 1 to MaxLetter do
cond[j, i]:= 1-bit(num, i-1);
inc(num);
end;
end;


procedure push(f: TBit);
// "вталкивание" элемента в стек
begin
if (sp<=MAXVAL) then
begin
vals[sp]:=f;
sp := sp+1;
end
else
writeln('error stack full');
end; { push }

function pop: TBit;
// "выталкивание" элемента из стека
begin
if (sp>1) then
begin
dec(sp);
pop := vals[sp];
end
else
begin
writeln('error stack empty');
pop := 0;
end;
end; { pop }

function getop(var s: string): char;
// получение кода операции
var
i: integer;
begin
i:= 1;
while (s[i]=' ') do
inc(i);
getop := s[i];
delete(s,1,i);
end; { getop }

procedure CalcBool(s: string; var b: TBit; var code: integer);
// логический калькулятор
// построен на основе стека
begin
s:= trim(s);
if (s<>'') then
begin
repeat
ctype := getop(s);
case ctype of
'0','1': // значение И/Л
push(ord(ctype)-ord('0'));
'+': // бинарная операция v дизъюнкция
push(pop() or pop());
'*': // бинарная операция & конъюнкция
push(pop() and pop());
'>': // бинарная операция => следование
push(pop() or (1-pop()));
'~': // бинарная операция отрицание
push(1-pop());
else
begin
if ctype in ['a'..'z'] then
push(variable[ctype]) // имя переменной
else
begin
writeln('error: unknown command ', s);
code:=1;
halt;
end;
end;
end;
until s='';
b:= pop(); // последнее значение в стеке
code := 0; // результат выражения
end
else
code:= -1;
end; { process }

var
s : string;
i, j : integer;
c : char;
code : integer;
F : TBit;
begin
write('Ваша строка ');
readln(s);

// на первом проходе создаем таблицу имен аргументов
// и заполняем таблицу значений
CreateTable(s);

sp := 1; // инициализация стека
// указатель на вершину стека

// в цикле по строкам и по столбцам
// вычисляем значение выражения
for j:= 1 to MaxRow do
for c:= 'a' to 'z' do
// удобней создать и использовать массив, содержащий имена и значения
// всех букв, для данной задачи выделение памяти некритично
// выигрываем в простоте кода
begin
if letters[c]>0 then
variable[c]:= cond[j,letters[c]];
CalcBool(s, F, code);
cond[j, MaxLetter+1]:=F;
end;

// Печать результата
write(' ':3);
for c:= 'a' to 'z' do
if letters[c]>0 then
write(c:3);
writeln('F=':4, s);

for j:= 1 to MaxRow do
begin
write(j: 3);
for i:= 1 to MaxLetter+1 do
write(cond[j,i]: 3);
writeln;
end;

// Печать эквивалентной СДНФ
//
writeln('Эквивалентная СДНФ');
for j:= 1 to MaxRow do
if cond[j, MaxLetter+1]=1 then
begin
for i:= 1 to MaxLetter do
begin
if (cond[j,i]=0) then write('(~');
for c:= 'a' to 'z' do
if letters[c]=i then
write(chr(ord(c)-ord('a')+ord('A')));
if (cond[j,i]=0) then write(')');
if i< MaxLetter then write('&');
end;
if j < MaxRow then
write(' + ');
end;
writeln;

end.


Примеры работы
Код:
Ваша строка c c ~ +
c F=c c ~ +
1 1 1
2 0 1
Ваша строка a b * a b ~ * +
a b F=a b * a b ~ * +
1 1 1 1
2 0 1 0
3 1 0 1
4 0 0 0

Новые примеры
Код:
Пример 1
(a->(b->c))->((a->b)>(a->c))
ПОЛИЗ. a b c > > a b > a c > > >
Диалог
Ваша строка
a b c F=a b c > > a b > a c > > >
1 1 1 1 1
2 0 1 1 1
3 1 0 1 1
4 0 0 1 1
5 1 1 0 1
6 0 1 0 1
7 1 0 0 1
8 0 0 0 1
Эквивалентная СДНФ
A&B&C + (~A)&B&C + A&(~B)&C + (~A)&(~B)&C + A&B&(~C) + (~A)&B&(~C) + A&(~B)&(~C) + (~A)&(~B)&(~C)

Пример 2. Вопрос 180429
Автор вопроса: sveta11115 (Посетитель)
Автор ответа : Лысков Игорь Витальевич
(x'-> y')->(y& z)->(x & z)
ПОЛИЗ. x ~ y ~ > y z * > x z * >

Диалог
Ваша строка
x y z F=x ~ y ~ > y z * > x z * >
1 1 1 1 1
2 0 1 1 0
3 1 0 1 1
4 0 0 1 1
5 1 1 0 1
6 0 1 0 0
7 1 0 0 1
8 0 0 0 1
Эквивалентная СДНФ
X&Y&Z + X&(~Y)&Z + (~X)&(~Y)&Z + X&Y&(~Z) + X&(~Y)&(~Z) + (~X)&(~Y)&(~Z)

Недостатки.
1. Не модуль
2. Не самая лучшая реализация
3. Нет перевода из инфиксной в постфиксную нотацию
4. Мало "гонял" последний вариант

Достоинства: работает (кажется :)
Вопросы в мини-форум или на пейджер.

Внесены дополнения 27/10/10.
1. По просьбе автора вопроса добавлены комментарии
2. Добавлена реализация импликации >
3. Добавлена печать эквивалентной СДНФ.
Удачи!
5
Отлично проделана работа!
Неизвестный
21.10.2010, 22:19
общий
Здравствуйте Lamed!

Спасибо за Построение таблиц двоичных данных! Там только в 1 минус есть... можено ли тут использовать так?
Цитата: lamed
letters: array[1..ord('z')] of char;
cond: array[1..TotalRows, 1..ord('z')] of TBit;


У меня компилятор ругался на ord('z') ....заменил на эквивалент "122" и программа заработала!

На счет второй программы... работает прекрасно и сразу. 5 Баллов.
давно
Академик
320937
2216
21.10.2010, 22:32
общий
Юдин Евгений Сергеевич:
Евгений Сергеевич! Я все уже "перелопатил". Актуальная версия в ответе. Если что-то окажется неисправным, сразу дайте знать. ord('z') - это, конечно, моя глупость. Надо было просто 26. Именно столько символов в английском алфавите. Внес изменения.
Неизвестный
22.10.2010, 09:31
общий
Цитата: lamed
Надо было просто 26


А не 122? ведь код маленькой z это 122 в ASCII

Спасибо!
давно
Академик
320937
2216
22.10.2010, 10:09
общий
Юдин Евгений Сергеевич:
Доброе утро! Конечно, речь идет о том, что это массив английских букв, который содержит 26 символов. Тогда был бы смысл указать
Код:
  cond     : array[1..TotalRows, 1..ord('z')-ord('a')+1] of TBit;
и таки работает в Pascal ABC, но это уже слишком.
/* Все мы помним, что в английском алфавите 26 букв*/
А вот Turbo-Pascal предыдущий вариант не пропустит, из-за ограничения суммарного объема памяти под массив, 122*1024 > 65200 элементов.
давно
Академик
320937
2216
27.10.2010, 11:57
общий
Добрый день, коллеги! Внес дополнения в ответ. Добавлена операция ИМПЛИКАЦИЯ > и печать эквивалентной СДНФ.
Форма ответа