Программа для проверки представимости булевой функции линейным арифметическим полиномом (PHP)
Материал из Модулярная арифметики
(перенаправлено с «LinearPolinomPHP»)
Содержание
Описание
Программа проверяет можно ли заданную булеву функцию представить линейным арифметическим полиномом. Используются материалы из статьи "В. П. Шмерко, Теоремы Малюгина: новое понимание в логическом управлении, проектировании сбис и структурах данных для новых технологий, Автомат. и телемех., 2004, выпуск 6, 61–83" Статья
Входные данные
На вход программы подается таблица истинности в виде:
4 3 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 0 1 1 1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 1 0 1 1 1 1 1 1 1 0
Здесь первые два числа количество входных N и выходных K переменных соответственно. Далее следуют 2N строк, в каждой N + K чисел "0" или "1". Первые N чисел - логические значения входов, следующие K чисел логические значения выходов.
Исходник на PHP
<?php
set_time_limit(3600);
function kronecker_product($a1, $a2) {
$x1 = count($a1);
$y1 = count($a1[0]);
$x2 = count($a2);
$y2 = count($a2[0]);
$ret = array();
for ($i1 = 0; $i1 < $x1; $i1++) {
for ($i2 = 0; $i2 < $x2; $i2++) {
for ($j1 = 0; $j1 < $y1; $j1++) {
for ($j2 = 0; $j2 < $y2; $j2++) {
$ret[$i1*$x2+$i2][$j1*$y2+$j2] = $a1[$i1][$j1]*$a2[$i2][$j2];
}
}
}
}
return $ret;
}
function get_conversion_matrix($num) {
$arr[0][0] = 1;
$arr[0][1] = 0;
$arr[1][0] = -1;
$arr[1][1] = 1;
if ($num == 1) {
return $arr;
}
$narr = $arr;
for ($i = 1; $i < $num; $i++) {
$narr = kronecker_product($narr, $arr);
}
return $narr;
}
function gen_polinom_koeffs($kron, $f) {
$len1 = count($f);
$len2 = count($kron);
if ($len1 != $len2) {
echo "Something strange ($len1 != $len2)";
exit;
}
$res = array();
for ($i = 0; $i < $len1; $i++) {
$res[$i] = 0;
for ($j = 0; $j < $len1; $j++) {
$res[$i] += $kron[$i][$j]*$f[$j];
}
}
return $res;
}
function print_2d_matrix($arr) {
$x = count($arr);
$y = count($arr[0]);
for ($i = 0; $i < $x; $i++) {
for ($j = 0; $j < $y; $j++) {
echo $arr[$i][$j]." ";
}
echo "\n";
}
echo "\n";
}
function print_polinom($res) {
$alpha = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l');
$len = count($res);
echo "Polinom: ";
for ($i = 0; $i < $len; $i++) {
if ($res[$i] != 0) {
if ($res[$i] > 0)
echo "+";
echo $res[$i];
$pos = 0;
$cur = $i;
while ($cur) {
if ($cur & 1)
echo $alpha[$pos];
$pos++;
$cur = $cur >> 1;
}
echo "";
}
}
echo "\n";
}
function count_ones($val) {
$c = 0;
while ($val) {
if ($val & 1)
$c++;
$val = $val >> 1;
}
return $c;
}
function check_polinom_linearity($res) {
$len = count($res);
for ($i = 1; $i < $len; $i++) {
if (count_ones($i) > 1) {
if ($res[$i] != 0)
return false;
}
}
return true;
}
function get_bit($j, $num) {
return ($j >> $num) & 1;
}
function if_pow_2($j) {
if ($j == 0)
return true;
for ($i = 0; $i < 32; $i++) {
if ($j == (1 << $i))
return true;
}
return false;
}
function swap(&$arr, $i, $j) {
$temp = $arr[$i];
$arr[$i] = $arr[$j];
$arr[$j] = $temp;
}
function gen_permute($arr, $i, $n) {
global $permutations;
if ($i == $n) {
$permutations[] = $arr;
} else {
for ($j = $i; $j < $n; $j++) {
swap($arr, $i, $j);
gen_permute($arr, $i+1, $n);
swap($arr, $i, $j);
}
}
}
function check_linearization_possibility_for_permutation_based_on_kroneker($f, $inum) {
$kron = get_conversion_matrix($inum);
$koefs = gen_polinom_koeffs($kron, $f);
$result = check_polinom_linearity($koefs);
if ($result == true || 1) {
print_polinom($koefs);
}
return $result;
}
function check_linearization_possibility_for_permutation($f, $in, $out, $inum, $onum, $number) {
for ($j = 0; $j < (1 << $inum); $j++) {
if (if_pow_2($j))
continue;
// Считаем значение функции в точке j
$sum = 0;
for ($i = 0; $i < $inum; $i++) {
$jni = get_bit($j, $inum-1-$i);
$f2i = $f[1 << $i];
$sum += $jni*$f2i;
}
$calc = 0;
for ($i = 0; $i < $inum; $i++) {
$jni = get_bit($j, $i);
$calc += $jni;
}
$sum = $sum + $f[0]*(1 - $calc);
if ($sum != $f[$j]) {
echo "$sum != ".$f[$j]." for J = $j\n";
return false;
}
}
return true;
}
function check_linearization_possibility($in, $out) {
global $permutations;
$inum = count($in[0]);
$onum = count($out[0]);
$number = count($in);
if ($onum > 10) {
echo "It's not possible to check all permuatations for $onum number of outputs!\n";
exit;
}
$permutations = array();
for ($j = 0; $j < $onum; $j++) {
$arr[$j] = $j;
}
gen_permute($arr,0,count($arr));
foreach ($permutations as $perm) {
echo "Check permuation of outputs:";
for ($j = 0; $j < $onum; $j++) {
echo " ".$perm[$j];
}
echo "\n";
// Получаем вектор f для выхода
for ($i = 0; $i < $number; $i++) {
$f[$i] = 0;
for ($j = 0; $j < $onum; $j++) {
$f[$i] += ($out[$i][$j] << $perm[$j]);
}
}
if (check_linearization_possibility_for_permutation_based_on_kroneker($f, $inum)) {
return true;
}
}
return false;
}
function read_tt($file, &$in, &$out) {
$lines = explode("\n", $file);
$arr = explode(" ", $lines[0]);
$inum = $arr[0];
$onum = $arr[1];
$ci = 0;
for ($i = 1; $i < count($lines); $i++) {
$l = trim($lines[$i]);
if ($l == '')
continue;
$l = preg_replace("/[^0-9]/i", " ", $l);
$l = preg_replace("/[[:blank:]]+/i", " ", $l);
$l = trim($l);
$arr = explode(" ", $l);
if (count($arr) != ($inum + $onum)) {
echo "Some problem at line $i: ".$lines[$i]." (".count($arr)." != ".$inum." + ".$onum.")\n";
print_r($arr);
exit;
}
for ($j = 0; $j < $inum; $j++) {
$in[$ci][$j] = $arr[$j];
}
for ($j = 0; $j < $onum; $j++) {
$out[$ci][$j] = $arr[($j+$inum)];
}
$ci++;
}
if (count($in) != 1 << $inum) {
echo "Check number of lines in truth table (".count($in)." != ".(1 << $inum).")\n";
exit;
}
}
function gen_random_truth_table($inum, $onum, &$in, &$out) {
$number = (1 << $inum);
for ($i = 0; $i < $number; $i++) {
for ($j = 0; $j < $inum; $j++) {
$in[$i][$j] = get_bit($i, $j);
}
for ($j = 0; $j < $onum; $j++) {
$out[$i][$j] = mt_rand(0, 1);
}
}
// print_r($in);
// print_r($out);
}
function print_table_to_file($file, $in, $out) {
$inum = count($in[0]);
$onum = count($out[0]);
$number = count($in);
$o = fopen($file, "w");
fprintf($o, "%d %d\n", $inum, $onum);
for ($i = 0; $i < $number; $i++) {
fprintf($o, "%d", $in[$i][0]);
for ($j = 1; $j < $inum; $j++) {
fprintf($o, " %d", $in[$i][$j]);
}
for ($j = 0; $j < $onum; $j++) {
fprintf($o, " %d", $out[$i][$j]);
}
fprintf($o, "\n");
}
fclose($o);
}
function simple_test() {
$kron = get_conversion_matrix(3);
$f = array(0, 2, 6, 4, 7, 5, 1, 2);
$ret = gen_polinom_koeffs($kron, $f);
print_2d_matrix($kron);
print_r($ret);
print_polinom($ret);
check_polinom_linearity($ret);
}
function check_truth_table_linearity($in_file) {
$file = file_get_contents($in_file);
read_tt($file, $in, $out);
if (check_linearization_possibility($in, $out)) {
echo "Possible !!!!\n";
} else {
echo "Not possible\n";
}
}
function try_to_find_linear_truth_table($out_file, $inum, $onum) {
for ($i = 0; $i < 100000; $i++) {
unset($in);
unset($out);
gen_random_truth_table($inum, $onum, $in, $out);
if (check_linearization_possibility($in, $out)) {
print_table_to_file($out_file, $in, $out);
echo "Possible !!!!\n";
break;
} else {
echo "Not possible\n";
}
}
echo "\n\n";
}
check_truth_table_linearity("example.txt");
// try_to_find_linear_truth_table("tt.txt", 3, 2);
?>
Примеры логических функций
Представимы линейным полиномом
3 4 0 0 0 0 1 1 1 0 0 1 0 0 1 1 0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 0 0 1 1 1 0 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1
Непредставимы линейным полиномом
ISCAS85 C17:
5 2 (0, 0, 0, 0, 0) | (0, 0) (0, 0, 0, 0, 1) | (0, 1) (0, 0, 0, 1, 0) | (0, 0) (0, 0, 0, 1, 1) | (0, 1) (0, 0, 1, 0, 0) | (0, 0) (0, 0, 1, 0, 1) | (0, 1) (0, 0, 1, 1, 0) | (0, 0) (0, 0, 1, 1, 1) | (0, 0) (0, 1, 0, 0, 0) | (1, 1) (0, 1, 0, 0, 1) | (1, 1) (0, 1, 0, 1, 0) | (1, 1) (0, 1, 0, 1, 1) | (1, 1) (0, 1, 1, 0, 0) | (1, 1) (0, 1, 1, 0, 1) | (1, 1) (0, 1, 1, 1, 0) | (0, 0) (0, 1, 1, 1, 1) | (0, 0) (1, 0, 0, 0, 0) | (0, 0) (1, 0, 0, 0, 1) | (0, 1) (1, 0, 0, 1, 0) | (0, 0) (1, 0, 0, 1, 1) | (0, 1) (1, 0, 1, 0, 0) | (1, 0) (1, 0, 1, 0, 1) | (1, 1) (1, 0, 1, 1, 0) | (1, 0) (1, 0, 1, 1, 1) | (1, 0) (1, 1, 0, 0, 0) | (1, 1) (1, 1, 0, 0, 1) | (1, 1) (1, 1, 0, 1, 0) | (1, 1) (1, 1, 0, 1, 1) | (1, 1) (1, 1, 1, 0, 0) | (1, 1) (1, 1, 1, 0, 1) | (1, 1) (1, 1, 1, 1, 0) | (1, 0) (1, 1, 1, 1, 1) | (1, 0)