/* Exploit smf when computing the intersection of NNC dual hypercubes.
Copyright (C) 2001-2004 Roberto Bagnara <bagnara@cs.unipr.it>
This file is part of the Parma Polyhedra Library (PPL).
The PPL 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 of the License, or (at your
option) any later version.
The PPL 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
For the most up-to-date information see the Parma Polyhedra Library
site: http://www.cs.unipr.it/ppl/ . */
#include "ppl_test.hh"
#include "timings.hh"
#include <vector>
using namespace std;
using namespace Parma_Polyhedra_Library;
#ifndef NOISY
#define NOISY 0
#endif
#ifndef VERY_NOISY
#define VERY_NOISY 0
#endif
#ifndef EXP_EVAL
#define EXP_EVAL 0
#endif
namespace {
void
closure_points_dual_hypercube(const dimension_type dims,
const LinExpression& weight_center,
const Integer& half_diagonal,
GenSys& gs) {
// An ill-formed (it has no points at all) generator system
// for a dual hypercube.
for (dimension_type axis = dims; axis-- > 0; ) {
gs.insert(closure_point(weight_center + half_diagonal * Variable(axis)));
gs.insert(closure_point(weight_center - half_diagonal * Variable(axis)));
}
}
void
add_facets(dimension_type& to_be_added,
GenSys& gs,
const LinExpression& expr,
const dimension_type axis,
const dimension_type dims,
const LinExpression& weight_center,
const Integer& half_diagonal) {
// Return if we have already added all facets.
if (to_be_added == 0)
return;
LinExpression expr1 = expr;
expr1 += half_diagonal * Variable(axis);
LinExpression expr2 = expr;
expr2 -= half_diagonal * Variable(axis);
if (axis == 0) {
gs.insert(point(dims * weight_center + expr1, dims));
--to_be_added;
if (to_be_added == 0)
return;
gs.insert(point(dims * weight_center + expr2, dims));
--to_be_added;
return;
}
// Here axis > 0.
// First recursive call with variable with index `axis'
// having coordinate 1/dims.
add_facets(to_be_added, gs, expr1,
axis-1, dims, weight_center, half_diagonal);
if (to_be_added == 0)
return;
// Second recursive call with variable with index `axis'
// having coordinate -1/dims.
add_facets(to_be_added, gs, expr2,
axis-1, dims, weight_center, half_diagonal);
}
NNC_Polyhedron
NNC_dual_hypercube(const dimension_type dims,
const LinExpression& weight_center,
const Integer& half_diagonal,
const int facet_percentage) {
GenSys gs;
closure_points_dual_hypercube(dims, weight_center, half_diagonal, gs);
// Number of facets in the closed dual hypercube.
dimension_type num_facets = 1;
for (dimension_type axis = dims; axis-- > 0; )
num_facets *= 2;
dimension_type facets_to_be_added = (num_facets * facet_percentage) / 100;
if (facets_to_be_added == 0)
// There has to be a point, at least.
gs.insert(point(weight_center));
else
add_facets(facets_to_be_added, gs, LinExpression(0),
dims-1, dims, weight_center, half_diagonal);
// Actually build the polyhedron.
return NNC_Polyhedron(gs);
}
void
build_polyhedra(const dimension_type dims,
const int perc,
vector<NNC_Polyhedron>& ph) {
LinExpression weight_center;
// 1st-polyhedron.
weight_center = LinExpression(0);
for (dimension_type axis = dims; axis-- > 0; )
weight_center += Variable(axis);
ph.push_back(NNC_dual_hypercube(dims, weight_center, 5, perc));
// 2nd-polyhedron.
weight_center = LinExpression(0);
for (dimension_type axis = dims; axis-- > 0; )
weight_center += 2*Variable(axis);
ph.push_back(NNC_dual_hypercube(dims, weight_center, 4, perc));
// 3rd-polyhedron.
weight_center = LinExpression(0);
for (dimension_type axis = dims; axis-- > 0; )
if (axis % 2 == 0)
weight_center += 10*Variable(axis);
else
weight_center += 2*Variable(axis);
ph.push_back(NNC_dual_hypercube(dims, weight_center, 5, perc));
// 4th-polyhedron.
weight_center = LinExpression(0);
for (dimension_type axis = dims; axis-- > 0; )
if (axis % 2 == 0)
weight_center += 10*Variable(axis);
else
weight_center += Variable(axis);
ph.push_back(NNC_dual_hypercube(dims, weight_center, 4, perc));
}
void
computation(vector<NNC_Polyhedron>& ph, bool enhanced) {
#if NOISY
cout << endl;
if (enhanced)
cout << "Enhanced computation: ";
else
cout << "Standard computation: ";
cout << "working with 4 NNC dual hypercubes of dimension "
<< ph[0].space_dimension() << endl;
start_clock();
#endif
// Compute the intersection of ph[0] and ph[1].
#if VERY_NOISY
// Print dimensions of arguments
// (being careful to override library laziness).
cout << "Computing intersection of ph[0] and ph[1]:" << endl;
cout << "=== ph[0] generators ===" << endl;
ph[0].generators().ascii_dump(cout);
cout << "=== ph[1] generators ===" << endl;
ph[1].generators().ascii_dump(cout);
#endif
if (enhanced) {
ph[0].minimized_constraints();
ph[1].minimized_constraints();
#if VERY_NOISY
// Print dimensions of arguments.
cout << "After the computation of smf for constraints" << endl;
#endif
}
#if VERY_NOISY
cout << "=== ph[0] constraints ===" << endl;
ph[0].constraints().ascii_dump(cout);
cout << "=== ph[1] constraints ===" << endl;
ph[1].constraints().ascii_dump(cout);
cout << endl;
#endif
ph[0].intersection_assign(ph[1]);
// Compute the intersection of ph[2] and ph[3].
#if VERY_NOISY
// Print dimensions of arguments
// (being careful to override library laziness).
cout << "Computing intersection of ph[2] and ph[3]:" << endl;
cout << "=== ph[2] generators ===" << endl;
ph[2].generators().ascii_dump(cout);
cout << "=== ph[3] generators ===" << endl;
ph[3].generators().ascii_dump(cout);
#endif
if (enhanced) {
ph[2].minimized_constraints();
ph[3].minimized_constraints();
#if VERY_NOISY
// Print dimensions of arguments.
cout << "After the computation of smf for constraints" << endl;
#endif
}
#if VERY_NOISY
cout << "=== ph[2] constraints ===" << endl;
ph[2].constraints().ascii_dump(cout);
cout << "=== ph[3] constraints ===" << endl;
ph[3].constraints().ascii_dump(cout);
cout << endl;
#endif
ph[2].intersection_assign(ph[3]);
// Compute the poly-hull of ph[0] and ph[2].
#if VERY_NOISY
cout << "Computing poly-hull of ph[0] and ph[2]:" << endl;
#endif
if (enhanced) {
ph[0].minimized_generators();
ph[2].minimized_generators();
#if VERY_NOISY
// Print dimensions of arguments.
cout << "After the computation of smf for generators" << endl;
#endif
}
#if VERY_NOISY
// Print dimensions of arguments
// (being careful to override library laziness).
cout << "=== ph[0] generators ===" << endl;
ph[0].generators().ascii_dump(cout);
cout << "=== ph[2] generators ===" << endl;
ph[2].generators().ascii_dump(cout);
cout << endl;
#endif
ph[0].poly_hull_assign(ph[2]);
ph[0].constraints();
#if NOISY
cout << "Wmf final result timing: ";
print_clock(cout);
cout << endl;
#endif
#if VERY_NOISY
// How many constraints and generators obtained?
cout << "Final result (wmf)" << endl;
cout << "=== ph[0] constraints ===" << endl;
ph[0].constraints().ascii_dump(cout);
cout << endl;
#endif
#if NOISY
cout << "Smf (cons) final result timing: ";
start_clock();
ph[0].minimized_constraints();
print_clock(cout);
cout << endl;
#endif
#if VERY_NOISY
// How many constraints and generators obtained?
cout << "Final result (smf cons)" << endl;
cout << "=== ph[0] constraints ===" << endl;
ph[0].constraints().ascii_dump(cout);
#endif
}
} // namespace
int
main() {
vector<NNC_Polyhedron> ph;
#if EXP_EVAL
dimension_type first_dim = 4;
dimension_type last_dim = 5;
#else
dimension_type first_dim = 2;
dimension_type last_dim = 4;
#endif
for (dimension_type dims = first_dim; dims <= last_dim; dims++)
for (int perc = 25; perc <= 50; perc += 25) {
#if NOISY
cout << endl
<< "++++++++ DIM = " << dims << " ++++++++"
<< endl
<< "++++++++ PERC = " << perc << " ++++++++"
<< endl;
#endif
// Standard evaluation strategy.
ph.clear();
build_polyhedra(dims, perc, ph);
computation(ph, false);
// Enhanced evaluation strategy.
ph.clear();
build_polyhedra(dims, perc, ph);
computation(ph, true);
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1