1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
# Copyright (c) 1997-2024
# Ewgenij Gawrilow, Michael Joswig, and the polymake team
# Technische Universität Berlin, Germany
# https://polymake.org
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version: http://www.gnu.org/licenses/gpl.txt.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#-------------------------------------------------------------------------------
# Read file format for circuits and turn it into Valiant polytope.
#
# Valiant: Reducibility by algebraic projections, Enseign. Math. (2) 28 (1982):3-4, pp. 253-268, MR684236 (84d:68046b)
#
# File format for non-CNF logical expressions described in:
# http://www.satcompetition.org/2005/edimacs.pdf
use application "polytope";
declare $debug=0;
sub And($$$$) {
my ($out, $in1, $in2, $d) = @_;
my $m = new Matrix(3,$d+1);
my ($ain1,$ain2)=(abs($in1),abs($in2));
# 1 + out - in1 - in 2 >= 0
$m->elem(0,0) = 1; $m->elem(0,$out) = 1; $m->elem(0,$ain1) = -1; $m->elem(0,$ain2) = -1;
$m->elem(1,0) = 0; $m->elem(1,$out) = -1, $m->elem(1,$ain1) = 1;
$m->elem(2,0) = 0; $m->elem(2,$out) = -1, $m->elem(2,$ain2) = 1;
if ($in1<0) { # subs in1 -> (1-in1)
$m->col(0) += new Vector([-1,1,0]);
$m->col($ain1) *= -1;
}
if ($in2<0) { # subs in2 -> (1-in2)
$m->col(0) += new Vector([-1,0,1]);
$m->col($ain2) *= -1;
}
return $m;
}
sub Or($$$$) {
my ($out, $in1, $in2, $d) = @_;
my $m = new Matrix(3,$d+1);
my ($ain1,$ain2)=(abs($in1),abs($in2));
# - out + in1 + in 2 >= 0
$m->elem(0,0) = 0; $m->elem(0,$out) = -1; $m->elem(0,$ain1) = 1; $m->elem(0,$ain2) = 1;
$m->elem(1,0) = 0; $m->elem(1,$out) = 1, $m->elem(1,$ain1) = -1;
$m->elem(2,0) = 0; $m->elem(2,$out) = 1, $m->elem(2,$ain2) = -1;
if ($in1<0) { # subs in1 -> (1-in1)
$m->col(0) += new Vector([1,-1,0]);
$m->col($ain1) *= -1;
}
if ($in2<0) { # subs in2 -> (1-in2)
$m->col(0) += new Vector([1,0,-1]);
$m->col($ain2) *= -1;
}
return $m;
}
my %dispatch=(
'4', \&And,
'6', \&Or,
);
sub edf2poly($) {
my @all_constraints;
my $filename=$_[0];
open EDF, $filename or die "edf2poly: cannot read $filename";
my $header = <EDF>; # reads first line
my $d=0;
$d=$1 if $header =~ /p\s+noncnf\s+(\d+)/;
print "header=$header\nd=$d\n" if $debug;
die "edf2poly: header invalid or no variables" unless $d>0;
foreach (<EDF>) {
my ($op,$out,$in1,$in2) = m/^\s*(\d+)\s+-1\s+(\d+)\s+(-?\d+)\s+(-?\d+)\s+0\s*$/;
print "op=$op out=$out in1=$in1 in2=$in2\n" if $debug;
if (defined($in2)) {
my $these_constraints = &{$dispatch{$op}}($out,$in1,$in2,$d);
push @all_constraints, @{rows($these_constraints)};
} else {
die "edf2poly: can't parse <$_>";
}
}
close EDF;
push @all_constraints, @{rows(cube($d,0)->FACETS)};
return new Polytope(INEQUALITIES=>new Matrix(@all_constraints), CONE_AMBIENT_DIM=>$d+1);
}
|