pax_global_header 0000666 0000000 0000000 00000000064 13031546015 0014510 g ustar 00root root 0000000 0000000 52 comment=807f6f3b396a1722da38d4670849b3999e41a173
pplacer-1.1.alpha19/ 0000775 0000000 0000000 00000000000 13031546015 0014235 5 ustar 00root root 0000000 0000000 pplacer-1.1.alpha19/.gitignore 0000664 0000000 0000000 00000000411 13031546015 0016221 0 ustar 00root root 0000000 0000000 /_build
TAGS
*.mltop
*.top
*.native
*.swp
*.byte
*.annot
.ocamlinit
.toplevel_history
.latest-upload
top_tests
bin
common_src/install_common_pprs.txt
common_src/version.ml
makefile
docs/generated_rst/
docs/_build/doctrees/
wiki
Session.vim
_builds
_projects
_steps
pplacer-1.1.alpha19/.gitmodules 0000664 0000000 0000000 00000000141 13031546015 0016406 0 ustar 00root root 0000000 0000000 [submodule "docs/_build/html"]
path = docs/_build/html
url = git@github.com:matsen/pplacer.git
pplacer-1.1.alpha19/CHANGELOG 0000664 0000000 0000000 00000053515 13031546015 0015460 0 ustar 00root root 0000000 0000000 1.1.alpha19
-----------
* Closed GH-352: Showing percent identity in the CSV file.
1.1.alpha18
-----------
* Closed GH-346: Adding proper support for ambigious amino acid codes.
1.1.alpha17
-----------
* Closed GH-340: "malformed row in jplace" after pplacer warning "computed function value is infinite or NaN".
* Closed GH-339: Better error message concerning strange mass.
1.1.alpha16
-----------
* Closed GH-334: multiclass_concat.py modifies placement database such that classif_table.py returns accurate tallies.
1.1.alpha15
-----------
* Closed GH-320: Now compiles fine with Batteries 2.
* Closed GH-327: Ignore sequences that aren't in both jplace and sequence files.
* Closed GH-312: An improved script for managing classification results, called ``classif_table.py``; ``classif_rect.py`` is now deprecated.
* Closed GH-315: support ``rppr info`` on reference packages lacking a taxonomy
* Closed GH-316: pplacer warns rather than fails when an alignment looks like nucleotides
* Closed GH-317: ``pplacer --write-masked-out`` respects ``--out-dir``
* Closed GH-318: Apply alignment mask on a per-placement basis
* Closed GH-319: ``pplacer --write-pre-masked`` no longer exits after writing mask.
* Closed GH-322: Moved to Batteries version 2.1.0. Supports OCaml 4.01.0
* Closed GH-323: ``pplacer``, ``guppy``, and ``rppr`` support gzip-compressed alignment and ``.jplace`` files.
* Closed GH-324: ``deduplicate_sequences.py`` supports gzip-compressed FASTA files.
1.1.alpha14
-----------
* Closed GH-181: Added ``guppy indep_c``; added ``--leaf-values`` to ``guppy mft``.
* Closed GH-215: Added ``pca_for_qiime.py`` and ``extract_taxonomy_from_biom.py``;
changed guppy and rppr to allow BIOM files to be passed as arguments where
placefiles are allowed.
* Closed GH-241: On the NBC classifier of ``guppy classify``: renamed
``--target-rank`` to ``--nbc-rank``; added ``--nbc-rank auto``.
* Closed GH-248: Added premasking by default to the NBC classifier of ``guppy
classify``; correspondingly added ``--no-pre-mask``.
* Closed GH-250: Completely revamped classification.
* Closed GH-251: Added the hybrid5 classifier.
* Closed GH-256: Added ``--mmap-file`` to pplacer; changed ``--pretend`` in
pplacer to show the amount of memory which would be allocated.
* Closed GH-259: Added ``guppy mcl`` and a ``--mcl`` flag to ``guppy compress``.
* Closed GH-260: Added ``rooted_pd`` to ``guppy fpd``; Added a ``--variance`` flag
to ``guppy rarefact``.
* Closed GH-261: Added ``rppr convex_taxids``.
* Closed GH-262: Added ``--as-mass`` to ``guppy redup``; updated
``sort_placefile.py`` for the new placefile format; fixed pplacer to better
deal with internal edges on a tree with a branch length of 0.
* Closed GH-263: Fixed a bug that could sometimes cause failures in ``rppr
min_adcl`` with the PAM algorithm.
* Closed GH-265: Fixed a bug that could cometimes cause ``rppr reroot`` to
return a suboptimal rooting.
* Closed GH-266: Adding ``map_ratio`` and ``map_overlap`` columns to ``guppy
to_csv``.
* Closed GH-267: Added a ``leaf_count`` column to ``rppr convex_taxids``.
* Closed GH-268: Merged various minor fixes.
* Closed GH-273: Fix convexify for multifurcating trees
* Closed GH-274: Added ``--weight-as-count`` to ``guppy rarefact``.
* Closed GH-276: Added ``-k`` to ``guppy rarefact``.
* Closed GH-277: Added ``--weight-as-count`` to ``guppy rarefy``.
* Closed GH-278: Changed ``guppy rarefact`` to allow multiple placefiles to be
passed instead of just one.
* Closed GH-282: Added a ``--inflation`` flag to ``guppy mcl`` and ``guppy
compress``.
* Closed GH-286: Changed pplacer's ``--mmap-file`` to accept a path to either a
directory or a file.
* Closed GH-287: Added a more informative error message for the case of an
input alignment containing some, but not all reference sequence names.
* Closed GH-288: Added ``guppy placemat``
* Closed GH-290: Random tie breaking in NBC classifier
* Closed GH-291: Added qD(T) alpha diversity measure from Chao et. al., 2010
(doi:10.1098/rstb.2010.0272)
* Closed GH-293: Switched build system to use OPAM
* Closed GH-294: Added ``--unitize`` option to ``guppy squash``
* Closed GH-297: Support multiprocessing during squash cluster bootstrapping
* Closed GH-298: Faster upper-limit finding during integration
* Closed GH-299: Fix NaN likelihoods for empirical frequencies + unseen state
* Closed GH-303: Updated Batteries dependency to version 2.0.0
* Closed GH-305: Eliminate compilation warnings from CDD
* Closed GH-306: Random tie breaking is default in NBC
* Closed GH-307: Renamed ``--kappa`` to ``--theta``, ``awpd`` to ``bwpd`` in ``guppy fpd``
* Closed GH-309: Support overlap minimization (SOM) added to ``guppy epca`` (see also GH-221)
1.1.alpha13
-----------
* Fixed a bug where pplacer would sometimes fail abruptly with a Child_error
of EBADF on close(2). [rc2]
* Added missing ``-o`` and related flags to ``guppy to_csv``. [rc3]
* Fixed minor errors in the documentation [r2]
* Closed GH-216: Added ``guppy trim`` and ``guppy check``.
* Closed GH-225: Added ``rppr vorotree``.
* Closed GH-235: Added ``--rep-edges`` flag for the splitify subcommands.
* Closed GH-237: Added a multiplicity column to ``guppy diplac``.
* Closed GH-238: Added ``--epsilon`` for splitify commands to filter constant
edges out of the resulting splitify matrices.
* Closed GH-239: Added the ``pam`` algorithm to voronoi commands; cleaned up
voronoi full algorithm and implementation.
* Closed GH-240: Added a ``-o`` flag for pplacer.
* Closed GH-242: Renamed ECLD to ADCL; added --max-adcl to voronoi commands.
* Closed GH-243: Updated ``rppr reroot`` so it can run on reference packages
which have unannotated sequences.
* Closed GH-244: Updated ``rppr infer`` to handle sequences which could not be
reasonably placed anywhere on the tree.
* Closed GH-245: Updated code to allow refpkgs to be passed as .zip files as
well as directories.
* Closed GH-246: Added --always-include to voronoi commands.
* Closed GH-247: Added ``guppy unifrac``.
* Closed GH-249: Added ``guppy rarefy``.
* Closed GH-252: Added ``--all-alternates`` to ``rppr convexify``.
* Closed GH-253: Added ``--no-collapse`` to ``guppy diplac``.
* Closed GH-255: Added ``guppy to_csv``.
* Closed GH-257: Renamed ``rppr voronoi`` to ``rppr min_adcl``, ``rppr vorotree`` to
``rppr min_adcl_tree``, and ``guppy diplac`` to ``guppy adcl``. Added ``--seed`` to
``rppr min_adcl`` and ``rppr min_adcl_tree``.
* Closed GH-280: Fixed a bug in which pplacer would fail if passed -t and
-s flags without also passing a -c or -r flag.
1.1.alpha12
-----------
* Added ``guppy to_rdp`` and ``guppy classify_rdp``.
* Closed GH-113: Updated the ``best_classification`` and ``multiclass`` SQL views;
correspondingly changed the flags to ``rppr prep_db``; added the
``placement_evidence`` table for bayes classification.
* Closed GH-183: Added documentation for more functions.
* Closed GH-189: Added ``guppy pentropy``.
* Closed GH-191: Added -m to ``guppy redup``; bumped the jplace format version
to 3 with the ability to give each name for a pquery a different mass.
* Closed GH-192: Added ``rppr infer``.
* Closed GH-193: Added ``rppr reclass``.
* Closed GH-194: Added a ``mass`` column to ``placement_names`` to parallel new
features in the jplace format.
* Closed GH-195: Added a --groups flag to pplacer for placing metagenomic
sequences onto trees built from very wide alignments.
* Closed GH-196: Added code to pplacer to better handle errors raised when
calling fork(2).
* Closed GH-198: Added progress reporting code to ``guppy compress``.
* Closed GH-199: Renamed ``guppy pentropy`` to ``guppy entropy``; added quadratic
entropy calculation.
* Closed GH-200: Added --discard-below to ``guppy {islands,compress}``.
* Closed GH-201: Added a setup.py file to the scripts directory.
* Closed GH-202: Added ``rppr prepsim``; added --include-pendant to
``guppy diplac``.
* Closed GH-204: Added more columns to ``rppr reclass``.
* Closed GH-205: Added ``guppy error``.
* Closed GH-206: Updated some pplacer documentation.
* Closed GH-207: Added CSV output to ``guppy edpl``.
* Closed GH-208: Fixed the -o flag to reflect the actual file written to for
``guppy {sing,tog,edpl}``.
* Closed GH-209: Fixed a bug preventing Gcat_model refinement if the supplied
alignment had a different number of sites from the refpkg; added
--always-refine to pplacer.
* Closed GH-210: Merged ``guppy {pd,wpd,entropy}`` into ``guppy fpd``.
* Closed GH-212: Changed parsing error messages to be more specific.
* Closed GH-213: Added PyNAST support to refpkg_align.py.
* Closed GH-214: Added ``guppy ograph``.
* Closed GH-218: Added --split-csv to ``guppy merge``.
* Closed GH-219: Fixed some guppy commands which needed a zero root branch
length.
* Closed GH-220: Added error messages for some exceptions; fixed
``guppy rarefact``.
* Closed GH-222: Added a -c flag to ``guppy bary``.
* Closed GH-236: Fixed support for numeric leaf names when writing out XML.
1.1.alpha11
-----------
* Fixed a bug with parsing MAP identity from a jplace file.
* Fixed a bug that occurred sometimes when running ``rppr convexify`` on a tree
where not every leaf had a corresponding tax_id at a particular rank.
* Fixed a bug with fasttree placements which caused failure when the site
categories had to be calculated (ie. when using a combined reference + query
alignment)
* Changed versions to be parsed only out of git tags.
* Closed GH-42: Added --edpl flag to ``guppy fat`` for EDPL coloring in fat
trees.
* Closed GH-146: Added an --unweighted flag to ``guppy pca``.
* Closed GH-168: Changed guppy and rppr to list the subcommands in --help;
reformatted the options flags to be more readable.
* Closed GH-169: Fixed all commands that work on reference packages to use the
-c flag to specify the reference package.
* Closed GH-176: Fixed ``rppr reroot`` to handle cases where not all tax_ids are
specified under the rank the rerooting is happening at.
* Closed GH-177: Added --mass-gt and --mass-le flags to ``guppy filter``.
* Closed GH-178: Fixed ``guppy compress`` to add a zero root branch length.
* Closed GH-179: Changed the JSON emitter to be able to represent a wider
range of floats.
* Closed GH-182: Changed 'weighted' to 'spread' and 'unweighted' to 'point'
across all the guppy and rppr commands.
* Closed GH-184: Added a placement_median_identites table for guppy classify.
* Closed GH-188: Added support for a reference package to be able to specify
that some reference sequences are unclassified.
1.1.alpha10
-----------
* Closed GH-126: Split Glv/Model into Gmix_model and Gcat_model with the
option of adding more models to pplacer later.
* Closed GH-154: Added ``guppy islands``.
* Closed GH-156: Added functionality for calculating multiple KR distances
with only one tree traversal.
* Closed GH-157: Added ``guppy compress``.
* Closed GH-162: Added fig ranking to pplacer.
* Closed GH-163: Added a --node-numbers flag to every command that emits a
phyloxml tree which adds the tree's node numbers to the phyloxml output as
bootstrap values.
* Closed GH-172: Switched from using xml-light to xmlm.
1.1.alpha09
-----------
* Fixed a bug that was making classifications appear too specific when the
placement was on the edge just proximal to an MRCA.
* Fixed a bug wherein the Newick parser would add a '.' to the end of leaf
names if the name was an integer.
* In fixing a bug, made ``guppy diplac`` only emit the first name in a pquery in
its results.
* Fixed a bug that caused the trailing } in a JSON file to be omitted when the
file was large enough.
* Added a ``multiclass`` view and associated parameters to ``rppr prep_db``.
* Fixed a bug where sometimes placements that fell too close to the root would
vanish with the --map-identity flag on.
* Fixed identity to give 0% sequence identity in the case of no overlap
between sequences.
* Fixed a bug by flushing all output buffers before forking, so that the same
data isn't written multiple times.
* Fixed a bug in pplacer in which it wouldn't write the original reference
tree when creating a placefile.
* Fixed some issues with phyloxml generation.
* Closed GH-27: Reorganized functions that operate on alignments.
* Closed GH-67: Added ``guppy wpd``.
* Closed GH-72: Added new features to ``rppr convexify`` and fixed the
implementation of the convexify algorithm, as it cut too many leaves in some
corner cases.
* Closed GH-75: Changed mass maps to use records types instead of tuples.
* Closed GH-76: Added a check in ``guppy classify`` to ensure that the sqlite
database has been properly initialized.
* Closed GH-78: Added an --average flag to ``guppy fat``.
* Closed GH-81: Removed old code that was deprecated by batteries; changed
most code to be using batteries.
* Closed GH-82: Merged the ``pick`` branch into dev.
* Closed GH-84: Renamed .json to .jplace for new-format placefiles.
* Closed GH-85: Added better error messages for potential premasking failures.
* Closed GH-86: Dropped support for older versions of the reference package
format.
* Closed GH-88: Improved handling very small alphas in pplacer, working around
a problem with the GSL that wasn't allowing us to invert the CDF for the
gamma distribution.
* Closed GH-89: Fixed some bugs in the convexify algorithm.
* Closed GH-90: Added an error message for if pplacer is invoked with no
arguments.
* Closed GH-91: Added more documentation to .mli files.
* Closed GH-92: Added searching and alignment scripts.
* Closed GH-94: Improved the leaf selection criteria in ``rppr voronoi``.
* Closed GH-96: Now using colors from colorbrewer2.org for heat.
* Closed GH-98: Added a --map-identity flag to pplacer.
* Closed GH-99: Added more examples for guppy batchfiles.
* Closed GH-101: Added virtual placefiles to guppy batchfiles.
* Closed GH-103: Added batteries as a dependency.
* Closed GH-104: Added a naive reference implementation of convexify,
accessible with a --naive flag.
* Closed GH-105: Added parameter substitution to guppy batchfiles.
* Closed GH-108: Added more data from jplace files into the taxtable schema;
added a way to change the cutoff for best_classifications.
* Closed GH-109: Added a ``rppr info`` subcommand.
* Closed GH-110: Added a --no-early flag to ``rppr convexify``.
* Closed GH-111: Added a script to update reference packages to version 1.1.
* Closed GH-112: Improved some of pplacer's error messages.
* Closed GH-114: Changed MAP identity in placefiles to be stored flat instead
of nested.
* Closed GH-115: Updated the documentation to reflect changes to the SQL
schema in ``rppr prep_db``.
* Closed GH-116: Added --keep-at-most and --keep-factor flags to pplacer.
* Closed GH-117: Added the output of ``git describe`` to --version output.
* Closed Gh-118: Added a --quiet flag to guppy and rppr.
* Closed GH-119: Added a ``rppr reroot`` subcommand.
* Closed GH-120: Added a --rank-limit flag to ``rppr convexify``.
* Closed GH-122: Renamed ``rppr taxtable`` to ``rppr prep_db``.
* Closed GH-124: Rewrote the Newick parser.
* Closed GH-125: Added a --rooted flag to ``rppr convexify``.
* Closed GH-128: Added informative priors to pplacer integration.
* Closed GH-129: Added the ability for ``rppr convexify`` to convexify a tree
not in a reference package.
* Closed GH-130: Added ``guppy pd``.
* Closed GH-131: Changed pplacer to set some defaults with the -p flag.
* Closed GH-133: Added edge painting classification by default to pplacer and
a corresponding --painted flag to ``rppr ref_tree``.
* Re-closed GH-133: Added checks for the case when not all ranks are
represented by some sequence in the reference package.
* Closed GH-135: Generally improved error messages in pplacer, guppy, and
rppr.
* Closed GH-138: Removed the --transform flag from everything except ``guppy
mft``; removed the --unweighted flag from commands which don't respect it.
* Closed GH-139: Added a check to pplacer to ensure all query sequences have
at least some overlap with some reference sequence.
* Closed GH-140: Allowed pplacer to be run with -t and without -r or -c.
* Closed GH-141: Removed ``compare_placements.py``; added ``check_placements.py``;
documented the rest of the python scripts.
* Closed GH-143: Changed the --leaves argument to ``rppr voronoi`` to specify
the number of leaves to keep in the tree instead of the number of leaves to
prune.
* Closed GH-144: Changed pplacer to explicitly disallow unplaced sequences
from being written out; changed ``best_classifications`` and ``multiclass`` views
to yield NULL for rows where no placements match all the criteria.
* Closed GH-149: Updated the jplace version to 2; changed the Newick parser
and emitter to allow for the new format of trees with edge numbers specified
in braces instead of brackets.
* Closed GH-153: Changed ``guppy mft`` to not squash name lists to mass by
default.
* Closed GH-155: Changed pplacer to always check for invalid bases when
pre-masking sequences.
* Closed GH-159: Updated to use the v2 batteries API.
* Closed GH-164: Fixed some bugs related to various APIs not knowing how to
deal with node labels on non-leaves.
* Closed GH-167: Fixed an issue where ``rppr reroot`` wasn't updating the bark
of trees correctly.
1.1.alpha08
-----------
* Closed GH-46: Added a --timing flag to pplacer to show where time was spent
during placements.
* Closed GH-47: Added unit tests for gaussian kr distance.
* Closed GH-49: Added a more informative error message to pplacer if reference
sequences occur multiple times in a query file.
* Closed GH-52: Fixed padding in ``guppy squash``.
* Closed GH-58: Improved navigation for the documentation on guppy commands.
* Closed GH-59: Improved documentation for guppy commands using sqlite.
* Closed GH-60: Improved documentation for ``guppy classify``.
* Closed GH-65: Released alpha08.
* Closed GH-66: Added a FAQ to the documentation.
* Closed GH-68: Changed ``guppy info`` to show multiplicity.
* Closed GH-69: Changed ``guppy tog`` to use polytomy instead of a _ delimiter
joining sequence names.
* Closed GH-70: Added documentation for how to compile pplacer.
* Closed GH-73: Added a pre-masking feature to cut out irrelevant columns of
the alignment.
* Closed GH-74: Improved how pplacer dedupes sequences before a placerun.
* Added a script to sort placefiles for easier visual diffs.
* Added more informative error messages when the length of the query alignment
and reference alignment don't match.
* ``guppy edpl`` now calculates the EDPL (expected distance between placement
locations) for placements
1.1.alpha07
-----------
* Fixed a serious issue with any command that used a ``--prefix`` flag.
1.1.alpha06
-----------
* Closed GH-20: efficiency of kr_distance evaluated and approved.
* Closed GH-44: improved sqlite3 support in guppy.
* Closed GH-45: better consistency of output flags across all guppy commands.
* Closed GH-48: better error reporting when loading json placefiles.
* Closed GH-50: fixed the output of ``guppy classify``.
* Closed GH-51: only parsing the first word as a sequence name in a fasta file.
* Renamed the ``--normal`` flag for ``guppy kr`` to ``--gaussian`` to avoid confusion
with normalization.
* Only one shuffle at a time is now stored in memory (big savings, obviously).
* Fixed bug that was throwing off ``guppy kr`` shuffling significance estimation.
* ``guppy pca`` now defaults to scaling eigenvalues to percent variance; now has
a --raw-eval flag to specify otherwise.
* Fixed all of the sequence parsers to be tail-recursive, so parsing large
files no longer causes segfaults.
* Added a ``guppy redup`` command for re-adding duplicate sequences to
placefiles generated from deduplicated sequence files.
1.1.alpha05
-----------
* Closed GH-11: options for the tree-generating subcommands are more uniform.
* Closed GH-22: added more unit tests for ``guppy kr``.
* Closed GH-32: using power iteration rather than full
eigendecomposition. Leads to 60x speedup for PCA on demo data.
* Closed GH-35: added a remark in the documentation about multiple comparison.
* Closed GH-41: added docs for the json placefile format.
* Added ``guppy splitify``. Spits out differences of mass across splits.
* Changed default behavior of ``guppy kr`` to not normalize, and
correspondingly added in a ``--normalize`` command line flag.
* Improved documentation.
* Moved ``guppy heat`` to ``guppy kr_heat``.
* The ``guppy heat`` subcommand now maps an arbitrary vector to a phylogenetic
tree contained in a reference package.
* Removed redundant ``classic`` subcommand from guppy.
* Changed ``guppy round`` to use the new placefile format.
* Added support for posterior probabilities in json placefiles.
* Removed csv and old-placefile-format generation from pplacer.
* Added the ability to run pplacer in multiple processes in parallel with the
-j flag.
* Removed friend-finding from pplacer, as it was superseded by some of the
multiprocessing code.
1.1.alpha03 to 1.1.alpha04
--------------------------
* Closed GH-12: removed Placement.classif, and renamed
Placement.contain_classif to Placement.classif.
* Closed GH-29: added ``guppy merge`` to merge multiple placefiles.
* Closed GH-30: accepting \r, \n, and \r\n as delimiters everywhere in pplacer
and guppy.
* Closed GH-36: added ``guppy {classic,tog,sing,filter}``. The former three were
originally a part of placeviz, and the lattermost filters placefiles to only
a specific subset of their placements.
* Closed GH-37: added a trailing newline to the end of json files.
* Closed GH-38: added this changelog.
* Bugfix in ``guppy classify``. From the commit:
Previously, a file was being opened and closed for every pquery in every
placerun. This resulted in only the last pquery being classified and
written out. Now only one file is being opened for each placerun.
pplacer-1.1.alpha19/COPYING 0000664 0000000 0000000 00000104513 13031546015 0015274 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
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 3 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
pplacer-1.1.alpha19/Makefile 0000664 0000000 0000000 00000003042 13031546015 0015674 0 ustar 00root root 0000000 0000000 RELEASE=pplacer guppy rppr
DEBUG=pplacer.d guppy.d rppr.d
DESCRIPT:=pplacer-$(shell uname)-$(shell git describe --tags)
all: $(RELEASE)
debug: $(DEBUG)
# For OPAM
OCAML_TOPLEVEL_PATH = $$OCAML_TOPLEVEL_PATH
ifneq ($(OCAML_TOPLEVEL_PATH),)
TOPLEVEL_FLAGS=-I ${OCAML_TOPLEVEL_PATH}
endif
$(RELEASE):
if [ ! -e bin ]; then mkdir bin; fi
make $@.native
cp `readlink $@.native` bin/$@
rm $@.native
%.native %.byte %.p.native:
ocamlbuild $@
clean:
rm -rf bin
rm -f tests.native
ocamlbuild -clean
rm -f *.mltop
%.d: %.d.byte
if [ ! -e bin ]; then mkdir bin; fi
cp "$<" "bin/$@"
%.top: %.byte
find _build -name '*.cmo' -print0 | xargs -0I% basename % .cmo > $*.mltop
ocamlbuild $@
rm $*.mltop
test: tests.native
./tests.native
%.runtop: %.top
rlwrap ./$*.top `find _build -name "*.cmi" | xargs -n1 dirname | sort -u | sed -e 's/^/-I /'` $(TOPLEVEL_FLAGS)
runcaml:
rlwrap ocaml
tags:
otags `find . -name "*.ml" | grep -v "_build"`
docs: gen_docs.native
./gen_docs.native
make -C docs html
touch docs/_build/html/.nojekyll
pplacer-linux.zip: $(RELEASE)
rm -rf $(DESCRIPT)
mkdir $(DESCRIPT)
cp -r bin/* scripts $(DESCRIPT)
zip -r pplacer-linux.zip $(DESCRIPT)/*
rm -rf $(DESCRIPT)
zip: pplacer-linux.zip
.latest-upload: pplacer-linux.zip
curl --upload-file ./pplacer-linux.zip https://transfer.sh/$(DESCRIPT).zip > .latest-upload
upload: .latest-upload
curl -X POST --data-urlencode 'payload={"text": "Latest pplacer uploaded to '$(shell cat .latest-upload)'"}' $(SLACK_URL)
.PHONY: $(RELEASE) clean runcaml tags test docs zip upload
pplacer-1.1.alpha19/README.md 0000664 0000000 0000000 00000001332 13031546015 0015513 0 ustar 00root root 0000000 0000000 # pplacer suite of programs
[](https://app.wercker.com/project/bykey/b3fe580ff3a62d0a69c6da264c03ba81)
`pplacer` places reads on a phylogenetic tree.
`guppy` (Grand Unified Phylogenetic Placement Yanalyzer) yanalyzes them.
`rppr` is a helpful tool for working with reference packages.
* [project webpage (with compiled binaries)](http://matsen.fhcrc.org/pplacer/)
* [documentation](http://matsen.github.com/pplacer/)
* [tutorial](http://fhcrc.github.com/microbiome-demo/)
* [compilation instructions](http://matsen.github.com/pplacer/compiling.html)
`pplacer`, `guppy`, and `rppr` are free software under the GPL v3.
pplacer-1.1.alpha19/_tags 0000664 0000000 0000000 00000000667 13031546015 0015266 0 ustar 00root root 0000000 0000000 <{common,pplacer,json,pdprune,cdd,pam}_src>: include
: include
: include
: pkg_oUnit
: pkg_oUnit
<**/*.ml>: warn_Z, annot
<*/*.annot>: precious
<**/*.{ml,mli,byte,native,top,p.native,d.byte}>: c_pam, c_cdd, c_pplacer, pkg_batteries, pkg_threads, pkg_unix, pkg_bigarray, pkg_gsl, pkg_csv, pkg_xmlm, pkg_str, pkg_sqlite3, pkg_zip, pkg_mcl
pplacer-1.1.alpha19/cdd_src/ 0000775 0000000 0000000 00000000000 13031546015 0015636 5 ustar 00root root 0000000 0000000 pplacer-1.1.alpha19/cdd_src/caml_cdd.c 0000664 0000000 0000000 00000002262 13031546015 0017532 0 ustar 00root root 0000000 0000000 #include
#include
#include
#include
#include
#include
#include
#define Val_none Val_int(0)
value Val_some(value v)
{
CAMLparam1(v);
CAMLlocal1(some);
some = caml_alloc_small(1, 0);
Field(some, 0) = v;
CAMLreturn(some);
}
#define Some_val(v) Field(v,0)
double *extreme_vertices(const double *, const size_t, const size_t, float, float, size_t *);
CAMLprim value caml_extreme_vertices(value vertices, value lower_bound, value upper_bound)
{
CAMLparam3(vertices, lower_bound, upper_bound);
double *vert_arr = Data_bigarray_val(vertices);
int nrows = (Bigarray_val(vertices)->dim[0]);
int ncols = (Bigarray_val(vertices)->dim[1]);
size_t res_size;
double *res = extreme_vertices(vert_arr, nrows, ncols,
Double_val(lower_bound), Double_val(upper_bound), &res_size);
if (res == NULL)
CAMLreturn(Val_none);
else {
value res_bigarr = alloc_bigarray_dims(BIGARRAY_FLOAT64 | BIGARRAY_C_LAYOUT, 2, NULL, res_size / 3, 3);
memcpy(Data_bigarray_val(res_bigarr), res, sizeof *res * res_size);
free(res);
CAMLreturn(Val_some(res_bigarr));
}
}
pplacer-1.1.alpha19/cdd_src/cdd.h 0000664 0000000 0000000 00000032707 13031546015 0016552 0 ustar 00root root 0000000 0000000 /* cdd.h: Header file for cddlib.c
written by Komei Fukuda, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* cddlib.c : C-Implementation of the double description method for
computing all vertices and extreme rays of the polyhedron
P= {x : b - A x >= 0}.
Please read COPYING (GNU General Public Licence) and
the manual cddlibman.tex for detail.
*/
#ifndef __CDD_H
#define __CDD_H
#endif /* __CDD_H */
#ifndef __CDDMP_H
#include "cddmp.h"
#endif /* __CDDMP_H */
#ifndef __CDDTYPES_H
#include "cddtypes.h"
#endif /* __CDDTYPES_H */
#ifdef GMPRATIONAL
#ifndef __CDD_HF
#include "cdd_f.h"
#endif
#endif
/* GLOBAL CONSTANTS and STATISTICS VARIABLES (to be set by dd_set_global_constants() */
extern mytype dd_zero;
extern mytype dd_one;
extern mytype dd_purezero;
extern mytype dd_minuszero;
extern mytype dd_minusone;
extern time_t dd_statStartTime; /* cddlib starting time */
extern long dd_statBApivots; /* basis finding pivots */
extern long dd_statCCpivots; /* criss-cross pivots */
extern long dd_statDS1pivots; /* phase 1 pivots */
extern long dd_statDS2pivots; /* phase 2 pivots */
extern long dd_statACpivots; /* anticycling (cc) pivots */
#ifdef GMPRATIONAL
extern long dd_statBSpivots; /* basis status checking pivots */
#endif
extern dd_LPSolverType dd_choiceLPSolverDefault; /* Default LP solver Algorithm */
extern dd_LPSolverType dd_choiceRedcheckAlgorithm; /* Redundancy Checking Algorithm */
extern dd_boolean dd_choiceLexicoPivotQ; /* whether to use the lexicographic pivot */
/* to be used to avoid creating temporary spaces for mytype */
#define dd_almostzero 1.0E-7
/* ---------- FUNCTIONS MEANT TO BE PUBLIC ---------- */
#if defined(__cplusplus)
extern "C" {
#endif
/* basic matrix manipulations */
void dd_InitializeArow(dd_colrange,dd_Arow *);
void dd_InitializeAmatrix(dd_rowrange,dd_colrange,dd_Amatrix *);
void dd_InitializeBmatrix(dd_colrange, dd_Bmatrix *);
dd_SetFamilyPtr dd_CreateSetFamily(dd_bigrange,dd_bigrange);
void dd_FreeSetFamily(dd_SetFamilyPtr);
dd_MatrixPtr dd_CreateMatrix(dd_rowrange,dd_colrange);
void dd_FreeAmatrix(dd_rowrange,dd_colrange,dd_Amatrix);
void dd_FreeArow(dd_colrange, dd_Arow);
void dd_FreeBmatrix(dd_colrange,dd_Bmatrix);
void dd_FreeDDMemory(dd_PolyhedraPtr);
void dd_FreePolyhedra(dd_PolyhedraPtr);
void dd_FreeMatrix(dd_MatrixPtr);
void dd_SetToIdentity(dd_colrange, dd_Bmatrix);
/* sign recognitions */
dd_boolean dd_Nonnegative(mytype);
dd_boolean dd_Nonpositive(mytype);
dd_boolean dd_Positive(mytype);
dd_boolean dd_Negative(mytype);
dd_boolean dd_EqualToZero(mytype);
dd_boolean dd_Nonzero(mytype);
dd_boolean dd_Equal(mytype,mytype);
dd_boolean dd_Larger(mytype,mytype);
dd_boolean dd_Smaller(mytype,mytype);
void dd_abs(mytype, mytype);
void dd_LinearComb(mytype, mytype, mytype, mytype, mytype);
void dd_InnerProduct(mytype, dd_colrange, dd_Arow, dd_Arow);
/* major cddlib operations */
dd_MatrixPtr dd_CopyInput(dd_PolyhedraPtr);
dd_MatrixPtr dd_CopyOutput(dd_PolyhedraPtr);
dd_MatrixPtr dd_CopyInequalities(dd_PolyhedraPtr);
dd_MatrixPtr dd_CopyGenerators(dd_PolyhedraPtr);
dd_SetFamilyPtr dd_CopyIncidence(dd_PolyhedraPtr);
dd_SetFamilyPtr dd_CopyAdjacency(dd_PolyhedraPtr);
dd_SetFamilyPtr dd_CopyInputIncidence(dd_PolyhedraPtr);
dd_SetFamilyPtr dd_CopyInputAdjacency(dd_PolyhedraPtr);
dd_boolean dd_DDFile2File(char *ifile, char *ofile, dd_ErrorType *err);
dd_boolean dd_DDInputAppend(dd_PolyhedraPtr*, dd_MatrixPtr, dd_ErrorType*);
dd_MatrixPtr dd_PolyFile2Matrix(FILE *f, dd_ErrorType *);
dd_PolyhedraPtr dd_DDMatrix2Poly(dd_MatrixPtr, dd_ErrorType *);
dd_PolyhedraPtr dd_DDMatrix2Poly2(dd_MatrixPtr, dd_RowOrderType, dd_ErrorType *);
dd_boolean dd_Redundant(dd_MatrixPtr, dd_rowrange, dd_Arow, dd_ErrorType *); /* 092 */
dd_rowset dd_RedundantRows(dd_MatrixPtr, dd_ErrorType *); /* 092 */
dd_boolean dd_SRedundant(dd_MatrixPtr, dd_rowrange, dd_Arow, dd_ErrorType *); /* 093a */
dd_rowset dd_SRedundantRows(dd_MatrixPtr, dd_ErrorType *); /* 093a */
dd_rowset dd_RedundantRowsViaShooting(dd_MatrixPtr, dd_ErrorType *); /* 092 */
dd_rowrange dd_RayShooting(dd_MatrixPtr, dd_Arow intpt, dd_Arow direction); /* 092 */
/* 092, find the first inequality "hit" by a ray from an intpt. */
dd_boolean dd_ImplicitLinearity(dd_MatrixPtr, dd_rowrange, dd_Arow, dd_ErrorType *); /* 092 */
dd_rowset dd_ImplicitLinearityRows(dd_MatrixPtr, dd_ErrorType *); /* 092 */
int dd_FreeOfImplicitLinearity(dd_MatrixPtr, dd_Arow, dd_rowset *, dd_ErrorType *) ; /* 094 */
dd_boolean dd_MatrixCanonicalizeLinearity(dd_MatrixPtr *, dd_rowset *,dd_rowindex *, dd_ErrorType *); /* 094 */
dd_boolean dd_MatrixCanonicalize(dd_MatrixPtr *, dd_rowset *, dd_rowset *, dd_rowindex *, dd_ErrorType *); /* 094 */
dd_boolean dd_MatrixRedundancyRemove(dd_MatrixPtr *M, dd_rowset *redset,dd_rowindex *newpos, dd_ErrorType *); /* 094 */
dd_boolean dd_FindRelativeInterior(dd_MatrixPtr, dd_rowset *, dd_rowset *, dd_LPSolutionPtr *, dd_ErrorType *); /* 094 */
dd_boolean dd_ExistsRestrictedFace(dd_MatrixPtr, dd_rowset, dd_rowset, dd_ErrorType *); /* 0.94 */
dd_boolean dd_ExistsRestrictedFace2(dd_MatrixPtr, dd_rowset, dd_rowset, dd_LPSolutionPtr *, dd_ErrorType *); /* 0.94 */
dd_SetFamilyPtr dd_Matrix2Adjacency(dd_MatrixPtr, dd_ErrorType *); /* 093 */
dd_SetFamilyPtr dd_Matrix2WeakAdjacency(dd_MatrixPtr, dd_ErrorType *); /* 093a */
long dd_MatrixRank(dd_MatrixPtr, dd_rowset, dd_colset, dd_rowset *, dd_colset *);
/* Matrix Basic Operations */
dd_MatrixPtr dd_MatrixCopy(dd_MatrixPtr); /* a new name for dd_CopyMatrix */
dd_MatrixPtr dd_CopyMatrix(dd_MatrixPtr); /* 090c, kept for compatibility */
dd_MatrixPtr dd_MatrixNormalizedCopy(dd_MatrixPtr); /* 094 */
dd_MatrixPtr dd_MatrixNormalizedSortedCopy(dd_MatrixPtr,dd_rowindex*); /* 094 */
dd_MatrixPtr dd_MatrixUniqueCopy(dd_MatrixPtr,dd_rowindex*); /* 094 */
dd_MatrixPtr dd_MatrixNormalizedSortedUniqueCopy(dd_MatrixPtr,dd_rowindex*); /* 094 */
dd_MatrixPtr dd_MatrixSortedUniqueCopy(dd_MatrixPtr,dd_rowindex*); /* 094 */
dd_MatrixPtr dd_MatrixAppend(dd_MatrixPtr, dd_MatrixPtr); /* a name for dd_AppendMatrix */
dd_MatrixPtr dd_AppendMatrix(dd_MatrixPtr, dd_MatrixPtr); /* 090c, kept for compatibility */
int dd_MatrixAppendTo(dd_MatrixPtr*, dd_MatrixPtr); /* 092 */
int dd_Remove(dd_MatrixPtr*, dd_rowrange); /* 092 */
dd_MatrixPtr dd_MatrixSubmatrix(dd_MatrixPtr, dd_rowset delset); /* 092 */
dd_MatrixPtr dd_MatrixSubmatrix2(dd_MatrixPtr, dd_rowset delset,dd_rowindex*); /* 094. It returns new row positions. */
dd_MatrixPtr dd_MatrixSubmatrix2L(dd_MatrixPtr, dd_rowset delset,dd_rowindex*); /* 094. Linearity shifted up. */
int dd_MatrixShiftupLinearity(dd_MatrixPtr *,dd_rowindex *); /* 094 */
int dd_MatrixRowRemove(dd_MatrixPtr *M, dd_rowrange r); /* 092 */
int dd_MatrixRowRemove2(dd_MatrixPtr *M, dd_rowrange r,dd_rowindex*); /* 094*/
int dd_MatrixRowsRemove(dd_MatrixPtr *M, dd_rowset delset); /* 094 */
int dd_MatrixRowsRemove2(dd_MatrixPtr *M, dd_rowset delset,dd_rowindex*); /* 094 */
/* input/output */
void dd_SetInputFile(FILE **f,dd_DataFileType inputfile, dd_ErrorType *);
void dd_SetWriteFileName(dd_DataFileType, dd_DataFileType, char, dd_RepresentationType);
void dd_WriteAmatrix(FILE *, dd_Amatrix, dd_rowrange, dd_colrange);
void dd_WriteArow(FILE *f, dd_Arow a, dd_colrange);
void dd_WriteBmatrix(FILE *, dd_colrange, dd_Bmatrix T);
void dd_WriteMatrix(FILE *, dd_MatrixPtr);
void dd_MatrixIntegerFilter(dd_MatrixPtr);
void dd_WriteReal(FILE *, mytype);
void dd_WriteNumber(FILE *f, mytype x);
/* write a number depending on the arithmetic used. */
void dd_WritePolyFile(FILE *, dd_PolyhedraPtr);
void dd_WriteRunningMode(FILE *, dd_PolyhedraPtr);
void dd_WriteErrorMessages(FILE *, dd_ErrorType);
void dd_WriteSetFamily(FILE *, dd_SetFamilyPtr);
void dd_WriteSetFamilyCompressed(FILE *, dd_SetFamilyPtr);
void dd_WriteProgramDescription(FILE *);
void dd_WriteDDTimes(FILE *, dd_PolyhedraPtr);
void dd_WriteTimes(FILE *, time_t, time_t);
void dd_WriteIncidence(FILE *, dd_PolyhedraPtr);
void dd_WriteAdjacency(FILE *, dd_PolyhedraPtr);
void dd_WriteInputAdjacency(FILE *, dd_PolyhedraPtr);
void dd_WriteInputIncidence(FILE *, dd_PolyhedraPtr);
/* functions and types for LP solving */
dd_LPPtr dd_Matrix2LP(dd_MatrixPtr, dd_ErrorType *);
/* Load a matrix to create an LP object. */
dd_LPPtr dd_Matrix2Feasibility(dd_MatrixPtr, dd_ErrorType *);
/* Load a matrix to create an LP object for feasibility (obj == 0) .*/ /* 094 */
dd_LPPtr dd_Matrix2Feasibility2(dd_MatrixPtr, dd_rowset, dd_rowset, dd_ErrorType *);
/* Load a matrix to create an LP object for feasibility with additional equality and
strict inequality constraints. */ /* 094 */
dd_boolean dd_LPSolve(dd_LPPtr,dd_LPSolverType,dd_ErrorType *);
dd_boolean dd_LPSolve0(dd_LPPtr,dd_LPSolverType,dd_ErrorType *);
void dd_CrissCrossSolve(dd_LPPtr lp,dd_ErrorType *);
void dd_DualSimplexSolve(dd_LPPtr lp,dd_ErrorType *);
dd_LPPtr dd_MakeLPforInteriorFinding(dd_LPPtr);
dd_LPSolutionPtr dd_CopyLPSolution(dd_LPPtr); /* 0.90c */
void dd_WriteLP(FILE *, dd_LPPtr); /* 092 */
dd_LPPtr dd_CreateLPData(dd_LPObjectiveType,dd_NumberType,dd_rowrange,dd_colrange);
int dd_LPReverseRow(dd_LPPtr, dd_rowrange);
/* reverse the i-th row (1 <= i <= no. of rows) */
int dd_LPReplaceRow(dd_LPPtr, dd_rowrange, dd_Arow);
/* replace the i-th row (1 <= i <= no. of rows) */
dd_Arow dd_LPCopyRow(dd_LPPtr, dd_rowrange);
/* copy the i-th row (1 <= i <= no. of rows) */
void dd_FreeLPData(dd_LPPtr);
void dd_FreeLPSolution(dd_LPSolutionPtr);
void dd_WriteLPResult(FILE *, dd_LPPtr, dd_ErrorType);
void dd_WriteLPErrorMessages(FILE *, dd_ErrorType);
void dd_WriteLPTimes(FILE *, dd_LPPtr);
void dd_WriteLPStats(FILE *f);
void dd_WriteLPMode(FILE *f);
dd_MatrixPtr dd_FourierElimination(dd_MatrixPtr,dd_ErrorType *);
dd_MatrixPtr dd_BlockElimination(dd_MatrixPtr, dd_colset, dd_ErrorType *);
#if defined(__cplusplus)
}
#endif
/* ---------- FUNCTIONS MEANT TO BE NON-PUBLIC ---------- */
void dd_QuickSort(dd_rowindex, long, long, dd_Amatrix, long);
void dd_RandomPermutation(dd_rowindex, long, unsigned int seed);
void dd_UniqueRows(dd_rowindex, long, long, dd_Amatrix, long, dd_rowset, long *);
dd_boolean dd_DoubleDescription(dd_PolyhedraPtr, dd_ErrorType*);
dd_boolean dd_DoubleDescription2(dd_PolyhedraPtr, dd_RowOrderType, dd_ErrorType *);
void dd_FreeDDMemory0(dd_ConePtr);
void dd_fread_rational_value (FILE *f, mytype value);
void dd_sread_rational_value (char *s, mytype value);
void dd_AddNewHalfspace1(dd_ConePtr, dd_rowrange);
void dd_AddNewHalfspace2(dd_ConePtr, dd_rowrange);
void dd_AddRay(dd_ConePtr, mytype *);
void dd_AddArtificialRay(dd_ConePtr);
void dd_AValue(mytype*,dd_colrange, dd_Amatrix, mytype *, dd_rowrange);
void dd_CheckAdjacency(dd_ConePtr, dd_RayPtr*, dd_RayPtr*, dd_boolean *);
void dd_CheckEquality(dd_colrange, dd_RayPtr *, dd_RayPtr *, dd_boolean *);
void dd_ComputeRowOrderVector(dd_ConePtr);
void dd_ConditionalAddEdge(dd_ConePtr,dd_RayPtr, dd_RayPtr, dd_RayPtr);
void dd_CopyArow(mytype *, mytype *, dd_colrange);
void dd_CopyNormalizedAmatrix(mytype **, mytype **, dd_rowrange, dd_colrange);
void dd_CopyNormalizedArow(mytype *, mytype *, dd_colrange);
void dd_CopyAmatrix(mytype **, mytype **, dd_rowrange, dd_colrange);
void dd_PermuteCopyAmatrix(mytype **, mytype **, dd_rowrange, dd_colrange, dd_rowindex);
void dd_PermutePartialCopyAmatrix(mytype **, mytype **, dd_rowrange, dd_colrange, dd_rowindex,dd_rowrange, dd_rowrange);
void dd_CopyBmatrix(dd_colrange, dd_Bmatrix T, dd_Bmatrix TCOPY);
void dd_CopyRay(mytype *, dd_colrange, dd_RayPtr,
dd_RepresentationType, dd_colindex);
void dd_CreateInitialEdges(dd_ConePtr);
void dd_CreateNewRay(dd_ConePtr, dd_RayPtr, dd_RayPtr, dd_rowrange);
void dd_Eliminate(dd_ConePtr, dd_RayPtr*);
void dd_EvaluateARay1(dd_rowrange, dd_ConePtr);
void dd_EvaluateARay2(dd_rowrange, dd_ConePtr);
void dd_FeasibilityIndices(long *, long *, dd_rowrange, dd_ConePtr);
void dd_FindBasis(dd_ConePtr, long *rank);
void dd_FindInitialRays(dd_ConePtr, dd_boolean *);
void dd_ColumnReduce(dd_ConePtr);
void dd_GaussianColumnPivot(dd_rowrange, dd_colrange, dd_Amatrix, dd_Bmatrix, dd_rowrange, dd_colrange);
dd_boolean dd_LexSmaller(mytype *, mytype *, long);
dd_boolean dd_LexLarger(mytype *, mytype *, long);
dd_boolean dd_LexEqual(mytype *, mytype *, long);
void dd_Normalize(dd_colrange, mytype *);
void dd_MatrixIntegerFilter(dd_MatrixPtr);
void dd_ProcessCommandLine(FILE*,dd_MatrixPtr, char *);
void dd_SelectNextHalfspace(dd_ConePtr, dd_rowset, dd_rowrange *);
void dd_SelectPivot2(dd_rowrange,dd_colrange,dd_Amatrix,
dd_Bmatrix,dd_RowOrderType,dd_rowindex, dd_rowset,dd_rowrange,dd_rowset,
dd_colset,dd_rowrange *,dd_colrange *,dd_boolean *);
void dd_SelectPreorderedNext(dd_ConePtr, dd_rowset, dd_rowrange *);
void dd_SetInequalitySets(dd_ConePtr);
void dd_SnapToInteger(mytype, mytype);
void dd_StoreRay1(dd_ConePtr, mytype *, dd_boolean *);
void dd_StoreRay2(dd_ConePtr, mytype *, dd_boolean *, dd_boolean *);
void dd_TableauEntry(mytype *, dd_rowrange, dd_colrange, dd_Amatrix, dd_Bmatrix T, dd_rowrange, dd_colrange);
void dd_UpdateEdges(dd_ConePtr, dd_RayPtr, dd_RayPtr);
void dd_UpdateRowOrderVector(dd_ConePtr, dd_rowset PriorityRows);
void dd_WriteRay(FILE *, dd_colrange, dd_RayPtr,
dd_RepresentationType, dd_colindex);
void dd_ZeroIndexSet(dd_rowrange, dd_colrange, dd_Amatrix, mytype *, dd_rowset);
/* New functions to handle data loading, NON-PUBLIC */
dd_NumberType dd_GetNumberType(char *);
dd_ConePtr dd_ConeDataLoad(dd_PolyhedraPtr);
dd_PolyhedraPtr dd_CreatePolyhedraData(dd_rowrange, dd_colrange);
dd_boolean dd_InitializeConeData(dd_rowrange, dd_colrange, dd_ConePtr*);
dd_boolean dd_AppendMatrix2Poly(dd_PolyhedraPtr*, dd_MatrixPtr);
/* end of cddlib.h */
pplacer-1.1.alpha19/cdd_src/cdd.ml 0000664 0000000 0000000 00000001317 13031546015 0016724 0 ustar 00root root 0000000 0000000 module BA = Bigarray
module BA2 = BA.Array2
type float_ba2 = (float, BA.float64_elt, BA.c_layout) BA2.t
external c_extreme_vertices: float_ba2 -> float -> float -> float_ba2 option = "caml_extreme_vertices"
let extreme_vertices lower_bound upper_bound parr =
let ba = BA2.create BA.float64 BA.c_layout (Array.length parr) 3 in
BA2.fill ba (-1.);
Array.iteri
(fun i (a, b) -> BA2.unsafe_set ba i 0 a; BA2.unsafe_set ba i 1 b)
parr;
match c_extreme_vertices ba lower_bound upper_bound with
| Some res ->
Some (Array.init
(BA2.dim1 res)
(fun i ->
let col = BA2.unsafe_get res i in
int_of_float (col 2), col 0, col 1))
| None -> None;
pplacer-1.1.alpha19/cdd_src/cddcore.c 0000664 0000000 0000000 00000161376 13031546015 0017423 0 ustar 00root root 0000000 0000000 /* cddcore.c: Core Procedures for cddlib
written by Komei Fukuda, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* cddlib : C-library of the double description method for
computing all vertices and extreme rays of the polyhedron
P= {x : b - A x >= 0}.
Please read COPYING (GNU General Public Licence) and
the manual cddlibman.tex for detail.
*/
#include "setoper.h" /* set operation library header (Ver. June 1, 2000 or later) */
#include "cdd.h"
#include
#include
#include
#include
#include
void dd_CheckAdjacency(dd_ConePtr cone,
dd_RayPtr *RP1, dd_RayPtr *RP2, dd_boolean *adjacent)
{
dd_RayPtr TempRay;
dd_boolean localdebug=dd_FALSE;
static dd_rowset Face, Face1;
static dd_rowrange last_m=0;
if (last_m!=cone->m) {
if (last_m>0){
set_free(Face); set_free(Face1);
}
set_initialize(&Face, cone->m);
set_initialize(&Face1, cone->m);
last_m=cone->m;
}
if (dd_debug) localdebug=dd_TRUE;
*adjacent = dd_TRUE;
set_int(Face1, (*RP1)->ZeroSet, (*RP2)->ZeroSet);
set_int(Face, Face1, cone->AddedHalfspaces);
if (set_card(Face)< cone->d - 2) {
*adjacent = dd_FALSE;
if (localdebug) {
fprintf(stderr,"non adjacent: set_card(face) %ld < %ld = cone->d.\n",
set_card(Face),cone->d);
}
return;
}
else if (cone->parent->NondegAssumed) {
*adjacent = dd_TRUE;
return;
}
TempRay = cone->FirstRay;
while (TempRay != NULL && *adjacent) {
if (TempRay != *RP1 && TempRay != *RP2) {
set_int(Face1, TempRay->ZeroSet, cone->AddedHalfspaces);
if (set_subset(Face, Face1)) *adjacent = dd_FALSE;
}
TempRay = TempRay->Next;
}
}
void dd_Eliminate(dd_ConePtr cone, dd_RayPtr*Ptr)
{
/*eliminate the record pointed by Ptr^.Next*/
dd_RayPtr TempPtr;
dd_colrange j;
TempPtr = (*Ptr)->Next;
(*Ptr)->Next = (*Ptr)->Next->Next;
if (TempPtr == cone->FirstRay) /*Update the first pointer*/
cone->FirstRay = (*Ptr)->Next;
if (TempPtr == cone->LastRay) /*Update the last pointer*/
cone->LastRay = *Ptr;
/* Added, Marc Pfetsch 010219 */
for (j=0;j < cone->d;j++)
dd_clear(TempPtr->Ray[j]);
dd_clear(TempPtr->ARay);
free(TempPtr->Ray); /* free the ray vector memory */
set_free(TempPtr->ZeroSet); /* free the ZeroSet memory */
free(TempPtr); /* free the dd_Ray structure memory */
cone->RayCount--;
}
void dd_SetInequalitySets(dd_ConePtr cone)
{
dd_rowrange i;
set_emptyset(cone->GroundSet);
set_emptyset(cone->EqualitySet);
set_emptyset(cone->NonequalitySet);
for (i = 1; i <= (cone->parent->m); i++){
set_addelem(cone->GroundSet, i);
if (cone->parent->EqualityIndex[i]==1) set_addelem(cone->EqualitySet,i);
if (cone->parent->EqualityIndex[i]==-1) set_addelem(cone->NonequalitySet,i);
}
}
void dd_AValue(mytype *val, dd_colrange d_size, dd_Amatrix A, mytype *p, dd_rowrange i)
{
/*return the ith component of the vector A x p */
dd_colrange j;
mytype x;
dd_init(x);
dd_set(*val,dd_purezero);
/* Changed by Marc Pfetsch 010219 */
for (j = 0; j < d_size; j++){
dd_mul(x,A[i - 1][j], p[j]);
dd_add(*val, *val, x);
}
dd_clear(x);
}
void dd_StoreRay1(dd_ConePtr cone, mytype *p, dd_boolean *feasible)
{ /* Original ray storing routine when RelaxedEnumeration is dd_FALSE */
dd_rowrange i,k,fii=cone->m+1;
dd_colrange j;
mytype temp;
dd_RayPtr RR;
dd_boolean localdebug=dd_debug;
dd_init(temp);
RR=cone->LastRay;
*feasible = dd_TRUE;
set_initialize(&(RR->ZeroSet),cone->m);
for (j = 0; j < cone->d; j++){
dd_set(RR->Ray[j],p[j]);
}
for (i = 1; i <= cone->m; i++) {
k=cone->OrderVector[i];
dd_AValue(&temp, cone->d, cone->A, p, k);
if (localdebug) {
fprintf(stderr,"dd_StoreRay1: dd_AValue at row %ld =",k);
dd_WriteNumber(stderr, temp);
fprintf(stderr,"\n");
}
if (dd_EqualToZero(temp)) {
set_addelem(RR->ZeroSet, k);
if (localdebug) {
fprintf(stderr,"recognized zero!\n");
}
}
if (dd_Negative(temp)){
if (localdebug) {
fprintf(stderr,"recognized negative!\n");
}
*feasible = dd_FALSE;
if (fii>cone->m) fii=i; /* the first violating inequality index */
if (localdebug) {
fprintf(stderr,"this ray is not feasible, neg comp = %ld\n", fii);
dd_WriteNumber(stderr, temp); fprintf(stderr,"\n");
}
}
}
RR->FirstInfeasIndex=fii;
RR->feasible = *feasible;
dd_clear(temp);
}
void dd_StoreRay2(dd_ConePtr cone, mytype *p,
dd_boolean *feasible, dd_boolean *weaklyfeasible)
/* Ray storing routine when RelaxedEnumeration is dd_TRUE.
weaklyfeasible is true iff it is feasible with
the strict_inequality conditions deleted. */
{
dd_RayPtr RR;
dd_rowrange i,k,fii=cone->m+1;
dd_colrange j;
mytype temp;
dd_init(temp);
RR=cone->LastRay;
*feasible = dd_TRUE;
*weaklyfeasible = dd_TRUE;
set_initialize(&(RR->ZeroSet),cone->m);
for (j = 0; j < cone->d; j++){
dd_set(RR->Ray[j],p[j]);
}
for (i = 1; i <= cone->m; i++) {
k=cone->OrderVector[i];
dd_AValue(&temp, cone->d, cone->A, p, k);
if (dd_EqualToZero(temp)){
set_addelem(RR->ZeroSet, k);
if (cone->parent->EqualityIndex[k]==-1)
*feasible=dd_FALSE; /* strict inequality required */
}
/* if (temp < -zero){ */
if (dd_Negative(temp)){
*feasible = dd_FALSE;
if (fii>cone->m && cone->parent->EqualityIndex[k]>=0) {
fii=i; /* the first violating inequality index */
*weaklyfeasible=dd_FALSE;
}
}
}
RR->FirstInfeasIndex=fii;
RR->feasible = *feasible;
dd_clear(temp);
}
void dd_AddRay(dd_ConePtr cone, mytype *p)
{
dd_boolean feasible, weaklyfeasible;
dd_colrange j;
if (cone->FirstRay == NULL) {
cone->FirstRay = (dd_RayPtr) malloc(sizeof(dd_RayType));
cone->FirstRay->Ray = (mytype *) calloc(cone->d, sizeof(mytype));
for (j=0; jd; j++) dd_init(cone->FirstRay->Ray[j]);
dd_init(cone->FirstRay->ARay);
if (dd_debug)
fprintf(stderr,"Create the first ray pointer\n");
cone->LastRay = cone->FirstRay;
cone->ArtificialRay->Next = cone->FirstRay;
} else {
cone->LastRay->Next = (dd_RayPtr) malloc(sizeof(dd_RayType));
cone->LastRay->Next->Ray = (mytype *) calloc(cone->d, sizeof(mytype));
for (j=0; jd; j++) dd_init(cone->LastRay->Next->Ray[j]);
dd_init(cone->LastRay->Next->ARay);
if (dd_debug) fprintf(stderr,"Create a new ray pointer\n");
cone->LastRay = cone->LastRay->Next;
}
cone->LastRay->Next = NULL;
cone->RayCount++;
cone->TotalRayCount++;
if (dd_debug) {
if (cone->TotalRayCount % 100 == 0) {
fprintf(stderr,"*Rays (Total, Currently Active, Feasible) =%8ld%8ld%8ld\n",
cone->TotalRayCount, cone->RayCount, cone->FeasibleRayCount);
}
}
if (cone->parent->RelaxedEnumeration){
dd_StoreRay2(cone, p, &feasible, &weaklyfeasible);
if (weaklyfeasible) (cone->WeaklyFeasibleRayCount)++;
} else {
dd_StoreRay1(cone, p, &feasible);
if (feasible) (cone->WeaklyFeasibleRayCount)++;
/* weaklyfeasible is equiv. to feasible in this case. */
}
if (!feasible) return;
else {
(cone->FeasibleRayCount)++;
}
}
void dd_AddArtificialRay(dd_ConePtr cone)
{
dd_Arow zerovector;
dd_colrange j,d1;
dd_boolean feasible;
if (cone->d<=0) d1=1; else d1=cone->d;
dd_InitializeArow(d1, &zerovector);
if (cone->ArtificialRay != NULL) {
fprintf(stderr,"Warning !!! FirstRay in not nil. Illegal Call\n");
free(zerovector); /* 086 */
return;
}
cone->ArtificialRay = (dd_RayPtr) malloc(sizeof(dd_RayType));
cone->ArtificialRay->Ray = (mytype *) calloc(d1, sizeof(mytype));
for (j=0; jArtificialRay->Ray[j]);
dd_init(cone->ArtificialRay->ARay);
if (dd_debug) fprintf(stderr,"Create the artificial ray pointer\n");
cone->LastRay=cone->ArtificialRay;
dd_StoreRay1(cone, zerovector, &feasible);
/* This stores a vector to the record pointed by cone->LastRay */
cone->ArtificialRay->Next = NULL;
for (j = 0; j < d1; j++){
dd_clear(zerovector[j]);
}
free(zerovector); /* 086 */
}
void dd_ConditionalAddEdge(dd_ConePtr cone,
dd_RayPtr Ray1, dd_RayPtr Ray2, dd_RayPtr ValidFirstRay)
{
long it,it_row,fii1,fii2,fmin,fmax;
dd_boolean adjacent,lastchance;
dd_RayPtr TempRay,Rmin,Rmax;
dd_AdjacencyType *NewEdge;
dd_boolean localdebug=dd_FALSE;
dd_rowset ZSmin, ZSmax;
static dd_rowset Face, Face1;
static dd_rowrange last_m=0;
if (last_m!=cone->m) {
if (last_m>0){
set_free(Face); set_free(Face1);
}
set_initialize(&Face, cone->m);
set_initialize(&Face1, cone->m);
last_m=cone->m;
}
fii1=Ray1->FirstInfeasIndex;
fii2=Ray2->FirstInfeasIndex;
if (fii1ZeroSet;
ZSmax = Rmax->ZeroSet;
if (localdebug) {
fprintf(stderr,"dd_ConditionalAddEdge: FMIN = %ld (row%ld) FMAX=%ld\n",
fmin, cone->OrderVector[fmin], fmax);
}
if (fmin==fmax){
if (localdebug) fprintf(stderr,"dd_ConditionalAddEdge: equal FII value-> No edge added\n");
}
else if (set_member(cone->OrderVector[fmin],ZSmax)){
if (localdebug) fprintf(stderr,"dd_ConditionalAddEdge: No strong separation -> No edge added\n");
}
else { /* the pair will be separated at the iteration fmin */
lastchance=dd_TRUE;
/* flag to check it will be the last chance to store the edge candidate */
set_int(Face1, ZSmax, ZSmin);
(cone->count_int)++;
if (localdebug){
fprintf(stderr,"Face: ");
for (it=1; it<=cone->m; it++) {
it_row=cone->OrderVector[it];
if (set_member(it_row, Face1)) fprintf(stderr,"%ld ",it_row);
}
fprintf(stderr,"\n");
}
for (it=cone->Iteration+1; it < fmin && lastchance; it++){
it_row=cone->OrderVector[it];
if (cone->parent->EqualityIndex[it_row]>=0 && set_member(it_row, Face1)){
lastchance=dd_FALSE;
(cone->count_int_bad)++;
if (localdebug){
fprintf(stderr,"There will be another chance iteration %ld (row %ld) to store the pair\n", it, it_row);
}
}
}
if (lastchance){
adjacent = dd_TRUE;
(cone->count_int_good)++;
/* adjacent checking */
set_int(Face, Face1, cone->AddedHalfspaces);
if (localdebug){
fprintf(stderr,"Check adjacency\n");
fprintf(stderr,"AddedHalfspaces: "); set_fwrite(stderr,cone->AddedHalfspaces);
fprintf(stderr,"Face: ");
for (it=1; it<=cone->m; it++) {
it_row=cone->OrderVector[it];
if (set_member(it_row, Face)) fprintf(stderr,"%ld ",it_row);
}
fprintf(stderr,"\n");
}
if (set_card(Face)< cone->d - 2) {
adjacent = dd_FALSE;
}
else if (cone->parent->NondegAssumed) {
adjacent = dd_TRUE;
}
else{
TempRay = ValidFirstRay; /* the first ray for adjacency checking */
while (TempRay != NULL && adjacent) {
if (TempRay != Ray1 && TempRay != Ray2) {
set_int(Face1, TempRay->ZeroSet, cone->AddedHalfspaces);
if (set_subset(Face, Face1)) {
if (localdebug) set_fwrite(stderr,Face1);
adjacent = dd_FALSE;
}
}
TempRay = TempRay->Next;
}
}
if (adjacent){
if (localdebug) fprintf(stderr,"The pair is adjacent and the pair must be stored for iteration %ld (row%ld)\n",
fmin, cone->OrderVector[fmin]);
NewEdge=(dd_AdjacencyPtr) malloc(sizeof *NewEdge);
NewEdge->Ray1=Rmax; /* save the one remains in iteration fmin in the first */
NewEdge->Ray2=Rmin; /* save the one deleted in iteration fmin in the second */
NewEdge->Next=NULL;
(cone->EdgeCount)++;
(cone->TotalEdgeCount)++;
if (cone->Edges[fmin]==NULL){
cone->Edges[fmin]=NewEdge;
if (localdebug) fprintf(stderr,"Create a new edge list of %ld\n", fmin);
}else{
NewEdge->Next=cone->Edges[fmin];
cone->Edges[fmin]=NewEdge;
}
}
}
}
}
void dd_CreateInitialEdges(dd_ConePtr cone)
{
dd_RayPtr Ptr1, Ptr2;
dd_rowrange fii1,fii2;
long count=0;
dd_boolean adj,localdebug=dd_FALSE;
cone->Iteration=cone->d; /* CHECK */
if (cone->FirstRay ==NULL || cone->LastRay==NULL){
/* fprintf(stderr,"Warning: dd_ CreateInitialEdges called with NULL pointer(s)\n"); */
goto _L99;
}
Ptr1=cone->FirstRay;
while(Ptr1!=cone->LastRay && Ptr1!=NULL){
fii1=Ptr1->FirstInfeasIndex;
Ptr2=Ptr1->Next;
while(Ptr2!=NULL){
fii2=Ptr2->FirstInfeasIndex;
count++;
if (localdebug) fprintf(stderr,"dd_ CreateInitialEdges: edge %ld \n",count);
dd_CheckAdjacency(cone, &Ptr1, &Ptr2, &adj);
if (fii1!=fii2 && adj)
dd_ConditionalAddEdge(cone, Ptr1, Ptr2, cone->FirstRay);
Ptr2=Ptr2->Next;
}
Ptr1=Ptr1->Next;
}
_L99:;
}
void dd_UpdateEdges(dd_ConePtr cone, dd_RayPtr RRbegin, dd_RayPtr RRend)
/* This procedure must be called after the ray list is sorted
by dd_EvaluateARay2 so that FirstInfeasIndex's are monotonically
increasing.
*/
{
dd_RayPtr Ptr1, Ptr2begin, Ptr2;
dd_rowrange fii1;
dd_boolean ptr2found,quit,localdebug=dd_FALSE;
long count=0,pos1, pos2;
float workleft,prevworkleft=110.0,totalpairs;
totalpairs=(cone->ZeroRayCount-1.0)*(cone->ZeroRayCount-2.0)+1.0;
Ptr2begin = NULL;
if (RRbegin ==NULL || RRend==NULL){
if (1) fprintf(stderr,"Warning: dd_UpdateEdges called with NULL pointer(s)\n");
goto _L99;
}
Ptr1=RRbegin;
pos1=1;
do{
ptr2found=dd_FALSE;
quit=dd_FALSE;
fii1=Ptr1->FirstInfeasIndex;
pos2=2;
for (Ptr2=Ptr1->Next; !ptr2found && !quit; Ptr2=Ptr2->Next,pos2++){
if (Ptr2->FirstInfeasIndex > fii1){
Ptr2begin=Ptr2;
ptr2found=dd_TRUE;
}
else if (Ptr2==RRend) quit=dd_TRUE;
}
if (ptr2found){
quit=dd_FALSE;
for (Ptr2=Ptr2begin; !quit ; Ptr2=Ptr2->Next){
count++;
if (localdebug) fprintf(stderr,"dd_UpdateEdges: edge %ld \n",count);
dd_ConditionalAddEdge(cone, Ptr1,Ptr2,RRbegin);
if (Ptr2==RRend || Ptr2->Next==NULL) quit=dd_TRUE;
}
}
Ptr1=Ptr1->Next;
pos1++;
workleft = 100.0 * (cone->ZeroRayCount-pos1) * (cone->ZeroRayCount - pos1-1.0) / totalpairs;
if (cone->ZeroRayCount>=500 && dd_debug && pos1%10 ==0 && prevworkleft-workleft>=10 ) {
fprintf(stderr,"*Work of iteration %5ld(/%ld): %4ld/%4ld => %4.1f%% left\n",
cone->Iteration, cone->m, pos1, cone->ZeroRayCount, workleft);
prevworkleft=workleft;
}
}while(Ptr1!=RRend && Ptr1!=NULL);
_L99:;
}
void dd_FreeDDMemory0(dd_ConePtr cone)
{
dd_RayPtr Ptr, PrevPtr;
long count;
dd_colrange j;
dd_boolean localdebug=dd_FALSE;
/* THIS SHOULD BE REWRITTEN carefully */
PrevPtr=cone->ArtificialRay;
if (PrevPtr!=NULL){
count=0;
for (Ptr=cone->ArtificialRay->Next; Ptr!=NULL; Ptr=Ptr->Next){
/* Added Marc Pfetsch 2/19/01 */
for (j=0;j < cone->d;j++)
dd_clear(PrevPtr->Ray[j]);
dd_clear(PrevPtr->ARay);
free(PrevPtr->Ray);
free(PrevPtr->ZeroSet);
free(PrevPtr);
count++;
PrevPtr=Ptr;
};
cone->FirstRay=NULL;
/* Added Marc Pfetsch 010219 */
for (j=0;j < cone->d;j++)
dd_clear(cone->LastRay->Ray[j]);
dd_clear(cone->LastRay->ARay);
free(cone->LastRay->Ray);
cone->LastRay->Ray = NULL;
set_free(cone->LastRay->ZeroSet);
cone->LastRay->ZeroSet = NULL;
free(cone->LastRay);
cone->LastRay = NULL;
cone->ArtificialRay=NULL;
if (localdebug) fprintf(stderr,"%ld ray storage spaces freed\n",count);
}
/* must add (by Sato) */
free(cone->Edges);
set_free(cone->GroundSet);
set_free(cone->EqualitySet);
set_free(cone->NonequalitySet);
set_free(cone->AddedHalfspaces);
set_free(cone->WeaklyAddedHalfspaces);
set_free(cone->InitialHalfspaces);
free(cone->InitialRayIndex);
free(cone->OrderVector);
free(cone->newcol);
/* Fixed by Shawn Rusaw. Originally it was cone->d instead of cone->d_alloc */
dd_FreeBmatrix(cone->d_alloc,cone->B);
dd_FreeBmatrix(cone->d_alloc,cone->Bsave);
/* Fixed by Marc Pfetsch 010219*/
dd_FreeAmatrix(cone->m_alloc,cone->d_alloc,cone->A);
cone->A = NULL;
free(cone);
}
void dd_FreeDDMemory(dd_PolyhedraPtr poly)
{
dd_FreeDDMemory0(poly->child);
poly->child=NULL;
}
void dd_FreePolyhedra(dd_PolyhedraPtr poly)
{
dd_bigrange i;
if ((poly)->child != NULL) dd_FreeDDMemory(poly);
dd_FreeAmatrix((poly)->m_alloc,poly->d_alloc, poly->A);
dd_FreeArow((poly)->d_alloc,(poly)->c);
free((poly)->EqualityIndex);
if (poly->AincGenerated){
for (i=1; i<=poly->m1; i++){
set_free(poly->Ainc[i-1]);
}
free(poly->Ainc);
set_free(poly->Ared);
set_free(poly->Adom);
poly->Ainc=NULL;
}
free(poly);
}
void dd_Normalize(dd_colrange d_size, mytype *V)
{
long j;
mytype temp,min;
dd_boolean nonzerofound=dd_FALSE;
if (d_size>0){
dd_init(min); dd_init(temp);
dd_abs(min,V[0]); /* set the minmizer to 0 */
if (dd_Positive(min)) nonzerofound=dd_TRUE;
for (j = 1; j < d_size; j++) {
dd_abs(temp,V[j]);
if (dd_Positive(temp)){
if (!nonzerofound || dd_Smaller(temp,min)){
nonzerofound=dd_TRUE;
dd_set(min, temp);
}
}
}
if (dd_Positive(min)){
for (j = 0; j < d_size; j++) dd_div(V[j], V[j], min);
}
dd_clear(min); dd_clear(temp);
}
}
void dd_ZeroIndexSet(dd_rowrange m_size, dd_colrange d_size, dd_Amatrix A, mytype *x, dd_rowset ZS)
{
dd_rowrange i;
mytype temp;
/* Changed by Marc Pfetsch 010219 */
dd_init(temp);
set_emptyset(ZS);
for (i = 1; i <= m_size; i++) {
dd_AValue(&temp, d_size, A, x, i);
if (dd_EqualToZero(temp)) set_addelem(ZS, i);
}
/* Changed by Marc Pfetsch 010219 */
dd_clear(temp);
}
void dd_CopyBmatrix(dd_colrange d_size, dd_Bmatrix T, dd_Bmatrix TCOPY)
{
dd_rowrange i;
dd_colrange j;
for (i=0; i < d_size; i++) {
for (j=0; j < d_size; j++) {
dd_set(TCOPY[i][j],T[i][j]);
}
}
}
void dd_CopyArow(mytype *acopy, mytype *a, dd_colrange d)
{
dd_colrange j;
for (j = 0; j < d; j++) {
dd_set(acopy[j],a[j]);
}
}
void dd_CopyNormalizedArow(mytype *acopy, mytype *a, dd_colrange d)
{
dd_CopyArow(acopy, a, d);
dd_Normalize(d,acopy);
}
void dd_CopyAmatrix(mytype **Acopy, mytype **A, dd_rowrange m, dd_colrange d)
{
dd_rowrange i;
for (i = 0; i< m; i++) {
dd_CopyArow(Acopy[i],A[i],d);
}
}
void dd_CopyNormalizedAmatrix(mytype **Acopy, mytype **A, dd_rowrange m, dd_colrange d)
{
dd_rowrange i;
for (i = 0; i< m; i++) {
dd_CopyNormalizedArow(Acopy[i],A[i],d);
}
}
void dd_PermuteCopyAmatrix(mytype **Acopy, mytype **A, dd_rowrange m, dd_colrange d, dd_rowindex roworder)
{
dd_rowrange i;
for (i = 1; i<= m; i++) {
dd_CopyArow(Acopy[i-1],A[roworder[i]-1],d);
}
}
void dd_PermutePartialCopyAmatrix(mytype **Acopy, mytype **A, dd_rowrange m, dd_colrange d, dd_rowindex roworder,dd_rowrange p, dd_rowrange q)
{
/* copy the rows of A whose roworder is positive. roworder[i] is the row index of the copied row. */
dd_rowrange i;
for (i = 1; i<= m; i++) {
if (roworder[i]>0) dd_CopyArow(Acopy[roworder[i]-1],A[i-1],d);
}
}
void dd_InitializeArow(dd_colrange d,dd_Arow *a)
{
dd_colrange j;
if (d>0) *a=(mytype*) calloc(d,sizeof(mytype));
for (j = 0; j < d; j++) {
dd_init((*a)[j]);
}
}
void dd_InitializeAmatrix(dd_rowrange m,dd_colrange d,dd_Amatrix *A)
{
dd_rowrange i;
if (m>0) (*A)=(mytype**) calloc(m,sizeof(mytype*));
for (i = 0; i < m; i++) {
dd_InitializeArow(d,&((*A)[i]));
}
}
void dd_FreeAmatrix(dd_rowrange m,dd_colrange d,dd_Amatrix A)
{
dd_rowrange i;
dd_colrange j;
for (i = 0; i < m; i++) {
for (j = 0; j < d; j++) {
dd_clear(A[i][j]);
}
}
if (A!=NULL) {
for (i = 0; i < m; i++) {
free(A[i]);
}
free(A);
}
}
void dd_FreeArow(dd_colrange d, dd_Arow a)
{
dd_colrange j;
for (j = 0; j < d; j++) {
dd_clear(a[j]);
}
free(a);
}
void dd_InitializeBmatrix(dd_colrange d,dd_Bmatrix *B)
{
dd_colrange i,j;
(*B)=(mytype**) calloc(d,sizeof(mytype*));
for (j = 0; j < d; j++) {
(*B)[j]=(mytype*) calloc(d,sizeof(mytype));
}
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) {
dd_init((*B)[i][j]);
}
}
}
void dd_FreeBmatrix(dd_colrange d,dd_Bmatrix B)
{
dd_colrange i,j;
for (i = 0; i < d; i++) {
for (j = 0; j < d; j++) {
dd_clear(B[i][j]);
}
}
if (B!=NULL) {
for (j = 0; j < d; j++) {
free(B[j]);
}
free(B);
}
}
dd_SetFamilyPtr dd_CreateSetFamily(dd_bigrange fsize, dd_bigrange ssize)
{
dd_SetFamilyPtr F;
dd_bigrange i,f0,f1,s0,s1;
if (fsize<=0) {
f0=0; f1=1;
/* if fsize<=0, the fsize is set to zero and the created size is one */
} else {
f0=fsize; f1=fsize;
}
if (ssize<=0) {
s0=0; s1=1;
/* if ssize<=0, the ssize is set to zero and the created size is one */
} else {
s0=ssize; s1=ssize;
}
F=(dd_SetFamilyPtr) malloc (sizeof(dd_SetFamilyType));
F->set=(set_type*) calloc(f1,sizeof(set_type));
for (i=0; iset[i]), s1);
}
F->famsize=f0;
F->setsize=s0;
return F;
}
void dd_FreeSetFamily(dd_SetFamilyPtr F)
{
dd_bigrange i,f1;
if (F!=NULL){
if (F->famsize<=0) f1=1; else f1=F->famsize;
/* the smallest created size is one */
for (i=0; iset[i]);
}
free(F->set);
free(F);
}
}
dd_MatrixPtr dd_CreateMatrix(dd_rowrange m_size,dd_colrange d_size)
{
dd_MatrixPtr M;
dd_rowrange m0,m1;
dd_colrange d0,d1;
if (m_size<=0){
m0=0; m1=1;
/* if m_size <=0, the number of rows is set to zero, the actual size is 1 */
} else {
m0=m_size; m1=m_size;
}
if (d_size<=0){
d0=0; d1=1;
/* if d_size <=0, the number of cols is set to zero, the actual size is 1 */
} else {
d0=d_size; d1=d_size;
}
M=(dd_MatrixPtr) malloc (sizeof(dd_MatrixType));
dd_InitializeAmatrix(m1,d1,&(M->matrix));
dd_InitializeArow(d1,&(M->rowvec));
M->rowsize=m0;
set_initialize(&(M->linset), m1);
M->colsize=d0;
M->objective=dd_LPnone;
M->numbtype=dd_Unknown;
M->representation=dd_Unspecified;
return M;
}
void dd_FreeMatrix(dd_MatrixPtr M)
{
dd_rowrange m1;
dd_colrange d1;
if (M!=NULL) {
if (M->rowsize<=0) m1=1; else m1=M->rowsize;
if (M->colsize<=0) d1=1; else d1=M->colsize;
if (M!=NULL) {
dd_FreeAmatrix(m1,d1,M->matrix);
dd_FreeArow(d1,M->rowvec);
set_free(M->linset);
free(M);
}
}
}
void dd_SetToIdentity(dd_colrange d_size, dd_Bmatrix T)
{
dd_colrange j1, j2;
for (j1 = 1; j1 <= d_size; j1++) {
for (j2 = 1; j2 <= d_size; j2++) {
if (j1 == j2)
dd_set(T[j1 - 1][j2 - 1],dd_one);
else
dd_set(T[j1 - 1][j2 - 1],dd_purezero);
}
}
}
void dd_ColumnReduce(dd_ConePtr cone)
{
dd_colrange j,j1=0;
dd_rowrange i;
dd_boolean localdebug=dd_FALSE;
for (j=1;j<=cone->d;j++) {
if (cone->InitialRayIndex[j]>0){
j1=j1+1;
if (j1m; i++) dd_set(cone->A[i-1][j1-1],cone->A[i-1][j-1]);
cone->newcol[j]=j1;
if (localdebug){
fprintf(stderr,"shifting the column %ld to column %ld\n", j, j1);
}
/* shifting forward */
}
} else {
cone->newcol[j]=0;
if (localdebug) {
fprintf(stderr,"a generator (or an equation) of the linearity space: ");
for (i=1; i<=cone->d; i++) dd_WriteNumber(stderr, cone->B[i-1][j-1]);
fprintf(stderr,"\n");
}
}
}
cone->d=j1; /* update the dimension. cone->d_orig remembers the old. */
dd_CopyBmatrix(cone->d_orig, cone->B, cone->Bsave);
/* save the dual basis inverse as Bsave. This matrix contains the linearity space generators. */
cone->ColReduced=dd_TRUE;
}
long dd_MatrixRank(dd_MatrixPtr M, dd_rowset ignoredrows, dd_colset ignoredcols, dd_rowset *rowbasis, dd_colset *colbasis)
{
dd_boolean stop, chosen, localdebug=dd_debug;
dd_rowset NopivotRow,PriorityRow;
dd_colset ColSelected;
dd_Bmatrix B;
dd_rowindex roworder;
dd_rowrange r;
dd_colrange s;
long rank;
rank = 0;
stop = dd_FALSE;
set_initialize(&ColSelected, M->colsize);
set_initialize(&NopivotRow, M->rowsize);
set_initialize(rowbasis, M->rowsize);
set_initialize(colbasis, M->colsize);
set_initialize(&PriorityRow, M->rowsize);
set_copy(NopivotRow,ignoredrows);
set_copy(ColSelected,ignoredcols);
dd_InitializeBmatrix(M->colsize, &B);
dd_SetToIdentity(M->colsize, B);
roworder=(long *)calloc(M->rowsize+1,sizeof(long));
for (r=0; rrowsize; r++){roworder[r+1]=r+1;
}
do { /* Find a set of rows for a basis */
dd_SelectPivot2(M->rowsize, M->colsize,M->matrix,B,dd_MinIndex,roworder,
PriorityRow,M->rowsize, NopivotRow, ColSelected, &r, &s, &chosen);
if (dd_debug && chosen)
fprintf(stderr,"Procedure dd_MatrixRank: pivot on (r,s) =(%ld, %ld).\n", r, s);
if (chosen) {
set_addelem(NopivotRow, r);
set_addelem(*rowbasis, r);
set_addelem(ColSelected, s);
set_addelem(*colbasis, s);
rank++;
dd_GaussianColumnPivot(M->rowsize, M->colsize, M->matrix, B, r, s);
if (localdebug) dd_WriteBmatrix(stderr,M->colsize,B);
} else {
stop=dd_TRUE;
}
if (rank==M->colsize) stop = dd_TRUE;
} while (!stop);
dd_FreeBmatrix(M->colsize,B);
free(roworder);
set_free(ColSelected);
set_free(NopivotRow);
set_free(PriorityRow);
return rank;
}
void dd_FindBasis(dd_ConePtr cone, long *rank)
{
dd_boolean stop, chosen, localdebug=dd_debug;
dd_rowset NopivotRow;
dd_colset ColSelected;
dd_rowrange r;
dd_colrange j,s;
*rank = 0;
stop = dd_FALSE;
for (j=0;j<=cone->d;j++) cone->InitialRayIndex[j]=0;
set_emptyset(cone->InitialHalfspaces);
set_initialize(&ColSelected, cone->d);
set_initialize(&NopivotRow, cone->m);
set_copy(NopivotRow,cone->NonequalitySet);
dd_SetToIdentity(cone->d, cone->B);
do { /* Find a set of rows for a basis */
dd_SelectPivot2(cone->m, cone->d,cone->A,cone->B,cone->HalfspaceOrder,cone->OrderVector,
cone->EqualitySet,cone->m, NopivotRow, ColSelected, &r, &s, &chosen);
if (dd_debug && chosen)
fprintf(stderr,"Procedure dd_FindBasis: pivot on (r,s) =(%ld, %ld).\n", r, s);
if (chosen) {
set_addelem(cone->InitialHalfspaces, r);
set_addelem(NopivotRow, r);
set_addelem(ColSelected, s);
cone->InitialRayIndex[s]=r; /* cone->InitialRayIndex[s] stores the corr. row index */
(*rank)++;
dd_GaussianColumnPivot(cone->m, cone->d, cone->A, cone->B, r, s);
if (localdebug) dd_WriteBmatrix(stderr,cone->d,cone->B);
} else {
stop=dd_TRUE;
}
if (*rank==cone->d) stop = dd_TRUE;
} while (!stop);
set_free(ColSelected);
set_free(NopivotRow);
}
void dd_FindInitialRays(dd_ConePtr cone, dd_boolean *found)
{
dd_rowset CandidateRows;
dd_rowrange i;
long rank;
dd_RowOrderType roworder_save=dd_LexMin;
*found = dd_FALSE;
set_initialize(&CandidateRows, cone->m);
if (cone->parent->InitBasisAtBottom==dd_TRUE) {
roworder_save=cone->HalfspaceOrder;
cone->HalfspaceOrder=dd_MaxIndex;
cone->PreOrderedRun=dd_FALSE;
}
else cone->PreOrderedRun=dd_TRUE;
if (dd_debug) dd_WriteBmatrix(stderr, cone->d, cone->B);
for (i = 1; i <= cone->m; i++)
if (!set_member(i,cone->NonequalitySet)) set_addelem(CandidateRows, i);
/*all rows not in NonequalitySet are candidates for initial cone*/
dd_FindBasis(cone, &rank);
if (dd_debug) dd_WriteBmatrix(stderr, cone->d, cone->B);
if (dd_debug) fprintf(stderr,"dd_FindInitialRays: rank of Amatrix = %ld\n", rank);
cone->LinearityDim=cone->d - rank;
if (dd_debug) fprintf(stderr,"Linearity Dimension = %ld\n", cone->LinearityDim);
if (cone->LinearityDim > 0) {
dd_ColumnReduce(cone);
dd_FindBasis(cone, &rank);
}
if (!set_subset(cone->EqualitySet,cone->InitialHalfspaces)) {
if (dd_debug) {
fprintf(stderr,"Equality set is dependent. Equality Set and an initial basis:\n");
set_fwrite(stderr,cone->EqualitySet);
set_fwrite(stderr,cone->InitialHalfspaces);
};
}
*found = dd_TRUE;
set_free(CandidateRows);
if (cone->parent->InitBasisAtBottom==dd_TRUE) {
cone->HalfspaceOrder=roworder_save;
}
if (cone->HalfspaceOrder==dd_MaxCutoff||
cone->HalfspaceOrder==dd_MinCutoff||
cone->HalfspaceOrder==dd_MixCutoff){
cone->PreOrderedRun=dd_FALSE;
} else cone->PreOrderedRun=dd_TRUE;
}
void dd_CheckEquality(dd_colrange d_size, dd_RayPtr*RP1, dd_RayPtr*RP2, dd_boolean *equal)
{
long j;
if (dd_debug)
fprintf(stderr,"Check equality of two rays\n");
*equal = dd_TRUE;
j = 1;
while (j <= d_size && *equal) {
if (!dd_Equal((*RP1)->Ray[j - 1],(*RP2)->Ray[j - 1]))
*equal = dd_FALSE;
j++;
}
if (*equal)
fprintf(stderr,"Equal records found !!!!\n");
}
void dd_CreateNewRay(dd_ConePtr cone,
dd_RayPtr Ptr1, dd_RayPtr Ptr2, dd_rowrange ii)
{
/*Create a new ray by taking a linear combination of two rays*/
dd_colrange j;
mytype a1, a2, v1, v2;
static dd_Arow NewRay;
static dd_colrange last_d=0;
dd_boolean localdebug=dd_debug;
dd_init(a1); dd_init(a2); dd_init(v1); dd_init(v2);
if (last_d!=cone->d){
if (last_d>0) {
for (j=0; jd,sizeof(mytype));
for (j=0; jd; j++) dd_init(NewRay[j]);
last_d=cone->d;
}
dd_AValue(&a1, cone->d, cone->A, Ptr1->Ray, ii);
dd_AValue(&a2, cone->d, cone->A, Ptr2->Ray, ii);
if (localdebug) {
fprintf(stderr,"CreatNewRay: Ray1 ="); dd_WriteArow(stderr, Ptr1->Ray, cone->d);
fprintf(stderr,"CreatNewRay: Ray2 ="); dd_WriteArow(stderr, Ptr2->Ray, cone->d);
}
dd_abs(v1,a1);
dd_abs(v2,a2);
if (localdebug){
fprintf(stderr,"dd_AValue1 and ABS"); dd_WriteNumber(stderr,a1); dd_WriteNumber(stderr,v1); fprintf(stderr,"\n");
fprintf(stderr,"dd_AValue2 and ABS"); dd_WriteNumber(stderr,a2); dd_WriteNumber(stderr,v2); fprintf(stderr,"\n");
}
for (j = 0; j < cone->d; j++){
dd_LinearComb(NewRay[j], Ptr1->Ray[j],v2,Ptr2->Ray[j],v1);
}
if (localdebug) {
fprintf(stderr,"CreatNewRay: New ray ="); dd_WriteArow(stderr, NewRay, cone->d);
}
dd_Normalize(cone->d, NewRay);
if (localdebug) {
fprintf(stderr,"CreatNewRay: dd_Normalized ray ="); dd_WriteArow(stderr, NewRay, cone->d);
}
dd_AddRay(cone, NewRay);
dd_clear(a1); dd_clear(a2); dd_clear(v1); dd_clear(v2);
}
void dd_EvaluateARay1(dd_rowrange i, dd_ConePtr cone)
/* Evaluate the ith component of the vector A x RD.Ray
and rearrange the linked list so that
the infeasible rays with respect to i will be
placed consecutively from First
*/
{
dd_colrange j;
mytype temp,tnext;
dd_RayPtr Ptr, PrevPtr, TempPtr;
dd_init(temp); dd_init(tnext);
Ptr = cone->FirstRay;
PrevPtr = cone->ArtificialRay;
if (PrevPtr->Next != Ptr) {
fprintf(stderr,"Error. Artificial Ray does not point to FirstRay!!!\n");
}
while (Ptr != NULL) {
dd_set(temp,dd_purezero);
for (j = 0; j < cone->d; j++){
dd_mul(tnext,cone->A[i - 1][j],Ptr->Ray[j]);
dd_add(temp,temp,tnext);
}
dd_set(Ptr->ARay,temp);
/* if ( temp <= -zero && Ptr != cone->FirstRay) {*/
if ( dd_Negative(temp) && Ptr != cone->FirstRay) {
/* fprintf(stderr,"Moving an infeasible record w.r.t. %ld to FirstRay\n",i); */
if (Ptr==cone->LastRay) cone->LastRay=PrevPtr;
TempPtr=Ptr;
Ptr = Ptr->Next;
PrevPtr->Next = Ptr;
cone->ArtificialRay->Next = TempPtr;
TempPtr->Next = cone->FirstRay;
cone->FirstRay = TempPtr;
}
else {
PrevPtr = Ptr;
Ptr = Ptr->Next;
}
}
dd_clear(temp); dd_clear(tnext);
}
void dd_EvaluateARay2(dd_rowrange i, dd_ConePtr cone)
/* Evaluate the ith component of the vector A x RD.Ray
and rearrange the linked list so that
the infeasible rays with respect to i will be
placed consecutively from First. Also for all feasible rays,
"positive" rays and "zero" rays will be placed consecutively.
*/
{
dd_colrange j;
mytype temp,tnext;
dd_RayPtr Ptr, NextPtr;
dd_boolean zerofound=dd_FALSE,negfound=dd_FALSE,posfound=dd_FALSE;
if (cone==NULL || cone->TotalRayCount<=0) goto _L99;
dd_init(temp); dd_init(tnext);
cone->PosHead=NULL;cone->ZeroHead=NULL;cone->NegHead=NULL;
cone->PosLast=NULL;cone->ZeroLast=NULL;cone->NegLast=NULL;
Ptr = cone->FirstRay;
while (Ptr != NULL) {
NextPtr=Ptr->Next; /* remember the Next record */
Ptr->Next=NULL; /* then clear the Next pointer */
dd_set(temp,dd_purezero);
for (j = 0; j < cone->d; j++){
dd_mul(tnext,cone->A[i - 1][j],Ptr->Ray[j]);
dd_add(temp,temp,tnext);
}
dd_set(Ptr->ARay,temp);
/* if ( temp < -zero) {*/
if ( dd_Negative(temp)) {
if (!negfound){
negfound=dd_TRUE;
cone->NegHead=Ptr;
cone->NegLast=Ptr;
}
else{
Ptr->Next=cone->NegHead;
cone->NegHead=Ptr;
}
}
/* else if (temp > zero){*/
else if (dd_Positive(temp)){
if (!posfound){
posfound=dd_TRUE;
cone->PosHead=Ptr;
cone->PosLast=Ptr;
}
else{
Ptr->Next=cone->PosHead;
cone->PosHead=Ptr;
}
}
else {
if (!zerofound){
zerofound=dd_TRUE;
cone->ZeroHead=Ptr;
cone->ZeroLast=Ptr;
}
else{
Ptr->Next=cone->ZeroHead;
cone->ZeroHead=Ptr;
}
}
Ptr=NextPtr;
}
/* joining three neg, pos and zero lists */
if (negfound){ /* -list nonempty */
cone->FirstRay=cone->NegHead;
if (posfound){ /* -list & +list nonempty */
cone->NegLast->Next=cone->PosHead;
if (zerofound){ /* -list, +list, 0list all nonempty */
cone->PosLast->Next=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
else{ /* -list, +list nonempty but 0list empty */
cone->LastRay=cone->PosLast;
}
}
else{ /* -list nonempty & +list empty */
if (zerofound){ /* -list,0list nonempty & +list empty */
cone->NegLast->Next=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
else { /* -list nonempty & +list,0list empty */
cone->LastRay=cone->NegLast;
}
}
}
else if (posfound){ /* -list empty & +list nonempty */
cone->FirstRay=cone->PosHead;
if (zerofound){ /* -list empty & +list,0list nonempty */
cone->PosLast->Next=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
else{ /* -list,0list empty & +list nonempty */
cone->LastRay=cone->PosLast;
}
}
else{ /* -list,+list empty & 0list nonempty */
cone->FirstRay=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
cone->ArtificialRay->Next=cone->FirstRay;
cone->LastRay->Next=NULL;
dd_clear(temp); dd_clear(tnext);
_L99:;
}
void dd_DeleteNegativeRays(dd_ConePtr cone)
/* Eliminate the infeasible rays with respect to i which
are supposed to be consecutive from the head of the dd_Ray list,
and sort the zero list assumed to be consecutive at the
end of the list.
*/
{
dd_rowrange fii,fiitest;
mytype temp;
dd_RayPtr Ptr, PrevPtr,NextPtr,ZeroPtr1,ZeroPtr0;
dd_boolean found, completed, zerofound=dd_FALSE,negfound=dd_FALSE,posfound=dd_FALSE;
dd_boolean localdebug=dd_FALSE;
dd_init(temp);
cone->PosHead=NULL;cone->ZeroHead=NULL;cone->NegHead=NULL;
cone->PosLast=NULL;cone->ZeroLast=NULL;cone->NegLast=NULL;
/* Delete the infeasible rays */
PrevPtr= cone->ArtificialRay;
Ptr = cone->FirstRay;
if (PrevPtr->Next != Ptr)
fprintf(stderr,"Error at dd_DeleteNegativeRays: ArtificialRay does not point the FirstRay.\n");
completed=dd_FALSE;
while (Ptr != NULL && !completed){
/* if ( (Ptr->ARay) < -zero ){ */
if ( dd_Negative(Ptr->ARay)){
dd_Eliminate(cone, &PrevPtr);
Ptr=PrevPtr->Next;
}
else{
completed=dd_TRUE;
}
}
/* Sort the zero rays */
Ptr = cone->FirstRay;
cone->ZeroRayCount=0;
while (Ptr != NULL) {
NextPtr=Ptr->Next; /* remember the Next record */
dd_set(temp,Ptr->ARay);
if (localdebug) {fprintf(stderr,"Ptr->ARay :"); dd_WriteNumber(stderr, temp);}
/* if ( temp < -zero) {*/
if ( dd_Negative(temp)) {
if (!negfound){
fprintf(stderr,"Error: An infeasible ray found after their removal\n");
negfound=dd_TRUE;
}
}
/* else if (temp > zero){*/
else if (dd_Positive(temp)){
if (!posfound){
posfound=dd_TRUE;
cone->PosHead=Ptr;
cone->PosLast=Ptr;
}
else{
cone->PosLast=Ptr;
}
}
else {
(cone->ZeroRayCount)++;
if (!zerofound){
zerofound=dd_TRUE;
cone->ZeroHead=Ptr;
cone->ZeroLast=Ptr;
cone->ZeroLast->Next=NULL;
}
else{/* Find a right position to store the record sorted w.r.t. FirstInfeasIndex */
fii=Ptr->FirstInfeasIndex;
found=dd_FALSE;
ZeroPtr1=NULL;
for (ZeroPtr0=cone->ZeroHead; !found && ZeroPtr0!=NULL ; ZeroPtr0=ZeroPtr0->Next){
fiitest=ZeroPtr0->FirstInfeasIndex;
if (fiitest >= fii){
found=dd_TRUE;
}
else ZeroPtr1=ZeroPtr0;
}
/* fprintf(stderr,"insert position found \n %d index %ld\n",found, fiitest); */
if (!found){ /* the new record must be stored at the end of list */
cone->ZeroLast->Next=Ptr;
cone->ZeroLast=Ptr;
cone->ZeroLast->Next=NULL;
}
else{
if (ZeroPtr1==NULL){ /* store the new one at the head, and update the head ptr */
/* fprintf(stderr,"Insert at the head\n"); */
Ptr->Next=cone->ZeroHead;
cone->ZeroHead=Ptr;
}
else{ /* store the new one inbetween ZeroPtr1 and 0 */
/* fprintf(stderr,"Insert inbetween\n"); */
Ptr->Next=ZeroPtr1->Next;
ZeroPtr1->Next=Ptr;
}
}
/*
Ptr->Next=cone->ZeroHead;
cone->ZeroHead=Ptr;
*/
}
}
Ptr=NextPtr;
}
/* joining the pos and zero lists */
if (posfound){ /* -list empty & +list nonempty */
cone->FirstRay=cone->PosHead;
if (zerofound){ /* +list,0list nonempty */
cone->PosLast->Next=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
else{ /* 0list empty & +list nonempty */
cone->LastRay=cone->PosLast;
}
}
else{ /* +list empty & 0list nonempty */
cone->FirstRay=cone->ZeroHead;
cone->LastRay=cone->ZeroLast;
}
cone->ArtificialRay->Next=cone->FirstRay;
cone->LastRay->Next=NULL;
dd_clear(temp);
}
void dd_FeasibilityIndices(long *fnum, long *infnum, dd_rowrange i, dd_ConePtr cone)
{
/*Evaluate the number of feasible rays and infeasible rays*/
/* w.r.t the hyperplane i*/
dd_colrange j;
mytype temp, tnext;
dd_RayPtr Ptr;
dd_init(temp); dd_init(tnext);
*fnum = 0;
*infnum = 0;
Ptr = cone->FirstRay;
while (Ptr != NULL) {
dd_set(temp,dd_purezero);
for (j = 0; j < cone->d; j++){
dd_mul(tnext, cone->A[i - 1][j],Ptr->Ray[j]);
dd_add(temp, temp, tnext);
}
if (dd_Nonnegative(temp))
(*fnum)++;
else
(*infnum)++;
Ptr = Ptr->Next;
}
dd_clear(temp); dd_clear(tnext);
}
dd_boolean dd_LexSmaller(mytype *v1, mytype *v2, long dmax)
{ /* dmax is the size of vectors v1,v2 */
dd_boolean determined, smaller;
dd_colrange j;
smaller = dd_FALSE;
determined = dd_FALSE;
j = 1;
do {
if (!dd_Equal(v1[j - 1],v2[j - 1])) { /* 086 */
if (dd_Smaller(v1[j - 1],v2[j - 1])) { /*086 */
smaller = dd_TRUE;
}
determined = dd_TRUE;
} else
j++;
} while (!(determined) && (j <= dmax));
return smaller;
}
dd_boolean dd_LexLarger(mytype *v1, mytype *v2, long dmax)
{
return dd_LexSmaller(v2, v1, dmax);
}
dd_boolean dd_LexEqual(mytype *v1, mytype *v2, long dmax)
{ /* dmax is the size of vectors v1,v2 */
dd_boolean determined, equal;
dd_colrange j;
equal = dd_TRUE;
determined = dd_FALSE;
j = 1;
do {
if (!dd_Equal(v1[j - 1],v2[j - 1])) { /* 093c */
equal = dd_FALSE;
determined = dd_TRUE;
} else {
j++;
}
} while (!(determined) && (j <= dmax));
return equal;
}
void dd_AddNewHalfspace1(dd_ConePtr cone, dd_rowrange hnew)
/* This procedure 1 must be used with PreorderedRun=dd_FALSE
This procedure is the most elementary implementation of
DD and can be used with any type of ordering, including
dynamic ordering of rows, e.g. MaxCutoff, MinCutoff.
The memory requirement is minimum because it does not
store any adjacency among the rays.
*/
{
dd_RayPtr RayPtr0,RayPtr1,RayPtr2,RayPtr2s,RayPtr3;
long pos1, pos2;
double prevprogress, progress;
mytype value1, value2;
dd_boolean adj, equal, completed;
dd_init(value1); dd_init(value2);
dd_EvaluateARay1(hnew, cone);
/*Check feasibility of rays w.r.t. hnew
and put all infeasible ones consecutively */
RayPtr0 = cone->ArtificialRay; /*Pointer pointing RayPrt1*/
RayPtr1 = cone->FirstRay; /*1st hnew-infeasible ray to scan and compare with feasible rays*/
dd_set(value1,cone->FirstRay->ARay);
if (dd_Nonnegative(value1)) {
if (cone->RayCount==cone->WeaklyFeasibleRayCount) cone->CompStatus=dd_AllFound;
goto _L99; /* Sicne there is no hnew-infeasible ray and nothing to do */
}
else {
RayPtr2s = RayPtr1->Next;/* RayPtr2s must point the first feasible ray */
pos2=1;
while (RayPtr2s!=NULL && dd_Negative(RayPtr2s->ARay)) {
RayPtr2s = RayPtr2s->Next;
pos2++;
}
}
if (RayPtr2s==NULL) {
cone->FirstRay=NULL;
cone->ArtificialRay->Next=cone->FirstRay;
cone->RayCount=0;
cone->CompStatus=dd_AllFound;
goto _L99; /* All rays are infeasible, and the computation must stop */
}
RayPtr2 = RayPtr2s; /*2nd feasible ray to scan and compare with 1st*/
RayPtr3 = cone->LastRay; /*Last feasible for scanning*/
prevprogress=-10.0;
pos1 = 1;
completed=dd_FALSE;
while ((RayPtr1 != RayPtr2s) && !completed) {
dd_set(value1,RayPtr1->ARay);
dd_set(value2,RayPtr2->ARay);
dd_CheckEquality(cone->d, &RayPtr1, &RayPtr2, &equal);
if ((dd_Positive(value1) && dd_Negative(value2)) || (dd_Negative(value1) && dd_Positive(value2))){
dd_CheckAdjacency(cone, &RayPtr1, &RayPtr2, &adj);
if (adj) dd_CreateNewRay(cone, RayPtr1, RayPtr2, hnew);
}
if (RayPtr2 != RayPtr3) {
RayPtr2 = RayPtr2->Next;
continue;
}
if (dd_Negative(value1) || equal) {
dd_Eliminate(cone, &RayPtr0);
RayPtr1 = RayPtr0->Next;
RayPtr2 = RayPtr2s;
} else {
completed=dd_TRUE;
}
pos1++;
progress = 100.0 * ((double)pos1 / pos2) * (2.0 * pos2 - pos1) / pos2;
if (progress-prevprogress>=10 && pos1%10==0 && dd_debug) {
fprintf(stderr,"*Progress of iteration %5ld(/%ld): %4ld/%4ld => %4.1f%% done\n",
cone->Iteration, cone->m, pos1, pos2, progress);
prevprogress=progress;
}
}
if (cone->RayCount==cone->WeaklyFeasibleRayCount) cone->CompStatus=dd_AllFound;
_L99:;
dd_clear(value1); dd_clear(value2);
}
void dd_AddNewHalfspace2(dd_ConePtr cone, dd_rowrange hnew)
/* This procedure must be used under PreOrderedRun mode */
{
dd_RayPtr RayPtr0,RayPtr1,RayPtr2;
dd_AdjacencyType *EdgePtr, *EdgePtr0;
long pos1;
dd_rowrange fii1, fii2;
dd_boolean localdebug=dd_FALSE;
dd_EvaluateARay2(hnew, cone);
/* Check feasibility of rays w.r.t. hnew
and sort them. ( -rays, +rays, 0rays)*/
if (cone->PosHead==NULL && cone->ZeroHead==NULL) {
cone->FirstRay=NULL;
cone->ArtificialRay->Next=cone->FirstRay;
cone->RayCount=0;
cone->CompStatus=dd_AllFound;
goto _L99; /* All rays are infeasible, and the computation must stop */
}
if (localdebug){
pos1=0;
fprintf(stderr,"(pos, FirstInfeasIndex, A Ray)=\n");
for (RayPtr0=cone->FirstRay; RayPtr0!=NULL; RayPtr0=RayPtr0->Next){
pos1++;
fprintf(stderr,"(%ld,%ld,",pos1,RayPtr0->FirstInfeasIndex);
dd_WriteNumber(stderr,RayPtr0->ARay);
fprintf(stderr,") ");
}
fprintf(stderr,"\n");
}
if (cone->ZeroHead==NULL) cone->ZeroHead=cone->LastRay;
EdgePtr=cone->Edges[cone->Iteration];
while (EdgePtr!=NULL){
RayPtr1=EdgePtr->Ray1;
RayPtr2=EdgePtr->Ray2;
fii1=RayPtr1->FirstInfeasIndex;
dd_CreateNewRay(cone, RayPtr1, RayPtr2, hnew);
fii2=cone->LastRay->FirstInfeasIndex;
if (fii1 != fii2)
dd_ConditionalAddEdge(cone,RayPtr1,cone->LastRay,cone->PosHead);
EdgePtr0=EdgePtr;
EdgePtr=EdgePtr->Next;
free(EdgePtr0);
(cone->EdgeCount)--;
}
cone->Edges[cone->Iteration]=NULL;
dd_DeleteNegativeRays(cone);
set_addelem(cone->AddedHalfspaces, hnew);
if (cone->Iterationm){
if (cone->ZeroHead!=NULL && cone->ZeroHead!=cone->LastRay){
if (cone->ZeroRayCount>200 && dd_debug) fprintf(stderr,"*New edges being scanned...\n");
dd_UpdateEdges(cone, cone->ZeroHead, cone->LastRay);
}
}
if (cone->RayCount==cone->WeaklyFeasibleRayCount) cone->CompStatus=dd_AllFound;
_L99:;
}
void dd_SelectNextHalfspace0(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*A natural way to choose the next hyperplane. Simply the largest index*/
long i;
dd_boolean determined;
i = cone->m;
determined = dd_FALSE;
do {
if (set_member(i, excluded))
i--;
else
determined = dd_TRUE;
} while (!determined && i>=1);
if (determined)
*hnext = i;
else
*hnext = 0;
}
void dd_SelectNextHalfspace1(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Natural way to choose the next hyperplane. Simply the least index*/
long i;
dd_boolean determined;
i = 1;
determined = dd_FALSE;
do {
if (set_member(i, excluded))
i++;
else
determined = dd_TRUE;
} while (!determined && i<=cone->m);
if (determined)
*hnext = i;
else
*hnext=0;
}
void dd_SelectNextHalfspace2(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Choose the next hyperplane with maximum infeasibility*/
long i, fea, inf, infmin, fi=0; /*feasibility and infeasibility numbers*/
infmin = cone->RayCount + 1;
for (i = 1; i <= cone->m; i++) {
if (!set_member(i, excluded)) {
dd_FeasibilityIndices(&fea, &inf, i, cone);
if (inf < infmin) {
infmin = inf;
fi = fea;
*hnext = i;
}
}
}
if (dd_debug) {
fprintf(stderr,"*infeasible rays (min) =%5ld, #feas rays =%5ld\n", infmin, fi);
}
}
void dd_SelectNextHalfspace3(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Choose the next hyperplane with maximum infeasibility*/
long i, fea, inf, infmax, fi=0; /*feasibility and infeasibility numbers*/
dd_boolean localdebug=dd_debug;
infmax = -1;
for (i = 1; i <= cone->m; i++) {
if (!set_member(i, excluded)) {
dd_FeasibilityIndices(&fea, &inf, i, cone);
if (inf > infmax) {
infmax = inf;
fi = fea;
*hnext = i;
}
}
}
if (localdebug) {
fprintf(stderr,"*infeasible rays (max) =%5ld, #feas rays =%5ld\n", infmax, fi);
}
}
void dd_SelectNextHalfspace4(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Choose the next hyperplane with the most unbalanced cut*/
long i, fea, inf, max, tmax, fi=0, infi=0;
/*feasibility and infeasibility numbers*/
max = -1;
for (i = 1; i <= cone->m; i++) {
if (!set_member(i, excluded)) {
dd_FeasibilityIndices(&fea, &inf, i, cone);
if (fea <= inf)
tmax = inf;
else
tmax = fea;
if (tmax > max) {
max = tmax;
fi = fea;
infi = inf;
*hnext = i;
}
}
}
if (!dd_debug)
return;
if (max == fi) {
fprintf(stderr,"*infeasible rays (min) =%5ld, #feas rays =%5ld\n", infi, fi);
} else {
fprintf(stderr,"*infeasible rays (max) =%5ld, #feas rays =%5ld\n", infi, fi);
}
}
void dd_SelectNextHalfspace5(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Choose the next hyperplane which is lexico-min*/
long i, minindex;
mytype *v1, *v2;
minindex = 0;
v1 = NULL;
for (i = 1; i <= cone->m; i++) {
if (!set_member(i, excluded)) {
v2 = cone->A[i - 1];
if (minindex == 0) {
minindex = i;
v1=v2;
} else if (dd_LexSmaller(v2,v1,cone->d)) {
minindex = i;
v1=v2;
}
}
}
*hnext = minindex;
}
void dd_SelectNextHalfspace6(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hnext)
{
/*Choose the next hyperplane which is lexico-max*/
long i, maxindex;
mytype *v1, *v2;
maxindex = 0;
v1 = NULL;
for (i = 1; i <= cone->m; i++) {
if (!set_member(i, excluded)) {
v2= cone->A[i - 1];
if (maxindex == 0) {
maxindex = i;
v1=v2;
} else if (dd_LexLarger(v2, v1, cone->d)) {
maxindex = i;
v1=v2;
}
}
}
*hnext = maxindex;
}
void dd_UniqueRows(dd_rowindex OV, long p, long r, dd_Amatrix A, long dmax, dd_rowset preferred, long *uniqrows)
{
/* Select a subset of rows of A (with range [p, q] up to dimension dmax) by removing duplicates.
When a row subset preferred is nonempty, those row indices in the set have priority. If
two priority rows define the same row vector, one is chosen.
For a selected unique row i, OV[i] returns a new position of the unique row i.
For other nonuniqu row i, OV[i] returns a negative of the original row j dominating i.
Thus the original contents of OV[p..r] will be rewritten. Other components remain the same.
*uniqrows returns the number of unique rows.
*/
long i,iuniq,j;
mytype *x;
dd_boolean localdebug=dd_FALSE;
if (p<=0 || p > r) goto _L99;
iuniq=p; j=1; /* the first unique row candidate */
x=A[p-1];
OV[p]=j; /* tentative row index of the candidate */
for (i=p+1;i<=r; i++){
if (!dd_LexEqual(x,A[i-1],dmax)) {
/* a new row vector found. */
iuniq=i;
j=j+1;
OV[i]=j; /* Tentatively register the row i. */
x=A[i-1];
} else {
/* rows are equal */
if (set_member(i, preferred) && !set_member(iuniq, preferred)){
OV[iuniq]=-i; /* the row iuniq is dominated by the row i */
iuniq=i; /* the row i is preferred. Change the candidate. */
OV[i]=j; /* the row i is tentatively registered. */
x=A[i-1];
} else {
OV[i]=-iuniq; /* the row iuniq is dominated by the row i */
}
}
}
*uniqrows=j;
if (localdebug){
printf("The number of unique rows are %ld\n with order vector",*uniqrows);
for (i=p;i<=r; i++){
printf(" %ld:%ld ",i,OV[i]);
}
printf("\n");
}
_L99:;
}
long dd_Partition(dd_rowindex OV, long p, long r, dd_Amatrix A, long dmax)
{
mytype *x;
long i,j,ovi;
x=A[OV[p]-1];
i=p-1;
j=r+1;
while (dd_TRUE){
do{
j--;
} while (dd_LexLarger(A[OV[j]-1],x,dmax));
do{
i++;
} while (dd_LexSmaller(A[OV[i]-1],x,dmax));
if (i1 ; j--) {
r=rand();
u=r/rand_max;
xk=(double)(j*u +1);
k=(long)xk;
if (localdebug) fprintf(stderr,"u=%g, k=%ld, r=%g, randmax= %g\n",u,k,r,rand_max);
ovj=OV[j];
OV[j]=OV[k];
OV[k]=ovj;
if (localdebug) fprintf(stderr,"row %ld is exchanged with %ld\n",j,k);
}
}
void dd_ComputeRowOrderVector(dd_ConePtr cone)
{
long i,itemp;
cone->OrderVector[0]=0;
switch (cone->HalfspaceOrder){
case dd_MaxIndex:
for(i=1; i<=cone->m; i++) cone->OrderVector[i]=cone->m-i+1;
break;
case dd_MinIndex:
for(i=1; i<=cone->m; i++) cone->OrderVector[i]=i;
break;
case dd_LexMin: case dd_MinCutoff: case dd_MixCutoff: case dd_MaxCutoff:
for(i=1; i<=cone->m; i++) cone->OrderVector[i]=i;
dd_RandomPermutation(cone->OrderVector, cone->m, cone->rseed);
dd_QuickSort(cone->OrderVector, 1, cone->m, cone->A, cone->d);
break;
case dd_LexMax:
for(i=1; i<=cone->m; i++) cone->OrderVector[i]=i;
dd_RandomPermutation(cone->OrderVector, cone->m, cone->rseed);
dd_QuickSort(cone->OrderVector, 1, cone->m, cone->A, cone->d);
for(i=1; i<=cone->m/2;i++){ /* just reverse the order */
itemp=cone->OrderVector[i];
cone->OrderVector[i]=cone->OrderVector[cone->m-i+1];
cone->OrderVector[cone->m-i+1]=itemp;
}
break;
case dd_RandomRow:
for(i=1; i<=cone->m; i++) cone->OrderVector[i]=i;
dd_RandomPermutation(cone->OrderVector, cone->m, cone->rseed);
break;
}
}
void dd_UpdateRowOrderVector(dd_ConePtr cone, dd_rowset PriorityRows)
/* Update the RowOrder vector to shift selected rows
in highest order.
*/
{
dd_rowrange i,j,k,j1=0,oj=0;
long rr;
dd_boolean found, localdebug=dd_FALSE;
if (dd_debug) localdebug=dd_TRUE;
found=dd_TRUE;
rr=set_card(PriorityRows);
if (localdebug) set_fwrite(stderr,PriorityRows);
for (i=1; i<=rr; i++){
found=dd_FALSE;
for (j=i; j<=cone->m && !found; j++){
oj=cone->OrderVector[j];
if (set_member(oj, PriorityRows)){
found=dd_TRUE;
if (localdebug) fprintf(stderr,"%ldth in sorted list (row %ld) is in PriorityRows\n", j, oj);
j1=j;
}
}
if (found){
if (j1>i) {
/* shift everything lower: ov[i]->cone->ov[i+1]..ov[j1-1]->cone->ov[j1] */
for (k=j1; k>=i; k--) cone->OrderVector[k]=cone->OrderVector[k-1];
cone->OrderVector[i]=oj;
if (localdebug){
fprintf(stderr,"OrderVector updated to:\n");
for (j = 1; j <= cone->m; j++) fprintf(stderr," %2ld", cone->OrderVector[j]);
fprintf(stderr,"\n");
}
}
} else {
fprintf(stderr,"UpdateRowOrder: Error.\n");
goto _L99;
}
}
_L99:;
}
void dd_SelectPreorderedNext(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hh)
{
dd_rowrange i,k;
*hh=0;
for (i=1; i<=cone->m && *hh==0; i++){
k=cone->OrderVector[i];
if (!set_member(k, excluded)) *hh=k ;
}
}
void dd_SelectNextHalfspace(dd_ConePtr cone, dd_rowset excluded, dd_rowrange *hh)
{
if (cone->PreOrderedRun){
if (dd_debug) {
fprintf(stderr,"debug dd_SelectNextHalfspace: Use PreorderNext\n");
}
dd_SelectPreorderedNext(cone, excluded, hh);
}
else {
if (dd_debug) {
fprintf(stderr,"debug dd_SelectNextHalfspace: Use DynamicOrderedNext\n");
}
switch (cone->HalfspaceOrder) {
case dd_MaxIndex:
dd_SelectNextHalfspace0(cone, excluded, hh);
break;
case dd_MinIndex:
dd_SelectNextHalfspace1(cone, excluded, hh);
break;
case dd_MinCutoff:
dd_SelectNextHalfspace2(cone, excluded, hh);
break;
case dd_MaxCutoff:
dd_SelectNextHalfspace3(cone, excluded, hh);
break;
case dd_MixCutoff:
dd_SelectNextHalfspace4(cone, excluded, hh);
break;
default:
dd_SelectNextHalfspace0(cone, excluded, hh);
break;
}
}
}
dd_boolean dd_Nonnegative(mytype val)
{
/* if (val>=-dd_zero) return dd_TRUE; */
if (dd_cmp(val,dd_minuszero)>=0) return dd_TRUE;
else return dd_FALSE;
}
dd_boolean dd_Nonpositive(mytype val)
{
/* if (val<=dd_zero) return dd_TRUE; */
if (dd_cmp(val,dd_zero)<=0) return dd_TRUE;
else return dd_FALSE;
}
dd_boolean dd_Positive(mytype val)
{
return !dd_Nonpositive(val);
}
dd_boolean dd_Negative(mytype val)
{
return !dd_Nonnegative(val);
}
dd_boolean dd_EqualToZero(mytype val)
{
return (dd_Nonnegative(val) && dd_Nonpositive(val));
}
dd_boolean dd_Nonzero(mytype val)
{
return (dd_Positive(val) || dd_Negative(val));
}
dd_boolean dd_Equal(mytype val1,mytype val2)
{
return (!dd_Larger(val1,val2) && !dd_Smaller(val1,val2));
}
dd_boolean dd_Larger(mytype val1,mytype val2)
{
mytype temp;
dd_boolean answer;
dd_init(temp);
dd_sub(temp,val1, val2);
answer=dd_Positive(temp);
dd_clear(temp);
return answer;
}
dd_boolean dd_Smaller(mytype val1,mytype val2)
{
return dd_Larger(val2,val1);
}
void dd_abs(mytype absval, mytype val)
{
if (dd_Negative(val)) dd_neg(absval,val);
else dd_set(absval,val);
}
void dd_LinearComb(mytype lc, mytype v1, mytype c1, mytype v2, mytype c2)
/* lc := v1 * c1 + v2 * c2 */
{
mytype temp;
dd_init(temp);
dd_mul(lc,v1,c1);
dd_mul(temp,v2,c2);
dd_add(lc,lc,temp);
dd_clear(temp);
}
void dd_InnerProduct(mytype prod, dd_colrange d, dd_Arow v1, dd_Arow v2)
{
mytype temp;
dd_colrange j;
dd_boolean localdebug=dd_FALSE;
dd_init(temp);
dd_set_si(prod, 0);
for (j = 0; j < d; j++){
dd_mul(temp,v1[j],v2[j]);
dd_add(prod,prod,temp);
}
if (localdebug) {
fprintf(stderr,"InnerProduct:\n");
dd_WriteArow(stderr, v1, d);
dd_WriteArow(stderr, v2, d);
fprintf(stderr,"prod =");
dd_WriteNumber(stderr, prod);
fprintf(stderr,"\n");
}
dd_clear(temp);
}
/* end of cddcore.c */
pplacer-1.1.alpha19/cdd_src/cddio.c 0000664 0000000 0000000 00000153063 13031546015 0017074 0 ustar 00root root 0000000 0000000 /* cddio.c: Basic Input and Output Procedures for cddlib
written by Komei Fukuda, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* cddlib : C-library of the double description method for
computing all vertices and extreme rays of the polyhedron
P= {x : b - A x >= 0}.
Please read COPYING (GNU General Public Licence) and
the manual cddlibman.tex for detail.
*/
#include "setoper.h" /* set operation library header (Ver. June 1, 2000 or later) */
#include "cdd.h"
#include
#include
#include
#include
#include
/* void dd_fread_rational_value (FILE *, mytype *); */
void dd_SetLinearity(dd_MatrixPtr, char *);
void dd_SetInputFile(FILE **f,dd_DataFileType inputfile,dd_ErrorType *Error)
{
int opened=0,stop,quit=0;
int i,trial=0;
char ch;
char *tempname;
*Error=dd_NoError;
while (!opened && !quit) {
fprintf(stderr,"\n>> Input file: ");
if(scanf("%s",inputfile));
ch=getchar();
stop=dd_FALSE;
for (i=0; i5) {
*Error=dd_IFileNotFound;
quit=1;
}
}
}
}
void dd_SetWriteFileName(dd_DataFileType inputfile, dd_DataFileType outfile, char cflag, dd_RepresentationType rep)
{
char *extension;
dd_DataFileType ifilehead="";
int i,dotpos;
switch (cflag) {
case 'o':
switch (rep) {
case dd_Generator:
extension=".ine"; break; /* output file for ine data */
case dd_Inequality:
extension=".ext"; break; /* output file for ext data */
default:
extension=".xxx";break;
}
break;
case 'a': /* decide for output adjacence */
if (rep==dd_Inequality)
extension=".ead"; /* adjacency file for ext data */
else
extension=".iad"; /* adjacency file for ine data */
break;
case 'i': /* decide for output incidence */
if (rep==dd_Inequality)
extension=".ecd"; /* ext incidence file */
else
extension=".icd"; /* ine incidence file */
break;
case 'n': /* decide for input incidence */
if (rep==dd_Inequality)
extension=".icd"; /* ine incidence file */
else
extension=".ecd"; /* ext incidence file */
break;
case 'j': /* decide for input adjacency */
if (rep==dd_Inequality)
extension=".iad"; /* ine adjacency file */
else
extension=".ead"; /* ext adjacency file */
break;
case 'l':
extension=".ddl";break; /* log file */
case 'd':
extension=".dex";break; /* decomposition output */
case 'p':
extension="sub.ine";break; /* preprojection sub inequality file */
case 'v':
extension=".solved";break; /* verify_input file */
case 's':
extension=".lps";break; /* LP solution file */
default:
extension=".xxx";break;
}
dotpos=-1;
for (i=0; i< strlen(inputfile); i++){
if (inputfile[i]=='.') dotpos=i;
}
if (dotpos>1) strncpy(ifilehead, inputfile, dotpos);
else strcpy(ifilehead,inputfile);
if (strlen(inputfile)<=0) strcpy(ifilehead,"tempcdd");
strcpy(outfile,ifilehead);
strcat(outfile,extension);
if (strcmp(inputfile, outfile)==0) {
strcpy(outfile,inputfile);
strcat(outfile,extension);
}
/* fprintf(stderr,"outfile name = %s\n",outfile); */
}
dd_NumberType dd_GetNumberType(char *line)
{
dd_NumberType nt;
if (strncmp(line, "integer", 7)==0) {
nt = dd_Integer;
}
else if (strncmp(line, "rational", 8)==0) {
nt = dd_Rational;
}
else if (strncmp(line, "real", 4)==0) {
nt = dd_Real;
}
else {
nt=dd_Unknown;
}
return nt;
}
void dd_ProcessCommandLine(FILE *f, dd_MatrixPtr M, char *line)
{
char newline[dd_linelenmax];
dd_colrange j;
mytype value;
dd_init(value);
if (strncmp(line, "hull", 4)==0) {
M->representation = dd_Generator;
}
if (strncmp(line, "debug", 5)==0) {
dd_debug = dd_TRUE;
#ifdef GMPRATIONAL
ddf_debug = ddf_TRUE;
#endif
}
if (strncmp(line, "partial_enum", 12)==0 ||
strncmp(line, "equality", 8)==0 ||
strncmp(line, "linearity", 9)==0 ) {
if(fgets(newline,dd_linelenmax,f));
dd_SetLinearity(M,newline);
}
if (strncmp(line, "maximize", 8)==0 ||
strncmp(line, "minimize", 8)==0) {
if (strncmp(line, "maximize", 8)==0) M->objective=dd_LPmax;
else M->objective=dd_LPmin;
for (j = 1; j <= M->colsize; j++) {
if (M->numbtype==dd_Real) {
#if !defined(GMPRATIONAL)
double rvalue;
if(fscanf(f, "%lf", &rvalue));
dd_set_d(value, rvalue);
#endif
} else {
dd_fread_rational_value (f, value);
}
dd_set(M->rowvec[j - 1],value);
if (dd_debug) {fprintf(stderr,"cost(%5ld) =",j); dd_WriteNumber(stderr,value);}
} /*of j*/
}
dd_clear(value);
}
dd_boolean dd_AppendMatrix2Poly(dd_PolyhedraPtr *poly, dd_MatrixPtr M)
{
dd_boolean success=dd_FALSE;
dd_MatrixPtr Mpoly,Mnew=NULL;
dd_ErrorType err;
if ((*poly)!=NULL && (*poly)->m >=0 && (*poly)->d>=0 &&
(*poly)->d==M->colsize && M->rowsize>0){
Mpoly=dd_CopyInput(*poly);
Mnew=dd_AppendMatrix(Mpoly, M);
dd_FreePolyhedra(*poly);
*poly=dd_DDMatrix2Poly(Mnew,&err);
dd_FreeMatrix(Mpoly);
dd_FreeMatrix(Mnew);
if (err==dd_NoError) success=dd_TRUE;
}
return success;
}
dd_MatrixPtr dd_MatrixCopy(dd_MatrixPtr M)
{
dd_MatrixPtr Mcopy=NULL;
dd_rowrange m;
dd_colrange d;
m= M->rowsize;
d= M->colsize;
if (m >=0 && d >=0){
Mcopy=dd_CreateMatrix(m, d);
dd_CopyAmatrix(Mcopy->matrix, M->matrix, m, d);
dd_CopyArow(Mcopy->rowvec, M->rowvec, d);
set_copy(Mcopy->linset,M->linset);
Mcopy->numbtype=M->numbtype;
Mcopy->representation=M->representation;
Mcopy->objective=M->objective;
}
return Mcopy;
}
dd_MatrixPtr dd_CopyMatrix(dd_MatrixPtr M)
{
return dd_MatrixCopy(M);
}
dd_MatrixPtr dd_MatrixNormalizedCopy(dd_MatrixPtr M)
{
dd_MatrixPtr Mcopy=NULL;
dd_rowrange m;
dd_colrange d;
m= M->rowsize;
d= M->colsize;
if (m >=0 && d >=0){
Mcopy=dd_CreateMatrix(m, d);
dd_CopyNormalizedAmatrix(Mcopy->matrix, M->matrix, m, d);
dd_CopyArow(Mcopy->rowvec, M->rowvec, d);
set_copy(Mcopy->linset,M->linset);
Mcopy->numbtype=M->numbtype;
Mcopy->representation=M->representation;
Mcopy->objective=M->objective;
}
return Mcopy;
}
dd_MatrixPtr dd_MatrixAppend(dd_MatrixPtr M1, dd_MatrixPtr M2)
{
dd_MatrixPtr M=NULL;
dd_rowrange i, m,m1,m2;
dd_colrange j, d,d1,d2;
m1=M1->rowsize;
d1=M1->colsize;
m2=M2->rowsize;
d2=M2->colsize;
m=m1+m2;
d=d1;
if (d1>=0 && d1==d2 && m1>=0 && m2>=0){
M=dd_CreateMatrix(m, d);
dd_CopyAmatrix(M->matrix, M1->matrix, m1, d);
dd_CopyArow(M->rowvec, M1->rowvec, d);
for (i=0; ilinset)) set_addelem(M->linset,i+1);
}
for (i=0; imatrix[m1+i][j],M2->matrix[i][j]);
/* append the second matrix */
if (set_member(i+1,M2->linset)) set_addelem(M->linset,m1+i+1);
}
M->numbtype=M1->numbtype;
}
return M;
}
dd_MatrixPtr dd_MatrixNormalizedSortedCopy(dd_MatrixPtr M,dd_rowindex *newpos) /* 094 */
{
/* Sort the rows of Amatrix lexicographically, and return a link to this sorted copy.
The vector newpos is allocated, where newpos[i] returns the new row index
of the original row i (i=1,...,M->rowsize). */
dd_MatrixPtr Mcopy=NULL,Mnorm=NULL;
dd_rowrange m,i;
dd_colrange d;
dd_rowindex roworder;
/* if (newpos!=NULL) free(newpos); */
m= M->rowsize;
d= M->colsize;
roworder=(long *)calloc(m+1,sizeof(long));
*newpos=(long *)calloc(m+1,sizeof(long));
if (m >=0 && d >=0){
Mnorm=dd_MatrixNormalizedCopy(M);
Mcopy=dd_CreateMatrix(m, d);
for(i=1; i<=m; i++) roworder[i]=i;
dd_RandomPermutation(roworder, m, 123);
dd_QuickSort(roworder,1,m,Mnorm->matrix,d);
dd_PermuteCopyAmatrix(Mcopy->matrix, Mnorm->matrix, m, d, roworder);
dd_CopyArow(Mcopy->rowvec, M->rowvec, d);
for(i=1; i<=m; i++) {
if (set_member(roworder[i],M->linset)) set_addelem(Mcopy->linset, i);
(*newpos)[roworder[i]]=i;
}
Mcopy->numbtype=M->numbtype;
Mcopy->representation=M->representation;
Mcopy->objective=M->objective;
dd_FreeMatrix(Mnorm);
}
free(roworder);
return Mcopy;
}
dd_MatrixPtr dd_MatrixUniqueCopy(dd_MatrixPtr M,dd_rowindex *newpos)
{
/* Remove row duplicates, and return a link to this sorted copy.
Linearity rows have priority over the other rows.
It is better to call this after sorting with dd_MatrixNormalizedSortedCopy.
The vector newpos is allocated, where *newpos[i] returns the new row index
of the original row i (i=1,...,M->rowsize). *newpos[i] is negative if the original
row is dominated by -*newpos[i] and eliminated in the new copy.
*/
dd_MatrixPtr Mcopy=NULL;
dd_rowrange m,i,uniqrows;
dd_rowset preferredrows;
dd_colrange d;
dd_rowindex roworder;
/* if (newpos!=NULL) free(newpos); */
m= M->rowsize;
d= M->colsize;
preferredrows=M->linset;
roworder=(long *)calloc(m+1,sizeof(long));
if (m >=0 && d >=0){
for(i=1; i<=m; i++) roworder[i]=i;
dd_UniqueRows(roworder, 1, m, M->matrix, d,preferredrows, &uniqrows);
Mcopy=dd_CreateMatrix(uniqrows, d);
dd_PermutePartialCopyAmatrix(Mcopy->matrix, M->matrix, m, d, roworder,1,m);
dd_CopyArow(Mcopy->rowvec, M->rowvec, d);
for(i=1; i<=m; i++) {
if (roworder[i]>0 && set_member(i,M->linset)) set_addelem(Mcopy->linset, roworder[i]);
}
Mcopy->numbtype=M->numbtype;
Mcopy->representation=M->representation;
Mcopy->objective=M->objective;
}
*newpos=roworder;
return Mcopy;
}
dd_MatrixPtr dd_MatrixNormalizedSortedUniqueCopy(dd_MatrixPtr M,dd_rowindex *newpos) /* 094 */
{
/* Sort and remove row duplicates, and return a link to this sorted copy.
Linearity rows have priority over the other rows.
It is better to call this after sorting with dd_MatrixNormalizedSortedCopy.
The vector newpos is allocated, where *newpos[i] returns the new row index
of the original row i (i=1,...,M->rowsize). *newpos[i] is negative if the original
row is dominated by -*newpos[i] and eliminated in the new copy.
*/
dd_MatrixPtr M1=NULL,M2=NULL;
dd_rowrange m,i;
dd_colrange d;
dd_rowindex newpos1=NULL,newpos1r=NULL,newpos2=NULL;
/* if (newpos!=NULL) free(newpos); */
m= M->rowsize;
d= M->colsize;
*newpos=(long *)calloc(m+1,sizeof(long));
newpos1r=(long *)calloc(m+1,sizeof(long));
if (m>=0 && d>=0){
M1=dd_MatrixNormalizedSortedCopy(M,&newpos1);
for (i=1; i<=m;i++) newpos1r[newpos1[i]]=i; /* reverse of newpos1 */
M2=dd_MatrixUniqueCopy(M1,&newpos2);
set_emptyset(M2->linset);
for(i=1; i<=m; i++) {
if (newpos2[newpos1[i]]>0){
printf("newpos1[%ld]=%ld, newpos2[newpos1[%ld]]=%ld\n",i,newpos1[i], i,newpos2[newpos1[i]]);
if (set_member(i,M->linset)) set_addelem(M2->linset, newpos2[newpos1[i]]);
(*newpos)[i]=newpos2[newpos1[i]];
} else {
(*newpos)[i]=-newpos1r[-newpos2[newpos1[i]]];
}
}
dd_FreeMatrix(M1);free(newpos1);free(newpos2);free(newpos1r);
}
return M2;
}
dd_MatrixPtr dd_MatrixSortedUniqueCopy(dd_MatrixPtr M,dd_rowindex *newpos) /* 094 */
{
/* Same as dd_MatrixNormalizedSortedUniqueCopy except that it returns a unnormalized origial data
with original ordering.
*/
dd_MatrixPtr M1=NULL,M2=NULL;
dd_rowrange m,i,k,ii;
dd_colrange d;
dd_rowindex newpos1=NULL,newpos1r=NULL,newpos2=NULL;
/* if (newpos!=NULL) free(newpos); */
m= M->rowsize;
d= M->colsize;
*newpos=(long *)calloc(m+1,sizeof(long));
newpos1r=(long *)calloc(m+1,sizeof(long));
if (m>=0 && d>=0){
M1=dd_MatrixNormalizedSortedCopy(M,&newpos1);
for (i=1; i<=m;i++) newpos1r[newpos1[i]]=i; /* reverse of newpos1 */
M2=dd_MatrixUniqueCopy(M1,&newpos2);
dd_FreeMatrix(M1);
set_emptyset(M2->linset);
for(i=1; i<=m; i++) {
if (newpos2[newpos1[i]]>0){
if (set_member(i,M->linset)) set_addelem(M2->linset, newpos2[newpos1[i]]);
(*newpos)[i]=newpos2[newpos1[i]];
} else {
(*newpos)[i]=-newpos1r[-newpos2[newpos1[i]]];
}
}
ii=0;
set_emptyset(M2->linset);
for (i = 1; i<=m ; i++) {
k=(*newpos)[i];
if (k>0) {
ii+=1;
(*newpos)[i]=ii;
dd_CopyArow(M2->matrix[ii-1],M->matrix[i-1],d);
if (set_member(i,M->linset)) set_addelem(M2->linset, ii);
}
}
free(newpos1);free(newpos2);free(newpos1r);
}
return M2;
}
dd_MatrixPtr dd_AppendMatrix(dd_MatrixPtr M1, dd_MatrixPtr M2)
{
return dd_MatrixAppend(M1,M2);
}
int dd_MatrixAppendTo(dd_MatrixPtr *M1, dd_MatrixPtr M2)
{
dd_MatrixPtr M=NULL;
dd_rowrange i, m,m1,m2;
dd_colrange j, d,d1,d2;
dd_boolean success=0;
m1=(*M1)->rowsize;
d1=(*M1)->colsize;
m2=M2->rowsize;
d2=M2->colsize;
m=m1+m2;
d=d1;
if (d1>=0 && d1==d2 && m1>=0 && m2>=0){
M=dd_CreateMatrix(m, d);
dd_CopyAmatrix(M->matrix, (*M1)->matrix, m1, d);
dd_CopyArow(M->rowvec, (*M1)->rowvec, d);
for (i=0; ilinset)) set_addelem(M->linset,i+1);
}
for (i=0; imatrix[m1+i][j],M2->matrix[i][j]);
/* append the second matrix */
if (set_member(i+1,M2->linset)) set_addelem(M->linset,m1+i+1);
}
M->numbtype=(*M1)->numbtype;
dd_FreeMatrix(*M1);
*M1=M;
success=1;
}
return success;
}
int dd_MatrixRowRemove(dd_MatrixPtr *M, dd_rowrange r) /* 092 */
{
dd_rowrange i,m;
dd_colrange d;
dd_boolean success=0;
m=(*M)->rowsize;
d=(*M)->colsize;
if (r >= 1 && r <=m){
(*M)->rowsize=m-1;
dd_FreeArow(d, (*M)->matrix[r-1]);
set_delelem((*M)->linset,r);
/* slide the row headers */
for (i=r; imatrix[i-1]=(*M)->matrix[i];
if (set_member(i+1, (*M)->linset)){
set_delelem((*M)->linset,i+1);
set_addelem((*M)->linset,i);
}
}
success=1;
}
return success;
}
int dd_MatrixRowRemove2(dd_MatrixPtr *M, dd_rowrange r, dd_rowindex *newpos) /* 094 */
{
dd_rowrange i,m;
dd_colrange d;
dd_boolean success=0;
dd_rowindex roworder;
m=(*M)->rowsize;
d=(*M)->colsize;
if (r >= 1 && r <=m){
roworder=(long *)calloc(m+1,sizeof(long));
(*M)->rowsize=m-1;
dd_FreeArow(d, (*M)->matrix[r-1]);
set_delelem((*M)->linset,r);
/* slide the row headers */
for (i=1; imatrix[i-1]=(*M)->matrix[i];
roworder[i+1]=i;
if (set_member(i+1, (*M)->linset)){
set_delelem((*M)->linset,i+1);
set_addelem((*M)->linset,i);
}
}
success=1;
}
return success;
}
dd_MatrixPtr dd_MatrixSubmatrix(dd_MatrixPtr M, dd_rowset delset) /* 092 */
{
dd_MatrixPtr Msub=NULL;
dd_rowrange i,isub=1, m,msub;
dd_colrange d;
m= M->rowsize;
d= M->colsize;
msub=m;
if (m >=0 && d >=0){
for (i=1; i<=m; i++) {
if (set_member(i,delset)) msub-=1;
}
Msub=dd_CreateMatrix(msub, d);
for (i=1; i<=m; i++){
if (!set_member(i,delset)){
dd_CopyArow(Msub->matrix[isub-1], M->matrix[i-1], d);
if (set_member(i, M->linset)){
set_addelem(Msub->linset,isub);
}
isub++;
}
}
dd_CopyArow(Msub->rowvec, M->rowvec, d);
Msub->numbtype=M->numbtype;
Msub->representation=M->representation;
Msub->objective=M->objective;
}
return Msub;
}
dd_MatrixPtr dd_MatrixSubmatrix2(dd_MatrixPtr M, dd_rowset delset,dd_rowindex *newpos) /* 092 */
{ /* returns a pointer to a new matrix which is a submatrix of M with rows in delset
removed. *newpos[i] returns the position of the original row i in the new matrix.
It is -1 if and only if it is deleted.
*/
dd_MatrixPtr Msub=NULL;
dd_rowrange i,isub=1, m,msub;
dd_colrange d;
dd_rowindex roworder;
m= M->rowsize;
d= M->colsize;
msub=m;
if (m >=0 && d >=0){
roworder=(long *)calloc(m+1,sizeof(long));
for (i=1; i<=m; i++) {
if (set_member(i,delset)) msub-=1;
}
Msub=dd_CreateMatrix(msub, d);
for (i=1; i<=m; i++){
if (set_member(i,delset)){
roworder[i]=0; /* zero means the row i is removed */
} else {
dd_CopyArow(Msub->matrix[isub-1], M->matrix[i-1], d);
if (set_member(i, M->linset)){
set_addelem(Msub->linset,isub);
}
roworder[i]=isub;
isub++;
}
}
*newpos=roworder;
dd_CopyArow(Msub->rowvec, M->rowvec, d);
Msub->numbtype=M->numbtype;
Msub->representation=M->representation;
Msub->objective=M->objective;
}
return Msub;
}
dd_MatrixPtr dd_MatrixSubmatrix2L(dd_MatrixPtr M, dd_rowset delset,dd_rowindex *newpos) /* 094 */
{ /* This is same as dd_MatrixSubmatrix2 except that the linearity rows will be shifted up
so that they are at the top of the matrix.
*/
dd_MatrixPtr Msub=NULL;
dd_rowrange i,iL, iI, m,msub;
dd_colrange d;
dd_rowindex roworder;
m= M->rowsize;
d= M->colsize;
msub=m;
if (m >=0 && d >=0){
roworder=(long *)calloc(m+1,sizeof(long));
for (i=1; i<=m; i++) {
if (set_member(i,delset)) msub-=1;
}
Msub=dd_CreateMatrix(msub, d);
iL=1; iI=set_card(M->linset)+1; /* starting positions */
for (i=1; i<=m; i++){
if (set_member(i,delset)){
roworder[i]=0; /* zero means the row i is removed */
} else {
if (set_member(i,M->linset)){
dd_CopyArow(Msub->matrix[iL-1], M->matrix[i-1], d);
set_delelem(Msub->linset,i);
set_addelem(Msub->linset,iL);
roworder[i]=iL;
iL+=1;
} else {
dd_CopyArow(Msub->matrix[iI-1], M->matrix[i-1], d);
roworder[i]=iI;
iI+=1;
}
}
}
*newpos=roworder;
dd_CopyArow(Msub->rowvec, M->rowvec, d);
Msub->numbtype=M->numbtype;
Msub->representation=M->representation;
Msub->objective=M->objective;
}
return Msub;
}
int dd_MatrixRowsRemove(dd_MatrixPtr *M, dd_rowset delset) /* 094 */
{
dd_MatrixPtr Msub=NULL;
int success;
Msub=dd_MatrixSubmatrix(*M, delset);
dd_FreeMatrix(*M);
*M=Msub;
success=1;
return success;
}
int dd_MatrixRowsRemove2(dd_MatrixPtr *M, dd_rowset delset,dd_rowindex *newpos) /* 094 */
{
dd_MatrixPtr Msub=NULL;
int success;
Msub=dd_MatrixSubmatrix2(*M, delset,newpos);
dd_FreeMatrix(*M);
*M=Msub;
success=1;
return success;
}
int dd_MatrixShiftupLinearity(dd_MatrixPtr *M,dd_rowindex *newpos) /* 094 */
{
dd_MatrixPtr Msub=NULL;
int success;
dd_rowset delset;
set_initialize(&delset,(*M)->rowsize); /* emptyset */
Msub=dd_MatrixSubmatrix2L(*M, delset,newpos);
dd_FreeMatrix(*M);
*M=Msub;
set_free(delset);
success=1;
return success;
}
dd_PolyhedraPtr dd_CreatePolyhedraData(dd_rowrange m, dd_colrange d)
{
dd_rowrange i;
dd_PolyhedraPtr poly=NULL;
poly=(dd_PolyhedraPtr) malloc (sizeof(dd_PolyhedraType));
poly->child =NULL; /* this links the homogenized cone data */
poly->m =m;
poly->d =d;
poly->n =-1; /* the size of output is not known */
poly->m_alloc =m+2; /* the allocated row size of matrix A */
poly->d_alloc =d; /* the allocated col size of matrix A */
poly->ldim =0; /* initialize the linearity dimension */
poly->numbtype=dd_Real;
dd_InitializeAmatrix(poly->m_alloc,poly->d_alloc,&(poly->A));
dd_InitializeArow(d,&(poly->c)); /* cost vector */
poly->representation =dd_Inequality;
poly->homogeneous =dd_FALSE;
poly->EqualityIndex=(int *)calloc(m+2, sizeof(int));
/* size increased to m+2 in 092b because it is used by the child cone,
This is a bug fix suggested by Thao Dang. */
/* ith component is 1 if it is equality, -1 if it is strict inequality, 0 otherwise. */
for (i = 0; i <= m+1; i++) poly->EqualityIndex[i]=0;
poly->IsEmpty = -1; /* initially set to -1, neither TRUE nor FALSE, meaning unknown */
poly->NondegAssumed = dd_FALSE;
poly->InitBasisAtBottom = dd_FALSE;
poly->RestrictedEnumeration = dd_FALSE;
poly->RelaxedEnumeration = dd_FALSE;
poly->AincGenerated=dd_FALSE; /* Ainc is a set array to store the input incidence. */
return poly;
}
dd_boolean dd_InitializeConeData(dd_rowrange m, dd_colrange d, dd_ConePtr *cone)
{
dd_boolean success=dd_TRUE;
dd_colrange j;
(*cone)=(dd_ConePtr)calloc(1, sizeof(dd_ConeType));
/* INPUT: A given representation of a cone: inequality */
(*cone)->m=m;
(*cone)->d=d;
(*cone)->m_alloc=m+2; /* allocated row size of matrix A */
(*cone)->d_alloc=d; /* allocated col size of matrix A, B and Bsave */
(*cone)->numbtype=dd_Real;
(*cone)->parent=NULL;
/* CONTROL: variables to control computation */
(*cone)->Iteration=0;
(*cone)->HalfspaceOrder=dd_LexMin;
(*cone)->ArtificialRay=NULL;
(*cone)->FirstRay=NULL;
(*cone)->LastRay=NULL; /* The second description: Generator */
(*cone)->PosHead=NULL;
(*cone)->ZeroHead=NULL;
(*cone)->NegHead=NULL;
(*cone)->PosLast=NULL;
(*cone)->ZeroLast=NULL;
(*cone)->NegLast=NULL;
(*cone)->RecomputeRowOrder = dd_TRUE;
(*cone)->PreOrderedRun = dd_FALSE;
set_initialize(&((*cone)->GroundSet),(*cone)->m_alloc);
set_initialize(&((*cone)->EqualitySet),(*cone)->m_alloc);
set_initialize(&((*cone)->NonequalitySet),(*cone)->m_alloc);
set_initialize(&((*cone)->AddedHalfspaces),(*cone)->m_alloc);
set_initialize(&((*cone)->WeaklyAddedHalfspaces),(*cone)->m_alloc);
set_initialize(&((*cone)->InitialHalfspaces),(*cone)->m_alloc);
(*cone)->RayCount=0;
(*cone)->FeasibleRayCount=0;
(*cone)->WeaklyFeasibleRayCount=0;
(*cone)->TotalRayCount=0;
(*cone)->ZeroRayCount=0;
(*cone)->EdgeCount=0;
(*cone)->TotalEdgeCount=0;
(*cone)->count_int=0;
(*cone)->count_int_good=0;
(*cone)->count_int_bad=0;
(*cone)->rseed=1; /* random seed for random row permutation */
dd_InitializeBmatrix((*cone)->d_alloc, &((*cone)->B));
dd_InitializeBmatrix((*cone)->d_alloc, &((*cone)->Bsave));
dd_InitializeAmatrix((*cone)->m_alloc,(*cone)->d_alloc,&((*cone)->A));
(*cone)->Edges
=(dd_AdjacencyType**) calloc((*cone)->m_alloc,sizeof(dd_AdjacencyType*));
(*cone)->InitialRayIndex=(long*)calloc(d+1,sizeof(long));
(*cone)->OrderVector=(long*)calloc((*cone)->m_alloc+1,sizeof(long));
(*cone)->newcol=(long*)calloc(((*cone)->d)+1,sizeof(long));
for (j=0; j<=(*cone)->d; j++) (*cone)->newcol[j]=j; /* identity map, initially */
(*cone)->LinearityDim = -2; /* -2 if it is not computed */
(*cone)->ColReduced = dd_FALSE;
(*cone)->d_orig = d;
/* STATES: variables to represent current state. */
/*(*cone)->Error;
(*cone)->CompStatus;
(*cone)->starttime;
(*cone)->endtime;
*/
return success;
}
dd_ConePtr dd_ConeDataLoad(dd_PolyhedraPtr poly)
{
dd_ConePtr cone=NULL;
dd_colrange d,j;
dd_rowrange m,i;
m=poly->m;
d=poly->d;
if (!(poly->homogeneous) && poly->representation==dd_Inequality){
m=poly->m+1;
}
poly->m1=m;
dd_InitializeConeData(m, d, &cone);
cone->representation=poly->representation;
/* Points to the original polyhedra data, and reversely */
cone->parent=poly;
poly->child=cone;
for (i=1; i<=poly->m; i++)
for (j=1; j<=cone->d; j++)
dd_set(cone->A[i-1][j-1],poly->A[i-1][j-1]);
if (poly->representation==dd_Inequality && !(poly->homogeneous)){
dd_set(cone->A[m-1][0],dd_one);
for (j=2; j<=d; j++) dd_set(cone->A[m-1][j-1],dd_purezero);
}
return cone;
}
void dd_SetLinearity(dd_MatrixPtr M, char *line)
{
int i=0;
dd_rowrange eqsize,var;
char *next;
const char ct[]=", "; /* allows separators "," and " ". */
next=strtok(line,ct);
eqsize=atol(next);
while (i < eqsize && (next=strtok(NULL,ct))!=NULL) {
var=atol(next);
set_addelem(M->linset,var); i++;
}
if (i!=eqsize) {
fprintf(stderr,"* Warning: there are inconsistencies in linearity setting.\n");
}
return;
}
dd_MatrixPtr dd_PolyFile2Matrix (FILE *f, dd_ErrorType *Error)
{
dd_MatrixPtr M=NULL;
dd_rowrange m_input,i;
dd_colrange d_input,j;
dd_RepresentationType rep=dd_Inequality;
mytype value;
dd_boolean found=dd_FALSE, linearity=dd_FALSE;
char command[dd_linelenmax], comsave[dd_linelenmax], numbtype[dd_wordlenmax];
dd_NumberType NT;
#if !defined(GMPRATIONAL)
double rvalue;
#endif
dd_init(value);
(*Error)=dd_NoError;
while (!found)
{
if (fscanf(f,"%s",command)==EOF) {
(*Error)=dd_ImproperInputFormat;
goto _L99;
}
else {
if (strncmp(command, "V-representation", 16)==0) {
rep=dd_Generator;
}
if (strncmp(command, "H-representation", 16)==0){
rep=dd_Inequality;
}
if (strncmp(command, "partial_enum", 12)==0 ||
strncmp(command, "equality", 8)==0 ||
strncmp(command, "linearity", 9)==0 ) {
linearity=dd_TRUE;
if(fgets(comsave,dd_linelenmax,f));
}
if (strncmp(command, "begin", 5)==0) found=dd_TRUE;
}
}
if(fscanf(f, "%ld %ld %s", &m_input, &d_input, numbtype));
fprintf(stderr,"size = %ld x %ld\nNumber Type = %s\n", m_input, d_input, numbtype);
NT=dd_GetNumberType(numbtype);
if (NT==dd_Unknown) {
(*Error)=dd_ImproperInputFormat;
goto _L99;
}
M=dd_CreateMatrix(m_input, d_input);
M->representation=rep;
M->numbtype=NT;
for (i = 1; i <= m_input; i++) {
for (j = 1; j <= d_input; j++) {
if (NT==dd_Real) {
#if defined GMPRATIONAL
*Error=dd_NoRealNumberSupport;
goto _L99;
#else
if(fscanf(f, "%lf", &rvalue));
dd_set_d(value, rvalue);
#endif
} else {
dd_fread_rational_value (f, value);
}
dd_set(M->matrix[i-1][j - 1],value);
if (dd_debug) {fprintf(stderr,"a(%3ld,%5ld) = ",i,j); dd_WriteNumber(stderr,value);}
} /*of j*/
} /*of i*/
if (fscanf(f,"%s",command)==EOF) {
(*Error)=dd_ImproperInputFormat;
goto _L99;
}
else if (strncmp(command, "end", 3)!=0) {
if (dd_debug) fprintf(stderr,"'end' missing or illegal extra data: %s\n",command);
(*Error)=dd_ImproperInputFormat;
goto _L99;
}
if (linearity) {
dd_SetLinearity(M,comsave);
}
while (!feof(f)) {
if(fscanf(f,"%s", command));
dd_ProcessCommandLine(f, M, command);
if(fgets(command,dd_linelenmax,f)); /* skip the CR/LF */
}
_L99: ;
dd_clear(value);
/* if (f!=NULL) fclose(f); */
return M;
}
dd_PolyhedraPtr dd_DDMatrix2Poly(dd_MatrixPtr M, dd_ErrorType *err)
{
dd_rowrange i;
dd_colrange j;
dd_PolyhedraPtr poly=NULL;
*err=dd_NoError;
if (M->rowsize<0 || M->colsize<0){
*err=dd_NegativeMatrixSize;
goto _L99;
}
poly=dd_CreatePolyhedraData(M->rowsize, M->colsize);
poly->representation=M->representation;
poly->homogeneous=dd_TRUE;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
poly->EqualityIndex[i]=1;
}
for (j = 1; j <= M->colsize; j++) {
dd_set(poly->A[i-1][j-1], M->matrix[i-1][j-1]);
if (j==1 && dd_Nonzero(M->matrix[i-1][j-1])) poly->homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
dd_DoubleDescription(poly,err);
_L99:
return poly;
}
dd_PolyhedraPtr dd_DDMatrix2Poly2(dd_MatrixPtr M, dd_RowOrderType horder, dd_ErrorType *err)
{
dd_rowrange i;
dd_colrange j;
dd_PolyhedraPtr poly=NULL;
*err=dd_NoError;
if (M->rowsize<0 || M->colsize<0){
*err=dd_NegativeMatrixSize;
goto _L99;
}
poly=dd_CreatePolyhedraData(M->rowsize, M->colsize);
poly->representation=M->representation;
poly->homogeneous=dd_TRUE;
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
poly->EqualityIndex[i]=1;
}
for (j = 1; j <= M->colsize; j++) {
dd_set(poly->A[i-1][j-1], M->matrix[i-1][j-1]);
if (j==1 && dd_Nonzero(M->matrix[i-1][j-1])) poly->homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
dd_DoubleDescription2(poly, horder, err);
_L99:
return poly;
}
void dd_MatrixIntegerFilter(dd_MatrixPtr M)
{ /* setting an almost integer to the integer. */
dd_rowrange i;
dd_colrange j;
mytype x;
dd_init(x);
for (i=0; i< M->rowsize; i++)
for (j=0; j< M->colsize; j++){
dd_SnapToInteger(x, M->matrix[i][j]);
dd_set(M->matrix[i][j],x);
}
dd_clear(x);
}
void dd_CopyRay(mytype *a, dd_colrange d_origsize, dd_RayPtr RR,
dd_RepresentationType rep, dd_colindex reducedcol)
{
long j,j1;
mytype b;
dd_init(b);
for (j = 1; j <= d_origsize; j++){
j1=reducedcol[j];
if (j1>0){
dd_set(a[j-1],RR->Ray[j1-1]);
/* the original column j is mapped to j1, and thus
copy the corresponding component */
} else {
dd_set(a[j-1],dd_purezero);
/* original column is redundant and removed for computation */
}
}
dd_set(b,a[0]);
if (rep==dd_Generator && dd_Nonzero(b)){
dd_set(a[0],dd_one);
for (j = 2; j <= d_origsize; j++)
dd_div(a[j-1],a[j-1],b); /* normalization for generators */
}
dd_clear(b);
}
void dd_WriteRay(FILE *f, dd_colrange d_origsize, dd_RayPtr RR, dd_RepresentationType rep, dd_colindex reducedcol)
{
dd_colrange j;
static dd_colrange d_last=0;
static dd_Arow a;
if (d_last< d_origsize){
if (d_last>0) free(a);
dd_InitializeArow(d_origsize+1, &a);
d_last=d_origsize+1;
}
dd_CopyRay(a, d_origsize, RR, rep, reducedcol);
for (j = 0; j < d_origsize; j++) dd_WriteNumber(f, a[j]);
fprintf(f, "\n");
}
void dd_WriteArow(FILE *f, dd_Arow a, dd_colrange d)
{
dd_colrange j;
for (j = 0; j < d; j++) dd_WriteNumber(f, a[j]);
fprintf(f, "\n");
}
void dd_WriteAmatrix(FILE *f, dd_Amatrix A, long rowmax, long colmax)
{
long i,j;
if (A==NULL){
fprintf(f, "WriteAmatrix: The requested matrix is empty\n");
goto _L99;
}
fprintf(f, "begin\n");
#if defined GMPRATIONAL
fprintf(f, " %ld %ld rational\n",rowmax, colmax);
#else
fprintf(f, " %ld %ld real\n",rowmax, colmax);
#endif
for (i=1; i <= rowmax; i++) {
for (j=1; j <= colmax; j++) {
dd_WriteNumber(f, A[i-1][j-1]);
}
fprintf(f,"\n");
}
fprintf(f, "end\n");
_L99:;
}
void dd_WriteBmatrix(FILE *f, dd_colrange d_size, dd_Bmatrix B)
{
dd_colrange j1, j2;
if (B==NULL){
fprintf(f, "WriteBmatrix: The requested matrix is empty\n");
goto _L99;
}
for (j1 = 0; j1 < d_size; j1++) {
for (j2 = 0; j2 < d_size; j2++) {
dd_WriteNumber(f, B[j1][j2]);
} /*of j2*/
putc('\n', f);
} /*of j1*/
putc('\n', f);
_L99:;
}
void dd_WriteSetFamily(FILE *f, dd_SetFamilyPtr F)
{
dd_bigrange i;
if (F==NULL){
fprintf(f, "WriteSetFamily: The requested family is empty\n");
goto _L99;
}
fprintf(f,"begin\n");
fprintf(f," %ld %ld\n", F->famsize, F->setsize);
for (i=0; ifamsize; i++) {
fprintf(f, " %ld %ld : ", i+1, set_card(F->set[i]));
set_fwrite(f, F->set[i]);
}
fprintf(f,"end\n");
_L99:;
}
void dd_WriteSetFamilyCompressed(FILE *f, dd_SetFamilyPtr F)
{
dd_bigrange i,card;
if (F==NULL){
fprintf(f, "WriteSetFamily: The requested family is empty\n");
goto _L99;
}
fprintf(f,"begin\n");
fprintf(f," %ld %ld\n", F->famsize, F->setsize);
for (i=0; ifamsize; i++) {
card=set_card(F->set[i]);
if (F->setsize - card >= card){
fprintf(f, " %ld %ld : ", i+1, card);
set_fwrite(f, F->set[i]);
} else {
fprintf(f, " %ld %ld : ", i+1, -card);
set_fwrite_compl(f, F->set[i]);
}
}
fprintf(f,"end\n");
_L99:;
}
void dd_WriteMatrix(FILE *f, dd_MatrixPtr M)
{
dd_rowrange i, linsize;
if (M==NULL){
fprintf(f, "WriteMatrix: The requested matrix is empty\n");
goto _L99;
}
switch (M->representation) {
case dd_Inequality:
fprintf(f, "H-representation\n"); break;
case dd_Generator:
fprintf(f, "V-representation\n"); break;
case dd_Unspecified:
break;
}
linsize=set_card(M->linset);
if (linsize>0) {
fprintf(f, "linearity %ld ", linsize);
for (i=1; i<=M->rowsize; i++)
if (set_member(i, M->linset)) fprintf(f, " %ld", i);
fprintf(f, "\n");
}
dd_WriteAmatrix(f, M->matrix, M->rowsize, M->colsize);
if (M->objective!=dd_LPnone){
if (M->objective==dd_LPmax)
fprintf(f, "maximize\n");
else
fprintf(f, "minimize\n");
dd_WriteArow(f, M->rowvec, M->colsize);
}
_L99:;
}
void dd_WriteLP(FILE *f, dd_LPPtr lp)
{
if (lp==NULL){
fprintf(f, "WriteLP: The requested lp is empty\n");
goto _L99;
}
fprintf(f, "H-representation\n");
dd_WriteAmatrix(f, lp->A, (lp->m)-1, lp->d);
if (lp->objective!=dd_LPnone){
if (lp->objective==dd_LPmax)
fprintf(f, "maximize\n");
else
fprintf(f, "minimize\n");
dd_WriteArow(f, lp->A[lp->objrow-1], lp->d);
}
_L99:;
}
void dd_SnapToInteger(mytype y, mytype x)
{
/* this is broken. It does nothing. */
dd_set(y,x);
}
void dd_WriteReal(FILE *f, mytype x)
{
long ix1,ix2,ix;
double ax;
ax=dd_get_d(x);
ix1= (long) (fabs(ax) * 10000. + 0.5);
ix2= (long) (fabs(ax) + 0.5);
ix2= ix2*10000;
if ( ix1 == ix2) {
if (dd_Positive(x)) {
ix = (long)(ax + 0.5);
} else {
ix = (long)(-ax + 0.5);
ix = -ix;
}
fprintf(f, " %2ld", ix);
} else
fprintf(f, " % .9E",ax);
}
void dd_WriteNumber(FILE *f, mytype x)
{
#if defined GMPRATIONAL
fprintf(f," ");
mpq_out_str(f, 10, x);
#else
dd_WriteReal(f, x);
#endif
}
void dd_WriteIncidence(FILE *f, dd_PolyhedraPtr poly)
{
dd_SetFamilyPtr I;
switch (poly->representation) {
case dd_Inequality:
fprintf(f, "ecd_file: Incidence of generators and inequalities\n");
break;
case dd_Generator:
fprintf(f, "icd_file: Incidence of inequalities and generators\n");
break;
default:
break;
}
I=dd_CopyIncidence(poly);
dd_WriteSetFamilyCompressed(f,I);
dd_FreeSetFamily(I);
}
void dd_WriteAdjacency(FILE *f, dd_PolyhedraPtr poly)
{
dd_SetFamilyPtr A;
switch (poly->representation) {
case dd_Inequality:
fprintf(f, "ead_file: Adjacency of generators\n");
break;
case dd_Generator:
fprintf(f, "iad_file: Adjacency of inequalities\n");
break;
default:
break;
}
A=dd_CopyAdjacency(poly);
dd_WriteSetFamilyCompressed(f,A);
dd_FreeSetFamily(A);
}
void dd_ComputeAinc(dd_PolyhedraPtr poly)
{
/* This generates the input incidence array poly->Ainc, and
two sets: poly->Ared, poly->Adom.
*/
dd_bigrange k;
dd_rowrange i,m1;
dd_colrange j;
dd_boolean redundant;
dd_MatrixPtr M=NULL;
mytype sum,temp;
dd_init(sum); dd_init(temp);
if (poly->AincGenerated==dd_TRUE) goto _L99;
M=dd_CopyOutput(poly);
poly->n=M->rowsize;
m1=poly->m1;
/* this number is same as poly->m, except when
poly is given by nonhomogeneous inequalty:
!(poly->homogeneous) && poly->representation==Inequality,
it is poly->m+1. See dd_ConeDataLoad.
*/
poly->Ainc=(set_type*)calloc(m1, sizeof(set_type));
for(i=1; i<=m1; i++) set_initialize(&(poly->Ainc[i-1]),poly->n);
set_initialize(&(poly->Ared), m1);
set_initialize(&(poly->Adom), m1);
for (k=1; k<=poly->n; k++){
for (i=1; i<=poly->m; i++){
dd_set(sum,dd_purezero);
for (j=1; j<=poly->d; j++){
dd_mul(temp,poly->A[i-1][j-1],M->matrix[k-1][j-1]);
dd_add(sum,sum,temp);
}
if (dd_EqualToZero(sum)) {
set_addelem(poly->Ainc[i-1], k);
}
}
if (!(poly->homogeneous) && poly->representation==dd_Inequality){
if (dd_EqualToZero(M->matrix[k-1][0])) {
set_addelem(poly->Ainc[m1-1], k); /* added infinity inequality (1,0,0,...,0) */
}
}
}
for (i=1; i<=m1; i++){
if (set_card(poly->Ainc[i-1])==M->rowsize){
set_addelem(poly->Adom, i);
}
}
for (i=m1; i>=1; i--){
if (set_card(poly->Ainc[i-1])==0){
redundant=dd_TRUE;
set_addelem(poly->Ared, i);
}else {
redundant=dd_FALSE;
for (k=1; k<=m1; k++) {
if (k!=i && !set_member(k, poly->Ared) && !set_member(k, poly->Adom) &&
set_subset(poly->Ainc[i-1], poly->Ainc[k-1])){
if (!redundant){
redundant=dd_TRUE;
}
set_addelem(poly->Ared, i);
}
}
}
}
dd_FreeMatrix(M);
poly->AincGenerated=dd_TRUE;
_L99:;
dd_clear(sum); dd_clear(temp);
}
dd_boolean dd_InputAdjacentQ(dd_PolyhedraPtr poly,
dd_rowrange i1, dd_rowrange i2)
/* Before calling this function, RedundantSet must be
a set of row indices whose removal results in a minimal
nonredundant system to represent the input polyhedron,
DominantSet must be the set of row indices which are
active at every extreme points/rays.
*/
{
dd_boolean adj=dd_TRUE;
dd_rowrange i;
static set_type common;
static long lastn=0;
if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
if (lastn!=poly->n){
if (lastn >0) set_free(common);
set_initialize(&common, poly->n);
lastn=poly->n;
}
if (set_member(i1, poly->Ared) || set_member(i2, poly->Ared)){
adj=dd_FALSE;
goto _L99;
}
if (set_member(i1, poly->Adom) || set_member(i2, poly->Adom)){
// dominant inequality is considered adjacencent to all others.
adj=dd_TRUE;
goto _L99;
}
set_int(common, poly->Ainc[i1-1], poly->Ainc[i2-1]);
i=0;
while (im1 && adj==dd_TRUE){
i++;
if (i!=i1 && i!=i2 && !set_member(i, poly->Ared) &&
!set_member(i, poly->Adom) && set_subset(common,poly->Ainc[i-1])){
adj=dd_FALSE;
}
}
_L99:;
return adj;
}
void dd_WriteInputIncidence(FILE *f, dd_PolyhedraPtr poly)
{
dd_SetFamilyPtr I;
if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
switch (poly->representation) {
case dd_Inequality:
fprintf(f,"icd_file: Incidence of inequalities and generators\n");
break;
case dd_Generator:
fprintf(f,"ecd_file: Incidence of generators and inequalities\n");
break;
default:
break;
}
I=dd_CopyInputIncidence(poly);
dd_WriteSetFamilyCompressed(f,I);
dd_FreeSetFamily(I);
}
void dd_WriteInputAdjacency(FILE *f, dd_PolyhedraPtr poly)
{
dd_SetFamilyPtr A;
if (poly->AincGenerated==dd_FALSE){
dd_ComputeAinc(poly);
}
switch (poly->representation) {
case dd_Inequality:
fprintf(f, "iad_file: Adjacency of inequalities\n");
break;
case dd_Generator:
fprintf(f, "ead_file: Adjacency of generators\n");
break;
default:
break;
}
A=dd_CopyInputAdjacency(poly);
dd_WriteSetFamilyCompressed(f,A);
dd_FreeSetFamily(A);
}
void dd_WriteProgramDescription(FILE *f)
{
fprintf(f, "* cddlib: a double description library:%s\n", dd_DDVERSION);
fprintf(f, "* compiled for %s arithmetic.\n", dd_ARITHMETIC);
fprintf(f,"* %s\n",dd_COPYRIGHT);
}
void dd_WriteTimes(FILE *f, time_t starttime, time_t endtime)
{
long ptime,ptime_sec,ptime_minu, ptime_hour;
/*
ptime=difftime(endtime,starttime);
This function is ANSI standard, but not available sometime
*/
ptime=(endtime - starttime);
/* This is to replace the line above, but it may not give
correct time in seconds */
ptime_hour=ptime/3600;
ptime_minu=(ptime-ptime_hour*3600)/60;
ptime_sec=ptime%60;
fprintf(f,"* Computation started at %s",asctime(localtime(&starttime)));
fprintf(f,"* ended at %s",asctime(localtime(&endtime)));
fprintf(f,"* Total processor time = %ld seconds\n",ptime);
fprintf(f,"* = %ld h %ld m %ld s\n",ptime_hour, ptime_minu, ptime_sec);
}
void dd_WriteDDTimes(FILE *f, dd_PolyhedraPtr poly)
{
dd_WriteTimes(f,poly->child->starttime,poly->child->endtime);
}
void dd_WriteLPTimes(FILE *f, dd_LPPtr lp)
{
dd_WriteTimes(f,lp->starttime,lp->endtime);
}
void dd_WriteLPStats(FILE *f)
{
time_t currenttime;
time(¤ttime);
fprintf(f, "\n*--- Statistics of pivots ---\n");
#if defined GMPRATIONAL
fprintf(f, "* f0 = %ld (float basis finding pivots)\n",ddf_statBApivots);
fprintf(f, "* fc = %ld (float CC pivots)\n",ddf_statCCpivots);
fprintf(f, "* f1 = %ld (float dual simplex phase I pivots)\n",ddf_statDS1pivots);
fprintf(f, "* f2 = %ld (float dual simplex phase II pivots)\n",ddf_statDS2pivots);
fprintf(f, "* f3 = %ld (float anticycling CC pivots)\n",ddf_statACpivots);
fprintf(f, "* e0 = %ld (exact basis finding pivots)\n",dd_statBApivots);
fprintf(f, "* ec = %ld (exact CC pivots)\n",dd_statCCpivots);
fprintf(f, "* e1 = %ld (exact dual simplex phase I pivots)\n",dd_statDS1pivots);
fprintf(f, "* e2 = %ld (exact dual simplex phase II pivots)\n",dd_statDS2pivots);
fprintf(f, "* e3 = %ld (exact anticycling CC pivots)\n",dd_statACpivots);
fprintf(f, "* e4 = %ld (exact basis verification pivots)\n",dd_statBSpivots);
#else
fprintf(f, "f0 = %ld (float basis finding pivots)\n",dd_statBApivots);
fprintf(f, "fc = %ld (float CC pivots)\n",dd_statCCpivots);
fprintf(f, "f1 = %ld (float dual simplex phase I pivots)\n",dd_statDS1pivots);
fprintf(f, "f2 = %ld (float dual simplex phase II pivots)\n",dd_statDS2pivots);
fprintf(f, "f3 = %ld (float anticycling CC pivots)\n",dd_statACpivots);
#endif
dd_WriteLPMode(f);
dd_WriteTimes(f,dd_statStartTime, currenttime);
}
void dd_WriteLPMode(FILE *f)
{
fprintf(f, "\n* LP solver: ");
switch (dd_choiceLPSolverDefault) {
case dd_DualSimplex:
fprintf(f, "DualSimplex\n");
break;
case dd_CrissCross:
fprintf(f, "Criss-Cross\n");
break;
default: break;
}
fprintf(f, "* Redundancy cheking solver: ");
switch (dd_choiceRedcheckAlgorithm) {
case dd_DualSimplex:
fprintf(f, "DualSimplex\n");
break;
case dd_CrissCross:
fprintf(f, "Criss-Cross\n");
break;
default: break;
}
fprintf(f, "* Lexicographic pivot: ");
if (dd_choiceLexicoPivotQ) fprintf(f, " on\n");
else fprintf(f, " off\n");
}
void dd_WriteRunningMode(FILE *f, dd_PolyhedraPtr poly)
{
if (poly->child!=NULL){
fprintf(f,"* roworder: ");
switch (poly->child->HalfspaceOrder) {
case dd_MinIndex:
fprintf(f, "minindex\n");
break;
case dd_MaxIndex:
fprintf(f, "maxindex\n");
break;
case dd_MinCutoff:
fprintf(f, "mincutoff\n");
break;
case dd_MaxCutoff:
fprintf(f, "maxcutoff\n");
break;
case dd_MixCutoff:
fprintf(f, "mixcutoff\n");
break;
case dd_LexMin:
fprintf(f, "lexmin\n");
break;
case dd_LexMax:
fprintf(f, "lexmax\n");
break;
case dd_RandomRow:
fprintf(f, "random %d\n",poly->child->rseed);
break;
default: break;
}
}
}
void dd_WriteCompletionStatus(FILE *f, dd_ConePtr cone)
{
if (cone->Iterationm && cone->CompStatus==dd_AllFound) {
fprintf(f,"*Computation completed at Iteration %4ld.\n", cone->Iteration);
}
if (cone->CompStatus == dd_RegionEmpty) {
fprintf(f,"*Computation completed at Iteration %4ld because the region found empty.\n",cone->Iteration);
}
}
void dd_WritePolyFile(FILE *f, dd_PolyhedraPtr poly)
{
dd_WriteAmatrix(f,poly->A,poly->m,poly->d);
}
void dd_WriteErrorMessages(FILE *f, dd_ErrorType Error)
{
switch (Error) {
case dd_DimensionTooLarge:
fprintf(f, "*Input Error: Input matrix is too large:\n");
fprintf(f, "*Please increase MMAX and/or NMAX in the source code and recompile.\n");
break;
case dd_IFileNotFound:
fprintf(f, "*Input Error: Specified input file does not exist.\n");
break;
case dd_OFileNotOpen:
fprintf(f, "*Output Error: Specified output file cannot be opened.\n");
break;
case dd_NegativeMatrixSize:
fprintf(f, "*Input Error: Input matrix has a negative size:\n");
fprintf(f, "*Please check rowsize or colsize.\n");
break;
case dd_ImproperInputFormat:
fprintf(f,"*Input Error: Input format is not correct.\n");
fprintf(f,"*Format:\n");
fprintf(f," begin\n");
fprintf(f," m n NumberType(real, rational or integer)\n");
fprintf(f," b -A\n");
fprintf(f," end\n");
break;
case dd_EmptyVrepresentation:
fprintf(f, "*Input Error: V-representation is empty:\n");
fprintf(f, "*cddlib does not accept this trivial case for which output can be any inconsistent system.\n");
break;
case dd_EmptyHrepresentation:
fprintf(f, "*Input Error: H-representation is empty.\n");
break;
case dd_EmptyRepresentation:
fprintf(f, "*Input Error: Representation is empty.\n");
break;
case dd_NoLPObjective:
fprintf(f, "*LP Error: No LP objective (max or min) is set.\n");
break;
case dd_NoRealNumberSupport:
fprintf(f, "*LP Error: The binary (with GMP Rational) does not support Real number input.\n");
fprintf(f, " : Use a binary compiled without -DGMPRATIONAL option.\n");
break;
case dd_NotAvailForH:
fprintf(f, "*Error: A function is called with H-rep which does not support an H-representation.\n");
break;
case dd_NotAvailForV:
fprintf(f, "*Error: A function is called with V-rep which does not support an V-representation.\n");
break;
case dd_CannotHandleLinearity:
fprintf(f, "*Error: The function called cannot handle linearity.\n");
break;
case dd_RowIndexOutOfRange:
fprintf(f, "*Error: Specified row index is out of range\n");
break;
case dd_ColIndexOutOfRange:
fprintf(f, "*Error: Specified column index is out of range\n");
break;
case dd_LPCycling:
fprintf(f, "*Error: Possibly an LP cycling occurs. Use the Criss-Cross method.\n");
break;
case dd_NumericallyInconsistent:
fprintf(f, "*Error: Numerical inconsistency is found. Use the GMP exact arithmetic.\n");
break;
case dd_NoError:
fprintf(f,"*No Error found.\n");
break;
}
}
dd_SetFamilyPtr dd_CopyIncidence(dd_PolyhedraPtr poly)
{
dd_SetFamilyPtr F=NULL;
dd_bigrange k;
dd_rowrange i;
if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) goto _L99;
if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
F=dd_CreateSetFamily(poly->n, poly->m1);
for (i=1; i<=poly->m1; i++)
for (k=1; k<=poly->n; k++)
if (set_member(k,poly->Ainc[i-1])) set_addelem(F->set[k-1],i);
_L99:;
return F;
}
dd_SetFamilyPtr dd_CopyInputIncidence(dd_PolyhedraPtr poly)
{
dd_rowrange i;
dd_SetFamilyPtr F=NULL;
if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) goto _L99;
if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
F=dd_CreateSetFamily(poly->m1, poly->n);
for(i=0; i< poly->m1; i++){
set_copy(F->set[i], poly->Ainc[i]);
}
_L99:;
return F;
}
dd_SetFamilyPtr dd_CopyAdjacency(dd_PolyhedraPtr poly)
{
dd_RayPtr RayPtr1,RayPtr2;
dd_SetFamilyPtr F=NULL;
long pos1, pos2;
dd_bigrange lstart,k,n;
set_type linset,allset;
dd_boolean adj;
if (poly->n==0 && poly->homogeneous && poly->representation==dd_Inequality){
n=1; /* the origin (the unique vertex) should be output. */
} else n=poly->n;
set_initialize(&linset, n);
set_initialize(&allset, n);
if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) goto _L99;
F=dd_CreateSetFamily(n, n);
if (n<=0) goto _L99;
poly->child->LastRay->Next=NULL;
for (RayPtr1=poly->child->FirstRay, pos1=1;RayPtr1 != NULL;
RayPtr1 = RayPtr1->Next, pos1++){
for (RayPtr2=poly->child->FirstRay, pos2=1; RayPtr2 != NULL;
RayPtr2 = RayPtr2->Next, pos2++){
if (RayPtr1!=RayPtr2){
dd_CheckAdjacency(poly->child, &RayPtr1, &RayPtr2, &adj);
if (adj){
set_addelem(F->set[pos1-1], pos2);
}
}
}
}
lstart=poly->n - poly->ldim + 1;
set_compl(allset,allset); /* allset is set to the ground set. */
for (k=lstart; k<=poly->n; k++){
set_addelem(linset,k); /* linearity set */
set_copy(F->set[k-1],allset); /* linearity generator is adjacent to all */
}
for (k=1; kset[k-1],F->set[k-1],linset);
/* every generator is adjacent to all linearity generators */
}
_L99:;
set_free(allset); set_free(linset);
return F;
}
dd_SetFamilyPtr dd_CopyInputAdjacency(dd_PolyhedraPtr poly)
{
dd_rowrange i,j;
dd_SetFamilyPtr F=NULL;
if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) goto _L99;
if (poly->AincGenerated==dd_FALSE) dd_ComputeAinc(poly);
F=dd_CreateSetFamily(poly->m1, poly->m1);
for (i=1; i<=poly->m1; i++){
for (j=1; j<=poly->m1; j++){
if (i!=j && dd_InputAdjacentQ(poly, i, j)) {
set_addelem(F->set[i-1],j);
}
}
}
_L99:;
return F;
}
dd_MatrixPtr dd_CopyOutput(dd_PolyhedraPtr poly)
{
dd_RayPtr RayPtr;
dd_MatrixPtr M=NULL;
dd_rowrange i=0,total;
dd_colrange j,j1;
mytype b;
dd_RepresentationType outputrep=dd_Inequality;
dd_boolean outputorigin=dd_FALSE;
dd_init(b);
total=poly->child->LinearityDim + poly->child->FeasibleRayCount;
if (poly->child->d<=0 || poly->child->newcol[1]==0) total=total-1;
if (poly->representation==dd_Inequality) outputrep=dd_Generator;
if (total==0 && poly->homogeneous && poly->representation==dd_Inequality){
total=1;
outputorigin=dd_TRUE;
/* the origin (the unique vertex) should be output. */
}
if (poly->child==NULL || poly->child->CompStatus!=dd_AllFound) goto _L99;
M=dd_CreateMatrix(total, poly->d);
RayPtr = poly->child->FirstRay;
while (RayPtr != NULL) {
if (RayPtr->feasible) {
dd_CopyRay(M->matrix[i], poly->d, RayPtr, outputrep, poly->child->newcol);
i++; /* 086 */
}
RayPtr = RayPtr->Next;
}
for (j=2; j<=poly->d; j++){
if (poly->child->newcol[j]==0){
/* original column j is dependent on others and removed for the cone */
dd_set(b,poly->child->Bsave[0][j-1]);
if (outputrep==dd_Generator && dd_Positive(b)){
dd_set(M->matrix[i][0],dd_one); /* dd_Normalize */
for (j1=1; j1d; j1++)
dd_div(M->matrix[i][j1],(poly->child->Bsave[j1][j-1]),b);
} else {
for (j1=0; j1d; j1++)
dd_set(M->matrix[i][j1],poly->child->Bsave[j1][j-1]);
}
set_addelem(M->linset, i+1);
i++;
}
}
if (outputorigin){
/* output the origin for homogeneous H-polyhedron with no rays. */
dd_set(M->matrix[0][0],dd_one);
for (j=1; jd; j++){
dd_set(M->matrix[0][j],dd_purezero);
}
}
dd_MatrixIntegerFilter(M);
if (poly->representation==dd_Inequality)
M->representation=dd_Generator;
else
M->representation=dd_Inequality;
_L99:;
dd_clear(b);
return M;
}
dd_MatrixPtr dd_CopyInput(dd_PolyhedraPtr poly)
{
dd_MatrixPtr M=NULL;
dd_rowrange i;
M=dd_CreateMatrix(poly->m, poly->d);
dd_CopyAmatrix(M->matrix, poly->A, poly->m, poly->d);
for (i=1; i<=poly->m; i++)
if (poly->EqualityIndex[i]==1) set_addelem(M->linset,i);
dd_MatrixIntegerFilter(M);
if (poly->representation==dd_Generator)
M->representation=dd_Generator;
else
M->representation=dd_Inequality;
return M;
}
dd_MatrixPtr dd_CopyGenerators(dd_PolyhedraPtr poly)
{
dd_MatrixPtr M=NULL;
if (poly->representation==dd_Generator){
M=dd_CopyInput(poly);
} else {
M=dd_CopyOutput(poly);
}
return M;
}
dd_MatrixPtr dd_CopyInequalities(dd_PolyhedraPtr poly)
{
dd_MatrixPtr M=NULL;
if (poly->representation==dd_Inequality){
M=dd_CopyInput(poly);
} else {
M=dd_CopyOutput(poly);
}
return M;
}
/****************************************************************************************/
/* rational number (a/b) read is taken from Vinci by Benno Bueeler and Andreas Enge */
/****************************************************************************************/
void dd_sread_rational_value (char *s, mytype value)
/* reads a rational value from the specified string "s" and assigns it to "value" */
{
char *numerator_s=NULL, *denominator_s=NULL, *position;
int sign = 1;
double numerator, denominator;
#if defined GMPRATIONAL
mpz_t znum, zden;
#else
double rvalue;
#endif
/* determine the sign of the number */
numerator_s = s;
if (s [0] == '-')
{ sign = -1;
numerator_s++;
}
else if (s [0] == '+')
numerator_s++;
/* look for a sign '/' and eventually split the number in numerator and denominator */
position = strchr (numerator_s, '/');
if (position != NULL)
{ *position = '\0'; /* terminates the numerator */
denominator_s = position + 1;
};
/* determine the floating point values of numerator and denominator */
numerator=atol (numerator_s);
if (position != NULL)
{
denominator=atol (denominator_s);
}
else denominator = 1;
/*
fprintf(stderr,"\nrational_read: numerator %f\n",numerator);
fprintf(stderr,"rational_read: denominator %f\n",denominator);
fprintf(stderr,"rational_read: sign %d\n",sign);
*/
#if defined GMPRATIONAL
mpz_init_set_str(znum,numerator_s,10);
if (sign<0) mpz_neg(znum,znum);
mpz_init(zden); mpz_set_ui(zden,1);
if (denominator_s!=NULL) mpz_init_set_str(zden,denominator_s,10);
mpq_set_num(value,znum); mpq_set_den(value,zden);
mpq_canonicalize(value);
mpz_clear(znum); mpz_clear(zden);
/* num=(long)sign * numerator; */
/* den=(unsigned long) denominator; */
/* mpq_set_si(value, num, den); */
#elif defined GMPFLOAT
rvalue=sign * numerator/ (signed long) denominator;
mpf_set_d(value, rvalue);
#else
rvalue=sign * numerator/ (signed long) denominator;
ddd_set_d(value, rvalue);
#endif
if (dd_debug) {
fprintf(stderr,"rational_read: ");
dd_WriteNumber(stderr,value); fprintf(stderr,"\n");
}
}
void dd_fread_rational_value (FILE *f, mytype value)
/* reads a rational value from the specified file "f" and assigns it to "value" */
{
char number_s [dd_wordlenmax];
mytype rational_value;
dd_init(rational_value);
if(fscanf(f, "%s ", number_s));
dd_sread_rational_value (number_s, rational_value);
dd_set(value,rational_value);
dd_clear(rational_value);
}
/****************************************************************************************/
/* end of cddio.c */
pplacer-1.1.alpha19/cdd_src/cddlib.c 0000664 0000000 0000000 00000026431 13031546015 0017231 0 ustar 00root root 0000000 0000000 /* cddlib.c: cdd library (library version of cdd)
written by Komei Fukuda, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
Standard ftp site: ftp.ifor.math.ethz.ch, Directory: pub/fukuda/cdd
*/
/* cdd : C-Implementation of the double description method for
computing all vertices and extreme rays of the polyhedron
P= {x : b - A x >= 0}.
Please read COPYING (GNU General Public Licence) and
the manual cddlibman.tex for detail.
*/
/* 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 of the License, or
(at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* The first version C0.21 was created on November 10,1993
with Dave Gillespie's p2c translator
from the Pascal program pdd.p written by Komei Fukuda.
*/
#include "setoper.h"
/* set operation library header (Ver. June 1, 2000 or later) */
#include "cdd.h"
#include
#include
#include
#include
#include
/* Global Variables */
dd_boolean dd_debug =dd_FALSE;
dd_boolean dd_log =dd_FALSE;
/* GLOBAL CONSTANTS and STATICS VARIABLES (to be set by dd_set_global_constants() */
mytype dd_zero;
mytype dd_one;
mytype dd_purezero;
mytype dd_minuszero;
mytype dd_minusone;
time_t dd_statStartTime; /* cddlib starting time */
long dd_statBApivots; /* basis finding pivots */
long dd_statCCpivots; /* criss-cross pivots */
long dd_statDS1pivots; /* phase 1 pivots */
long dd_statDS2pivots; /* phase 2 pivots */
long dd_statACpivots; /* anticycling (cc) pivots */
#ifdef GMPRATIONAL
long dd_statBSpivots; /* basis status checking pivots */
#endif
dd_LPSolverType dd_choiceLPSolverDefault; /* Default LP solver Algorithm */
dd_LPSolverType dd_choiceRedcheckAlgorithm; /* Redundancy Checking Algorithm */
dd_boolean dd_choiceLexicoPivotQ; /* whether to use the lexicographic pivot */
/* #include THINK C PROFILER */
/* #include THINK C PROFILER */
void dd_DDInit(dd_ConePtr cone)
{
cone->Error=dd_NoError;
cone->CompStatus=dd_InProgress;
cone->RayCount = 0;
cone->TotalRayCount = 0;
cone->FeasibleRayCount = 0;
cone->WeaklyFeasibleRayCount = 0;
cone->EdgeCount=0; /* active edge count */
cone->TotalEdgeCount=0; /* active edge count */
dd_SetInequalitySets(cone);
dd_ComputeRowOrderVector(cone);
cone->RecomputeRowOrder=dd_FALSE;
}
void dd_DDMain(dd_ConePtr cone)
{
dd_rowrange hh, itemp, otemp;
dd_boolean locallog=dd_log; /* if dd_log=dd_FALSE, no log will be written. */
if (cone->d<=0){
cone->Iteration=cone->m;
cone->FeasibleRayCount=0;
cone->CompStatus=dd_AllFound;
goto _L99;
}
if (locallog) {
fprintf(stderr,"(Initially added rows ) = ");
set_fwrite(stderr,cone->InitialHalfspaces);
}
while (cone->Iteration <= cone->m) {
dd_SelectNextHalfspace(cone, cone->WeaklyAddedHalfspaces, &hh);
if (set_member(hh,cone->NonequalitySet)){ /* Skip the row hh */
if (dd_debug) {
fprintf(stderr,"*The row # %3ld should be inactive and thus skipped.\n", hh);
}
set_addelem(cone->WeaklyAddedHalfspaces, hh);
} else {
if (cone->PreOrderedRun)
dd_AddNewHalfspace2(cone, hh);
else{
dd_AddNewHalfspace1(cone, hh);
}
set_addelem(cone->AddedHalfspaces, hh);
set_addelem(cone->WeaklyAddedHalfspaces, hh);
}
if (!cone->PreOrderedRun){
for (itemp=1; cone->OrderVector[itemp]!=hh; itemp++);
otemp=cone->OrderVector[cone->Iteration];
cone->OrderVector[cone->Iteration]=hh;
/* store the dynamic ordering in ordervec */
cone->OrderVector[itemp]=otemp;
/* store the dynamic ordering in ordervec */
}
if (locallog){
fprintf(stderr,"(Iter, Row, #Total, #Curr, #Feas)= %5ld %5ld %9ld %6ld %6ld\n",
cone->Iteration, hh, cone->TotalRayCount, cone->RayCount,
cone->FeasibleRayCount);
}
if (cone->CompStatus==dd_AllFound||cone->CompStatus==dd_RegionEmpty) {
set_addelem(cone->AddedHalfspaces, hh);
goto _L99;
}
(cone->Iteration)++;
}
_L99:;
if (cone->d<=0 || cone->newcol[1]==0){ /* fixing the number of output */
cone->parent->n=cone->LinearityDim + cone->FeasibleRayCount -1;
cone->parent->ldim=cone->LinearityDim - 1;
} else {
cone->parent->n=cone->LinearityDim + cone->FeasibleRayCount;
cone->parent->ldim=cone->LinearityDim;
}
}
void dd_InitialDataSetup(dd_ConePtr cone)
{
long j, r;
dd_rowset ZSet;
static dd_Arow Vector1,Vector2;
static dd_colrange last_d=0;
if (last_d < cone->d){
if (last_d>0) {
for (j=0; jd,sizeof(mytype));
Vector2=(mytype*)calloc(cone->d,sizeof(mytype));
for (j=0; jd; j++){
dd_init(Vector1[j]);
dd_init(Vector2[j]);
}
last_d=cone->d;
}
cone->RecomputeRowOrder=dd_FALSE;
cone->ArtificialRay = NULL;
cone->FirstRay = NULL;
cone->LastRay = NULL;
set_initialize(&ZSet,cone->m);
dd_AddArtificialRay(cone);
set_copy(cone->AddedHalfspaces, cone->InitialHalfspaces);
set_copy(cone->WeaklyAddedHalfspaces, cone->InitialHalfspaces);
dd_UpdateRowOrderVector(cone, cone->InitialHalfspaces);
for (r = 1; r <= cone->d; r++) {
for (j = 0; j < cone->d; j++){
dd_set(Vector1[j], cone->B[j][r-1]);
dd_neg(Vector2[j], cone->B[j][r-1]);
}
dd_Normalize(cone->d, Vector1);
dd_Normalize(cone->d, Vector2);
dd_ZeroIndexSet(cone->m, cone->d, cone->A, Vector1, ZSet);
if (set_subset(cone->EqualitySet, ZSet)){
if (dd_debug) {
fprintf(stderr,"add an initial ray with zero set:");
set_fwrite(stderr,ZSet);
}
dd_AddRay(cone, Vector1);
if (cone->InitialRayIndex[r]==0) {
dd_AddRay(cone, Vector2);
if (dd_debug) {
fprintf(stderr,"and add its negative also.\n");
}
}
}
}
dd_CreateInitialEdges(cone);
cone->Iteration = cone->d + 1;
if (cone->Iteration > cone->m) cone->CompStatus=dd_AllFound; /* 0.94b */
set_free(ZSet);
}
dd_boolean dd_CheckEmptiness(dd_PolyhedraPtr poly, dd_ErrorType *err)
{
dd_rowset R, S;
dd_MatrixPtr M=NULL;
dd_boolean answer=dd_FALSE;
*err=dd_NoError;
if (poly->representation==dd_Inequality){
M=dd_CopyInequalities(poly);
set_initialize(&R, M->rowsize);
set_initialize(&S, M->rowsize);
if (!dd_ExistsRestrictedFace(M, R, S, err)){
poly->child->CompStatus=dd_AllFound;
poly->IsEmpty=dd_TRUE;
poly->n=0;
answer=dd_TRUE;
}
set_free(R);
set_free(S);
dd_FreeMatrix(M);
} else if (poly->representation==dd_Generator && poly->m<=0){
*err=dd_EmptyVrepresentation;
poly->IsEmpty=dd_TRUE;
poly->child->CompStatus=dd_AllFound;
answer=dd_TRUE;
poly->child->Error=*err;
}
return answer;
}
dd_boolean dd_DoubleDescription(dd_PolyhedraPtr poly, dd_ErrorType *err)
{
dd_ConePtr cone=NULL;
dd_boolean found=dd_FALSE;
*err=dd_NoError;
if (poly!=NULL && (poly->child==NULL || poly->child->CompStatus!=dd_AllFound)){
cone=dd_ConeDataLoad(poly);
/* create a cone associated with poly by homogenization */
time(&cone->starttime);
dd_DDInit(cone);
if (poly->representation==dd_Generator && poly->m<=0){
*err=dd_EmptyVrepresentation;
cone->Error=*err;
goto _L99;
}
/* Check emptiness of the polyhedron */
dd_CheckEmptiness(poly,err);
if (cone->CompStatus!=dd_AllFound){
dd_FindInitialRays(cone, &found);
if (found) {
dd_InitialDataSetup(cone);
if (cone->CompStatus==dd_AllFound) goto _L99;
dd_DDMain(cone);
if (cone->FeasibleRayCount!=cone->RayCount) *err=dd_NumericallyInconsistent; /* cddlib-093d */
}
}
time(&cone->endtime);
}
_L99: ;
return found;
}
dd_boolean dd_DoubleDescription2(dd_PolyhedraPtr poly, dd_RowOrderType horder, dd_ErrorType *err)
{
dd_ConePtr cone=NULL;
dd_boolean found=dd_FALSE;
*err=dd_NoError;
if (poly!=NULL && (poly->child==NULL || poly->child->CompStatus!=dd_AllFound)){
cone=dd_ConeDataLoad(poly);
/* create a cone associated with poly by homogenization */
cone->HalfspaceOrder=horder; /* set the row order */
time(&cone->starttime);
dd_DDInit(cone);
if (poly->representation==dd_Generator && poly->m<=0){
*err=dd_EmptyVrepresentation;
cone->Error=*err;
goto _L99;
}
/* Check emptiness of the polyhedron */
dd_CheckEmptiness(poly,err);
if (cone->CompStatus!=dd_AllFound){
dd_FindInitialRays(cone, &found);
if (found) {
dd_InitialDataSetup(cone);
if (cone->CompStatus==dd_AllFound) goto _L99;
dd_DDMain(cone);
if (cone->FeasibleRayCount!=cone->RayCount) *err=dd_NumericallyInconsistent; /* cddlib-093d */
}
}
time(&cone->endtime);
}
_L99: ;
return found;
}
dd_boolean dd_DDInputAppend(dd_PolyhedraPtr *poly, dd_MatrixPtr M,
dd_ErrorType *err)
{
/* This is imcomplete. It simply solves the problem from scratch. */
dd_boolean found;
dd_ErrorType error;
if ((*poly)->child!=NULL) dd_FreeDDMemory(*poly);
dd_AppendMatrix2Poly(poly, M);
(*poly)->representation=dd_Inequality;
found=dd_DoubleDescription(*poly, &error);
*err=error;
return found;
}
dd_boolean dd_DDFile2File(char *ifile, char *ofile, dd_ErrorType *err)
{
/* The representation conversion from an input file to an outfile. */
/* modified by D. Avis to allow stdin/stdout */
dd_boolean found=dd_TRUE;
FILE *reading=NULL,*writing=NULL;
dd_PolyhedraPtr poly;
dd_MatrixPtr M, A, G;
if (strcmp(ifile,"**stdin") == 0 )
reading = stdin;
else if ( ( reading = fopen(ifile, "r") )!= NULL) {
fprintf(stderr,"input file %s is open\n", ifile);
}
else{
fprintf(stderr,"The input file %s not found\n",ifile);
found=dd_FALSE;
*err=dd_IFileNotFound;
goto _L99;
}
if (found){
if (strcmp(ofile,"**stdout") == 0 )
writing = stdout;
else if ( (writing = fopen(ofile, "w") ) != NULL){
fprintf(stderr,"output file %s is open\n",ofile);
found=dd_TRUE;
} else {
fprintf(stderr,"The output file %s cannot be opened\n",ofile);
found=dd_FALSE;
*err=dd_OFileNotOpen;
goto _L99;
}
}
M=dd_PolyFile2Matrix(reading, err);
if (*err!=dd_NoError){
goto _L99;
} poly=dd_DDMatrix2Poly(M, err); /* compute the second representation */ dd_FreeMatrix(M);
if (*err==dd_NoError) {
dd_WriteRunningMode(writing, poly);
A=dd_CopyInequalities(poly);
G=dd_CopyGenerators(poly);
if (poly->representation==dd_Inequality) {
dd_WriteMatrix(writing,G);
} else {
dd_WriteMatrix(writing,A);
}
dd_FreePolyhedra(poly);
dd_FreeMatrix(A);
dd_FreeMatrix(G);
}
_L99: ;
if (*err!=dd_NoError) dd_WriteErrorMessages(stderr,*err);
if (reading!=NULL) fclose(reading);
if (writing!=NULL) fclose(writing);
return found;
}
/* end of cddlib.c */
pplacer-1.1.alpha19/cdd_src/cddlp.c 0000664 0000000 0000000 00000360341 13031546015 0017077 0 ustar 00root root 0000000 0000000 /* cddlp.c: dual simplex method c-code
written by Komei Fukuda, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* cddlp.c : C-Implementation of the dual simplex method for
solving an LP: max/min A_(m-1).x subject to x in P, where
P= {x : A_i.x >= 0, i=0,...,m-2, and x_0=1}, and
A_i is the i-th row of an m x n matrix A.
Please read COPYING (GNU General Public Licence) and
the manual cddlibman.tex for detail.
*/
#include "setoper.h" /* set operation library header (Ver. May 18, 2000 or later) */
#include "cdd.h"
#include
#include
#include
#include
#include
#if defined GMPRATIONAL
#include "cdd_f.h"
#endif
#define dd_CDDLPVERSION "Version 0.94b (August 25, 2005)"
#define dd_FALSE 0
#define dd_TRUE 1
typedef set_type rowset; /* set_type defined in setoper.h */
typedef set_type colset;
void dd_CrissCrossSolve(dd_LPPtr lp,dd_ErrorType *);
void dd_DualSimplexSolve(dd_LPPtr lp,dd_ErrorType *);
void dd_CrissCrossMinimize(dd_LPPtr,dd_ErrorType *);
void dd_CrissCrossMaximize(dd_LPPtr,dd_ErrorType *);
void dd_DualSimplexMinimize(dd_LPPtr,dd_ErrorType *);
void dd_DualSimplexMaximize(dd_LPPtr,dd_ErrorType *);
void dd_FindLPBasis(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowindex,dd_rowset,
dd_colindex,dd_rowindex,dd_rowrange,dd_colrange,
dd_colrange *,int *,dd_LPStatusType *,long *);
void dd_FindDualFeasibleBasis(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowindex,
dd_colindex,long *,dd_rowrange,dd_colrange,dd_boolean,
dd_colrange *,dd_ErrorType *,dd_LPStatusType *,long *, long maxpivots);
#ifdef GMPRATIONAL
void dd_BasisStatus(ddf_LPPtr lpf, dd_LPPtr lp, dd_boolean*);
void dd_BasisStatusMinimize(dd_rowrange,dd_colrange, dd_Amatrix,dd_Bmatrix,dd_rowset,
dd_rowrange,dd_colrange,ddf_LPStatusType,mytype *,dd_Arow,dd_Arow,dd_rowset,ddf_colindex,
ddf_rowrange,ddf_colrange,dd_colrange *,long *, int *, int *);
void dd_BasisStatusMaximize(dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,dd_rowset,
dd_rowrange,dd_colrange,ddf_LPStatusType,mytype *,dd_Arow,dd_Arow,dd_rowset,ddf_colindex,
ddf_rowrange,ddf_colrange,dd_colrange *,long *, int *, int *);
#endif
void dd_WriteBmatrix(FILE *f,dd_colrange d_size,dd_Bmatrix T);
void dd_SetNumberType(char *line,dd_NumberType *number,dd_ErrorType *Error);
void dd_ComputeRowOrderVector2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,
dd_rowindex OV,dd_RowOrderType ho,unsigned int rseed);
void dd_SelectPreorderedNext2(dd_rowrange m_size,dd_colrange d_size,
rowset excluded,dd_rowindex OV,dd_rowrange *hnext);
void dd_SetSolutions(dd_rowrange,dd_colrange,
dd_Amatrix,dd_Bmatrix,dd_rowrange,dd_colrange,dd_LPStatusType,
mytype *,dd_Arow,dd_Arow,dd_rowset,dd_colindex,dd_rowrange,dd_colrange,dd_rowindex);
void dd_WriteTableau(FILE *,dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,
dd_colindex,dd_rowindex);
void dd_WriteSignTableau(FILE *,dd_rowrange,dd_colrange,dd_Amatrix,dd_Bmatrix,
dd_colindex,dd_rowindex);
dd_LPSolutionPtr dd_CopyLPSolution(dd_LPPtr lp)
{
dd_LPSolutionPtr lps;
dd_colrange j;
long i;
lps=(dd_LPSolutionPtr) calloc(1,sizeof(dd_LPSolutionType));
for (i=1; i<=dd_filenamelen; i++) lps->filename[i-1]=lp->filename[i-1];
lps->objective=lp->objective;
lps->solver=lp->solver;
lps->m=lp->m;
lps->d=lp->d;
lps->numbtype=lp->numbtype;
lps->LPS=lp->LPS; /* the current solution status */
dd_init(lps->optvalue);
dd_set(lps->optvalue,lp->optvalue); /* optimal value */
dd_InitializeArow(lp->d+1,&(lps->sol));
dd_InitializeArow(lp->d+1,&(lps->dsol));
lps->nbindex=(long*) calloc((lp->d)+1,sizeof(long)); /* dual solution */
for (j=0; j<=lp->d; j++){
dd_set(lps->sol[j],lp->sol[j]);
dd_set(lps->dsol[j],lp->dsol[j]);
lps->nbindex[j]=lp->nbindex[j];
}
lps->pivots[0]=lp->pivots[0];
lps->pivots[1]=lp->pivots[1];
lps->pivots[2]=lp->pivots[2];
lps->pivots[3]=lp->pivots[3];
lps->pivots[4]=lp->pivots[4];
lps->total_pivots=lp->total_pivots;
return lps;
}
dd_LPPtr dd_CreateLPData(dd_LPObjectiveType obj,
dd_NumberType nt,dd_rowrange m,dd_colrange d)
{
dd_LPType *lp;
lp=(dd_LPPtr) calloc(1,sizeof(dd_LPType));
lp->solver=dd_choiceLPSolverDefault; /* set the default lp solver */
lp->d=d;
lp->m=m;
lp->numbtype=nt;
lp->objrow=m;
lp->rhscol=1L;
lp->objective=dd_LPnone;
lp->LPS=dd_LPSundecided;
lp->eqnumber=0; /* the number of equalities */
lp->nbindex=(long*) calloc(d+1,sizeof(long));
lp->given_nbindex=(long*) calloc(d+1,sizeof(long));
set_initialize(&(lp->equalityset),m);
/* i must be in the set iff i-th row is equality . */
lp->redcheck_extensive=dd_FALSE; /* this is on only for RedundantExtensive */
lp->ired=0;
set_initialize(&(lp->redset_extra),m);
/* i is in the set if i-th row is newly recognized redundant (during the checking the row ired). */
set_initialize(&(lp->redset_accum),m);
/* i is in the set if i-th row is recognized redundant (during the checking the row ired). */
set_initialize(&(lp->posset_extra),m);
/* i is in the set if i-th row is recognized non-linearity (during the course of computation). */
lp->lexicopivot=dd_choiceLexicoPivotQ; /* dd_choice... is set in dd_set_global_constants() */
lp->m_alloc=lp->m+2;
lp->d_alloc=lp->d+2;
lp->objective=obj;
dd_InitializeBmatrix(lp->d_alloc,&(lp->B));
dd_InitializeAmatrix(lp->m_alloc,lp->d_alloc,&(lp->A));
dd_InitializeArow(lp->d_alloc,&(lp->sol));
dd_InitializeArow(lp->d_alloc,&(lp->dsol));
dd_init(lp->optvalue);
return lp;
}
dd_LPPtr dd_Matrix2LP(dd_MatrixPtr M, dd_ErrorType *err)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPType *lp;
dd_boolean localdebug=dd_FALSE;
*err=dd_NoError;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=M->colsize;
if (localdebug) fprintf(stderr,"number of equalities = %ld\n", linc);
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->eqnumber=linc; /* this records the number of equations */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && irowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],M->rowvec[j-1]); /* objective row */
} /*of j*/
return lp;
}
dd_LPPtr dd_Matrix2Feasibility(dd_MatrixPtr M, dd_ErrorType *err)
/* Load a matrix to create an LP object for feasibility. It is
essentially the dd_Matrix2LP except that the objject function
is set to identically ZERO (maximization).
*/
/* 094 */
{
dd_rowrange m, linc;
dd_colrange j;
dd_LPType *lp;
*err=dd_NoError;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
lp=dd_Matrix2LP(M, err);
lp->objective = dd_LPmax; /* since the objective is zero, this is not important */
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],dd_purezero); /* set the objective to zero. */
} /*of j*/
return lp;
}
dd_LPPtr dd_Matrix2Feasibility2(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_ErrorType *err)
/* Load a matrix to create an LP object for feasibility with additional equality and
strict inequality constraints given by R and S. There are three types of inequalities:
b_r + A_r x = 0 Linearity (Equations) specified by M
b_s + A_s x > 0 Strict Inequalities specified by row index set S
b_t + A_t x >= 0 The rest inequalities in M
Where the linearity is considered here as the union of linearity specified by
M and the additional set R. When S contains any linearity rows, those
rows are considered linearity (equation). Thus S does not overlide linearity.
To find a feasible solution, we set an LP
maximize z
subject to
b_r + A_r x = 0 all r in Linearity
b_s + A_s x - z >= 0 for all s in S
b_t + A_t x >= 0 for all the rest rows t
1 - z >= 0 to make the LP bounded.
Clearly, the feasibility problem has a solution iff the LP has a positive optimal value.
The variable z will be the last variable x_{d+1}.
*/
/* 094 */
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPType *lp;
dd_rowset L;
dd_boolean localdebug=dd_FALSE;
*err=dd_NoError;
set_initialize(&L, M->rowsize);
set_uni(L,M->linset,R);
linc=set_card(L);
m=M->rowsize+1+linc+1;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=M->colsize+1;
if (localdebug) fprintf(stderr,"number of equalities = %ld\n", linc);
lp=dd_CreateLPData(dd_LPmax, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->eqnumber=linc; /* this records the number of equations */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, L)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
} else if (set_member(i, S)) {
dd_set(lp->A[i-1][M->colsize],dd_minusone);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && irowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
for (j = 1; j <= d; j++) {
dd_set(lp->A[m-2][j-1],dd_purezero); /* initialize */
} /*of j*/
dd_set(lp->A[m-2][0],dd_one); /* the bounding constraint. */
dd_set(lp->A[m-2][M->colsize],dd_minusone); /* the bounding constraint. */
for (j = 1; j <= d; j++) {
dd_set(lp->A[m-1][j-1],dd_purezero); /* initialize */
} /*of j*/
dd_set(lp->A[m-1][M->colsize],dd_one); /* maximize z */
set_free(L);
return lp;
}
void dd_FreeLPData(dd_LPPtr lp)
{
if ((lp)!=NULL){
dd_clear(lp->optvalue);
dd_FreeArow(lp->d_alloc,lp->dsol);
dd_FreeArow(lp->d_alloc,lp->sol);
dd_FreeBmatrix(lp->d_alloc,lp->B);
dd_FreeAmatrix(lp->m_alloc,lp->d_alloc,lp->A);
set_free(lp->equalityset);
set_free(lp->redset_extra);
set_free(lp->redset_accum);
set_free(lp->posset_extra);
free(lp->nbindex);
free(lp->given_nbindex);
free(lp);
}
}
void dd_FreeLPSolution(dd_LPSolutionPtr lps)
{
if (lps!=NULL){
free(lps->nbindex);
dd_FreeArow(lps->d+1,lps->dsol);
dd_FreeArow(lps->d+1,lps->sol);
dd_clear(lps->optvalue);
free(lps);
}
}
int dd_LPReverseRow(dd_LPPtr lp, dd_rowrange i)
{
dd_colrange j;
int success=0;
if (i>=1 && i<=lp->m){
lp->LPS=dd_LPSundecided;
for (j=1; j<=lp->d; j++) {
dd_neg(lp->A[i-1][j-1],lp->A[i-1][j-1]);
/* negating the i-th constraint of A */
}
success=1;
}
return success;
}
int dd_LPReplaceRow(dd_LPPtr lp, dd_rowrange i, dd_Arow a)
{
dd_colrange j;
int success=0;
if (i>=1 && i<=lp->m){
lp->LPS=dd_LPSundecided;
for (j=1; j<=lp->d; j++) {
dd_set(lp->A[i-1][j-1],a[j-1]);
/* replacing the i-th constraint by a */
}
success=1;
}
return success;
}
dd_Arow dd_LPCopyRow(dd_LPPtr lp, dd_rowrange i)
{
dd_colrange j;
dd_Arow a;
if (i>=1 && i<=lp->m){
dd_InitializeArow(lp->d, &a);
for (j=1; j<=lp->d; j++) {
dd_set(a[j-1],lp->A[i-1][j-1]);
/* copying the i-th row to a */
}
}
return a;
}
void dd_SetNumberType(char *line,dd_NumberType *number,dd_ErrorType *Error)
{
if (strncmp(line,"integer",7)==0) {
*number = dd_Integer;
return;
}
else if (strncmp(line,"rational",8)==0) {
*number = dd_Rational;
return;
}
else if (strncmp(line,"real",4)==0) {
*number = dd_Real;
return;
}
else {
*number=dd_Unknown;
*Error=dd_ImproperInputFormat;
}
}
void dd_WriteTableau(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag)
/* Write the tableau A.T */
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) {
fprintf(f," %ld",nbindex[j]);
} fprintf(f,"\n");
for (j=1; j<= d_size+1; j++) {
fprintf(f," ----");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
dd_WriteNumber(f,x);
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_WriteSignTableau(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag)
/* Write the sign tableau A.T */
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) {
fprintf(f,"%3ld",nbindex[j]);
} fprintf(f,"\n ------- | ");
for (j=1; j<= d_size; j++) {
fprintf(f,"---");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (dd_Positive(x)) fprintf(f, " +");
else if (dd_Negative(x)) fprintf(f, " -");
else fprintf(f, " 0");
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_WriteSignTableau2(FILE *f,dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex_ref, dd_colindex nbindex,dd_rowindex bflag)
/* Write the sign tableau A.T and the reference basis */
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_init(x);
fprintf(f," %ld %ld real\n",m_size,d_size);
fprintf(f," |");
for (j=1; j<= d_size; j++) fprintf(f,"%3ld",nbindex_ref[j]);
fprintf(f,"\n |");
for (j=1; j<= d_size; j++) {
fprintf(f,"%3ld",nbindex[j]);
} fprintf(f,"\n ------- | ");
for (j=1; j<= d_size; j++) {
fprintf(f,"---");
} fprintf(f,"\n");
for (i=1; i<= m_size; i++) {
fprintf(f," %3ld(%3ld) |",i,bflag[i]);
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (dd_Positive(x)) fprintf(f, " +");
else if (dd_Negative(x)) fprintf(f, " -");
else fprintf(f, " 0");
}
fprintf(f,"\n");
}
fprintf(f,"end\n");
dd_clear(x);
}
void dd_GetRedundancyInformation(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag, dd_rowset redset)
/* Some basic variables that are forced to be nonnegative will be output. These are
variables whose dictionary row components are all nonnegative. */
{
dd_colrange j;
dd_rowrange i;
mytype x;
dd_boolean red=dd_FALSE,localdebug=dd_FALSE;
long numbred=0;
dd_init(x);
for (i=1; i<= m_size; i++) {
red=dd_TRUE;
for (j=1; j<= d_size; j++) {
dd_TableauEntry(&x,m_size,d_size,A,T,i,j);
if (red && dd_Negative(x)) red=dd_FALSE;
}
if (bflag[i]<0 && red) {
numbred+=1;
set_addelem(redset,i);
}
}
if (localdebug) fprintf(stderr,"\ndd_GetRedundancyInformation: %ld redundant rows over %ld\n",numbred, m_size);
dd_clear(x);
}
void dd_SelectDualSimplexPivot(dd_rowrange m_size,dd_colrange d_size,
int Phase1,dd_Amatrix A,dd_Bmatrix T,dd_rowindex OV,
dd_colindex nbindex_ref, dd_colindex nbindex,dd_rowindex bflag,
dd_rowrange objrow,dd_colrange rhscol, dd_boolean lexicopivot,
dd_rowrange *r,dd_colrange *s,int *selected,dd_LPStatusType *lps)
{
/* selects a dual simplex pivot (*r,*s) if the current
basis is dual feasible and not optimal. If not dual feasible,
the procedure returns *selected=dd_FALSE and *lps=LPSundecided.
If Phase1=dd_TRUE, the RHS column will be considered as the negative
of the column of the largest variable (==m_size). For this case, it is assumed
that the caller used the auxiliary row (with variable m_size) to make the current
dictionary dual feasible before calling this routine so that the nonbasic
column for m_size corresponds to the auxiliary variable.
*/
dd_boolean colselected=dd_FALSE,rowselected=dd_FALSE,
dualfeasible=dd_TRUE,localdebug=dd_FALSE;
dd_rowrange i,iref;
dd_colrange j,k;
mytype val,valn, minval,rat,minrat;
static dd_Arow rcost;
static dd_colrange d_last=0;
static dd_colset tieset,stieset; /* store the column indices with tie */
dd_init(val); dd_init(valn); dd_init(minval); dd_init(rat); dd_init(minrat);
if (d_last0) {
for (j=1; j<=d_last; j++){ dd_clear(rcost[j-1]);}
free(rcost);
set_free(tieset);
set_free(stieset);
}
rcost=(mytype*) calloc(d_size,sizeof(mytype));
for (j=1; j<=d_size; j++){ dd_init(rcost[j-1]);}
set_initialize(&tieset,d_size);
set_initialize(&stieset,d_size);
}
d_last=d_size;
*r=0; *s=0;
*selected=dd_FALSE;
*lps=dd_LPSundecided;
for (j=1; j<=d_size; j++){
if (j!=rhscol){
dd_TableauEntry(&(rcost[j-1]),m_size,d_size,A,T,objrow,j);
if (dd_Positive(rcost[j-1])) {
dualfeasible=dd_FALSE;
}
}
}
if (dualfeasible){
while ((*lps==dd_LPSundecided) && (!rowselected) && (!colselected)) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) { /* i is a basic variable */
if (Phase1){
dd_TableauEntry(&val, m_size,d_size,A,T,i,bflag[m_size]);
dd_neg(val,val);
/* for dual Phase I. The RHS (dual objective) is the negative of the auxiliary variable column. */
}
else {dd_TableauEntry(&val,m_size,d_size,A,T,i,rhscol);}
if (dd_Smaller(val,minval)) {
*r=i;
dd_set(minval,val);
}
}
}
if (dd_Nonnegative(minval)) {
*lps=dd_Optimal;
}
else {
rowselected=dd_TRUE;
set_emptyset(tieset);
for (j=1; j<=d_size; j++){
dd_TableauEntry(&val,m_size,d_size,A,T,*r,j);
if (j!=rhscol && dd_Positive(val)) {
dd_div(rat,rcost[j-1],val);
dd_neg(rat,rat);
if (*s==0 || dd_Smaller(rat,minrat)){
dd_set(minrat,rat);
*s=j;
set_emptyset(tieset);
set_addelem(tieset, j);
} else if (dd_Equal(rat,minrat)){
set_addelem(tieset,j);
}
}
}
if (*s>0) {
if (!lexicopivot || set_card(tieset)==1){
colselected=dd_TRUE; *selected=dd_TRUE;
} else { /* lexicographic rule with respect to the given reference cobasis. */
if (localdebug) {printf("Tie occurred at:"); set_write(tieset); printf("\n");
dd_WriteTableau(stderr,m_size,d_size,A,T,nbindex,bflag);
}
*s=0;
k=2; /* k runs through the column indices except RHS. */
do {
iref=nbindex_ref[k]; /* iref runs though the reference basic indices */
if (iref>0) {
j=bflag[iref];
if (j>0) {
if (set_member(j,tieset) && set_card(tieset)==1) {
*s=j;
colselected=dd_TRUE;
} else {
set_delelem(tieset, j);
/* iref is cobasic, and the corresponding col is not the pivot column except it is the last one. */
}
} else {
*s=0;
for (j=1; j<=d_size; j++){
if (set_member(j,tieset)) {
dd_TableauEntry(&val,m_size,d_size,A,T,*r,j);
dd_TableauEntry(&valn,m_size,d_size,A,T,iref,j);
if (j!=rhscol && dd_Positive(val)) {
dd_div(rat,valn,val);
if (*s==0 || dd_Smaller(rat,minrat)){
dd_set(minrat,rat);
*s=j;
set_emptyset(stieset);
set_addelem(stieset, j);
} else if (dd_Equal(rat,minrat)){
set_addelem(stieset,j);
}
}
}
}
set_copy(tieset,stieset);
if (set_card(tieset)==1) colselected=dd_TRUE;
}
}
k+=1;
} while (!colselected && k<=d_size);
*selected=dd_TRUE;
}
} else *lps=dd_Inconsistent;
}
} /* end of while */
}
if (localdebug) {
if (Phase1) fprintf(stderr,"Phase 1 : select %ld,%ld\n",*r,*s);
else fprintf(stderr,"Phase 2 : select %ld,%ld\n",*r,*s);
}
dd_clear(val); dd_clear(valn); dd_clear(minval); dd_clear(rat); dd_clear(minrat);
}
void dd_TableauEntry(mytype *x,dd_rowrange m_size, dd_colrange d_size, dd_Amatrix X, dd_Bmatrix T,
dd_rowrange r, dd_colrange s)
/* Compute the (r,s) entry of X.T */
{
dd_colrange j;
mytype temp;
dd_init(temp);
dd_set(*x,dd_purezero);
for (j=0; j< d_size; j++) {
dd_mul(temp,X[r-1][j], T[j][s-1]);
dd_add(*x, *x, temp);
}
dd_clear(temp);
}
void dd_SelectPivot2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_RowOrderType roworder,dd_rowindex ordervec, rowset equalityset,
dd_rowrange rowmax,rowset NopivotRow,
colset NopivotCol,dd_rowrange *r,dd_colrange *s,
dd_boolean *selected)
/* Select a position (*r,*s) in the matrix A.T such that (A.T)[*r][*s] is nonzero
The choice is feasible, i.e., not on NopivotRow and NopivotCol, and
best with respect to the specified roworder
*/
{
int stop;
dd_rowrange i,rtemp;
rowset rowexcluded;
mytype Xtemp;
dd_boolean localdebug=dd_FALSE;
stop = dd_FALSE;
localdebug=dd_debug;
dd_init(Xtemp);
set_initialize(&rowexcluded,m_size);
set_copy(rowexcluded,NopivotRow);
for (i=rowmax+1;i<=m_size;i++) {
set_addelem(rowexcluded,i); /* cannot pivot on any row > rmax */
}
*selected = dd_FALSE;
do {
rtemp=0; i=1;
while (i<=m_size && rtemp==0) { /* equalityset vars have highest priorities */
if (set_member(i,equalityset) && !set_member(i,rowexcluded)){
if (localdebug) fprintf(stderr,"marked set %ld chosen as a candidate\n",i);
rtemp=i;
}
i++;
}
if (rtemp==0) dd_SelectPreorderedNext2(m_size,d_size,rowexcluded,ordervec,&rtemp);;
if (rtemp>=1) {
*r=rtemp;
*s=1;
while (*s <= d_size && !*selected) {
dd_TableauEntry(&Xtemp,m_size,d_size,A,T,*r,*s);
if (!set_member(*s,NopivotCol) && dd_Nonzero(Xtemp)) {
*selected = dd_TRUE;
stop = dd_TRUE;
} else {
(*s)++;
}
}
if (!*selected) {
set_addelem(rowexcluded,rtemp);
}
}
else {
*r = 0;
*s = 0;
stop = dd_TRUE;
}
} while (!stop);
set_free(rowexcluded); dd_clear(Xtemp);
}
void dd_GaussianColumnPivot(dd_rowrange m_size, dd_colrange d_size,
dd_Amatrix X, dd_Bmatrix T, dd_rowrange r, dd_colrange s)
/* Update the Transformation matrix T with the pivot operation on (r,s)
This procedure performs a implicit pivot operation on the matrix X by
updating the dual basis inverse T.
*/
{
dd_colrange j, j1;
mytype Xtemp0, Xtemp1, Xtemp;
static dd_Arow Rtemp;
static dd_colrange last_d=0;
dd_init(Xtemp0); dd_init(Xtemp1); dd_init(Xtemp);
if (last_d!=d_size){
if (last_d>0) {
for (j=1; j<=last_d; j++) dd_clear(Rtemp[j-1]);
free(Rtemp);
}
Rtemp=(mytype*)calloc(d_size,sizeof(mytype));
for (j=1; j<=d_size; j++) dd_init(Rtemp[j-1]);
last_d=d_size;
}
for (j=1; j<=d_size; j++) {
dd_TableauEntry(&(Rtemp[j-1]), m_size, d_size, X, T, r,j);
}
dd_set(Xtemp0,Rtemp[s-1]);
for (j = 1; j <= d_size; j++) {
if (j != s) {
dd_div(Xtemp,Rtemp[j-1],Xtemp0);
dd_set(Xtemp1,dd_purezero);
for (j1 = 1; j1 <= d_size; j1++){
dd_mul(Xtemp1,Xtemp,T[j1-1][s - 1]);
dd_sub(T[j1-1][j-1],T[j1-1][j-1],Xtemp1);
/* T[j1-1][j-1] -= T[j1-1][s - 1] * Xtemp / Xtemp0; */
}
}
}
for (j = 1; j <= d_size; j++)
dd_div(T[j-1][s - 1],T[j-1][s - 1],Xtemp0);
dd_clear(Xtemp0); dd_clear(Xtemp1); dd_clear(Xtemp);
}
void dd_GaussianColumnPivot2(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_colindex nbindex,dd_rowindex bflag,dd_rowrange r,dd_colrange s)
/* Update the Transformation matrix T with the pivot operation on (r,s)
This procedure performs a implicit pivot operation on the matrix A by
updating the dual basis inverse T.
*/
{
int localdebug=dd_FALSE;
long entering;
if (dd_debug) localdebug=dd_debug;
dd_GaussianColumnPivot(m_size,d_size,A,T,r,s);
entering=nbindex[s];
bflag[r]=s; /* the nonbasic variable r corresponds to column s */
nbindex[s]=r; /* the nonbasic variable on s column is r */
if (entering>0) bflag[entering]=-1;
/* original variables have negative index and should not affect the row index */
if (localdebug) {
fprintf(stderr,"dd_GaussianColumnPivot2\n");
fprintf(stderr," pivot: (leaving, entering) = (%ld, %ld)\n", r,entering);
fprintf(stderr, " bflag[%ld] is set to %ld\n", r, s);
}
}
void dd_ResetTableau(dd_rowrange m_size,dd_colrange d_size,dd_Bmatrix T,
dd_colindex nbindex,dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol)
{
dd_rowrange i;
dd_colrange j;
/* Initialize T and nbindex */
for (j=1; j<=d_size; j++) nbindex[j]=-j;
nbindex[rhscol]=0;
/* RHS is already in nonbasis and is considered to be associated
with the zero-th row of input. */
dd_SetToIdentity(d_size,T);
/* Set the bflag according to nbindex */
for (i=1; i<=m_size; i++) bflag[i]=-1;
/* all basic variables have index -1 */
bflag[objrow]= 0;
/* bflag of the objective variable is 0,
different from other basic variables which have -1 */
for (j=1; j<=d_size; j++) if (nbindex[j]>0) bflag[nbindex[j]]=j;
/* bflag of a nonbasic variable is its column number */
}
void dd_SelectCrissCrossPivot(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,dd_Bmatrix T,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_rowrange *r,dd_colrange *s,
int *selected,dd_LPStatusType *lps)
{
int colselected=dd_FALSE,rowselected=dd_FALSE;
dd_rowrange i;
mytype val;
dd_init(val);
*selected=dd_FALSE;
*lps=dd_LPSundecided;
while ((*lps==dd_LPSundecided) && (!rowselected) && (!colselected)) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) { /* i is a basic variable */
dd_TableauEntry(&val,m_size,d_size,A,T,i,rhscol);
if (dd_Negative(val)) {
rowselected=dd_TRUE;
*r=i;
break;
}
}
else if (bflag[i] >0) { /* i is nonbasic variable */
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,bflag[i]);
if (dd_Positive(val)) {
colselected=dd_TRUE;
*s=bflag[i];
break;
}
}
}
if ((!rowselected) && (!colselected)) {
*lps=dd_Optimal;
return;
}
else if (rowselected) {
for (i=1; i<=m_size; i++) {
if (bflag[i] >0) { /* i is nonbasic variable */
dd_TableauEntry(&val,m_size,d_size,A,T,*r,bflag[i]);
if (dd_Positive(val)) {
colselected=dd_TRUE;
*s=bflag[i];
*selected=dd_TRUE;
break;
}
}
}
}
else if (colselected) {
for (i=1; i<=m_size; i++) {
if (i!=objrow && bflag[i]==-1) { /* i is a basic variable */
dd_TableauEntry(&val,m_size,d_size,A,T,i,*s);
if (dd_Negative(val)) {
rowselected=dd_TRUE;
*r=i;
*selected=dd_TRUE;
break;
}
}
}
}
if (!rowselected) {
*lps=dd_DualInconsistent;
}
else if (!colselected) {
*lps=dd_Inconsistent;
}
}
dd_clear(val);
}
void dd_CrissCrossSolve(dd_LPPtr lp, dd_ErrorType *err)
{
switch (lp->objective) {
case dd_LPmax:
dd_CrissCrossMaximize(lp,err);
break;
case dd_LPmin:
dd_CrissCrossMinimize(lp,err);
break;
case dd_LPnone: *err=dd_NoLPObjective; break;
}
}
void dd_DualSimplexSolve(dd_LPPtr lp, dd_ErrorType *err)
{
switch (lp->objective) {
case dd_LPmax:
dd_DualSimplexMaximize(lp,err);
break;
case dd_LPmin:
dd_DualSimplexMinimize(lp,err);
break;
case dd_LPnone: *err=dd_NoLPObjective; break;
}
}
#ifdef GMPRATIONAL
dd_LPStatusType LPSf2LPS(ddf_LPStatusType lpsf)
{
dd_LPStatusType lps=dd_LPSundecided;
switch (lpsf) {
case ddf_LPSundecided: lps=dd_LPSundecided; break;
case ddf_Optimal: lps=dd_Optimal; break;
case ddf_Inconsistent: lps=dd_Inconsistent; break;
case ddf_DualInconsistent: lps=dd_DualInconsistent; break;
case ddf_StrucInconsistent: lps=dd_StrucInconsistent; break;
case ddf_StrucDualInconsistent: lps=dd_StrucDualInconsistent; break;
case ddf_Unbounded: lps=dd_Unbounded; break;
case ddf_DualUnbounded: lps=dd_DualUnbounded; break;
}
return lps;
}
void dd_BasisStatus(ddf_LPPtr lpf, dd_LPPtr lp, dd_boolean *LPScorrect)
{
int i;
dd_colrange se, j;
dd_boolean basisfound;
switch (lp->objective) {
case dd_LPmax:
dd_BasisStatusMaximize(lp->m,lp->d,lp->A,lp->B,lp->equalityset,lp->objrow,lp->rhscol,
lpf->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lpf->nbindex,lpf->re,lpf->se,&se,lp->pivots,
&basisfound, LPScorrect);
if (*LPScorrect) {
/* printf("BasisStatus Check: the current basis is verified with GMP\n"); */
lp->LPS=LPSf2LPS(lpf->LPS);
lp->re=lpf->re;
lp->se=se;
for (j=1; j<=lp->d; j++) lp->nbindex[j]=lpf->nbindex[j];
}
for (i=1; i<=5; i++) lp->pivots[i-1]+=lpf->pivots[i-1];
break;
case dd_LPmin:
dd_BasisStatusMinimize(lp->m,lp->d,lp->A,lp->B,lp->equalityset,lp->objrow,lp->rhscol,
lpf->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lpf->nbindex,lpf->re,lpf->se,&se,lp->pivots,
&basisfound, LPScorrect);
if (*LPScorrect) {
/* printf("BasisStatus Check: the current basis is verified with GMP\n"); */
lp->LPS=LPSf2LPS(lpf->LPS);
lp->re=lpf->re;
lp->se=se;
for (j=1; j<=lp->d; j++) lp->nbindex[j]=lpf->nbindex[j];
}
for (i=1; i<=5; i++) lp->pivots[i-1]+=lpf->pivots[i-1];
break;
case dd_LPnone: break;
}
}
#endif
void dd_FindLPBasis(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A, dd_Bmatrix T,dd_rowindex OV,dd_rowset equalityset, dd_colindex nbindex,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_colrange *cs,int *found,dd_LPStatusType *lps,long *pivot_no)
{
/* Find a LP basis using Gaussian pivots.
If the problem has an LP basis,
the procedure returns *found=dd_TRUE,*lps=LPSundecided and an LP basis.
If the constraint matrix A (excluding the rhs and objective) is not
column independent, there are two cases. If the dependency gives a dual
inconsistency, this returns *found=dd_FALSE, *lps=dd_StrucDualInconsistent and
the evidence column *s. Otherwise, this returns *found=dd_TRUE,
*lps=LPSundecided and an LP basis of size less than d_size. Columns j
that do not belong to the basis (i.e. cannot be chosen as pivot because
they are all zero) will be indicated in nbindex vector: nbindex[j] will
be negative and set to -j.
*/
int chosen,stop;
long pivots_p0=0,rank;
colset ColSelected;
rowset RowSelected;
mytype val;
dd_rowrange r;
dd_colrange j,s;
dd_init(val);
*found=dd_FALSE; *cs=0; rank=0;
stop=dd_FALSE;
*lps=dd_LPSundecided;
set_initialize(&RowSelected,m_size);
set_initialize(&ColSelected,d_size);
set_addelem(RowSelected,objrow);
set_addelem(ColSelected,rhscol);
stop=dd_FALSE;
do { /* Find a LP basis */
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset,
m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) {
set_addelem(RowSelected,r);
set_addelem(ColSelected,s);
dd_GaussianColumnPivot2(m_size,d_size,A,T,nbindex,bflag,r,s);
pivots_p0++;
rank++;
} else {
for (j=1;j<=d_size && *lps==dd_LPSundecided; j++) {
if (j!=rhscol && nbindex[j]<0){
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,j);
if (dd_Nonzero(val)){ /* dual inconsistent */
*lps=dd_StrucDualInconsistent;
*cs=j;
/* dual inconsistent because the nonzero reduced cost */
}
}
}
if (*lps==dd_LPSundecided) *found=dd_TRUE;
/* dependent columns but not dual inconsistent. */
stop=dd_TRUE;
}
/* printf("d_size=%ld, rank=%ld\n",d_size,rank); */
if (rank==d_size-1) {
stop = dd_TRUE;
*found=dd_TRUE;
}
} while (!stop);
*pivot_no=pivots_p0;
dd_statBApivots+=pivots_p0;
set_free(RowSelected);
set_free(ColSelected);
dd_clear(val);
}
void dd_FindLPBasis2(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A, dd_Bmatrix T,dd_rowindex OV,dd_rowset equalityset, dd_colindex nbindex,
dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol,
dd_colrange *cs,int *found,long *pivot_no)
{
/* Similar to dd_FindLPBasis but it is much simpler. This tries to recompute T for
the specified basis given by nbindex. It will return *found=dd_FALSE if the specified
basis is not a basis.
*/
int chosen,stop;
long pivots_p0=0,rank;
dd_colset ColSelected,DependentCols;
dd_rowset RowSelected, NopivotRow;
mytype val;
dd_boolean localdebug=dd_FALSE;
dd_rowrange r,negcount=0;
dd_colrange j,s;
dd_init(val);
*found=dd_FALSE; *cs=0; rank=0;
set_initialize(&RowSelected,m_size);
set_initialize(&DependentCols,d_size);
set_initialize(&ColSelected,d_size);
set_initialize(&NopivotRow,m_size);
set_addelem(RowSelected,objrow);
set_addelem(ColSelected,rhscol);
set_compl(NopivotRow, NopivotRow); /* set NopivotRow to be the groundset */
for (j=2; j<=d_size; j++)
if (nbindex[j]>0)
set_delelem(NopivotRow, nbindex[j]);
else if (nbindex[j]<0){
negcount++;
set_addelem(DependentCols, -nbindex[j]);
set_addelem(ColSelected, -nbindex[j]);
}
set_uni(RowSelected, RowSelected, NopivotRow); /* RowSelected is the set of rows not allowed to poviot on */
stop=dd_FALSE;
do { /* Find a LP basis */
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset, m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) {
set_addelem(RowSelected,r);
set_addelem(ColSelected,s);
dd_GaussianColumnPivot2(m_size,d_size,A,T,nbindex,bflag,r,s);
if (localdebug && m_size <=10){
dd_WriteBmatrix(stderr,d_size,T);
dd_WriteTableau(stderr,m_size,d_size,A,T,nbindex,bflag);
}
pivots_p0++;
rank++;
} else{
*found=dd_FALSE; /* cannot pivot on any of the spacified positions. */
stop=dd_TRUE;
}
if (rank==d_size-1-negcount) {
if (negcount){
/* Now it tries to pivot on rows that are supposed to be dependent. */
set_diff(ColSelected, ColSelected, DependentCols);
dd_SelectPivot2(m_size,d_size,A,T,dd_MinIndex,OV,equalityset, m_size,RowSelected,ColSelected,&r,&s,&chosen);
if (chosen) *found=dd_FALSE; /* not supposed to be independent */
else *found=dd_TRUE;
if (localdebug){
printf("Try to check the dependent cols:");
set_write(DependentCols);
if (chosen) printf("They are not dependent. Can still pivot on (%ld, %ld)\n",r, s);
else printf("They are indeed dependent.\n");
}
} else {
*found=dd_TRUE;
}
stop = dd_TRUE;
}
} while (!stop);
for (j=1; j<=d_size; j++) if (nbindex[j]>0) bflag[nbindex[j]]=j;
*pivot_no=pivots_p0;
set_free(RowSelected);
set_free(ColSelected);
set_free(NopivotRow);
set_free(DependentCols);
dd_clear(val);
}
void dd_FindDualFeasibleBasis(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowindex OV,
dd_colindex nbindex,dd_rowindex bflag,dd_rowrange objrow,dd_colrange rhscol, dd_boolean lexicopivot,
dd_colrange *s,dd_ErrorType *err,dd_LPStatusType *lps,long *pivot_no, long maxpivots)
{
/* Find a dual feasible basis using Phase I of Dual Simplex method.
If the problem is dual feasible,
the procedure returns *err=NoError, *lps=LPSundecided and a dual feasible
basis. If the problem is dual infeasible, this returns
*err=NoError, *lps=DualInconsistent and the evidence column *s.
Caution: matrix A must have at least one extra row: the row space A[m_size] must
have been allocated.
*/
dd_boolean phase1,dualfeasible=dd_TRUE;
dd_boolean localdebug=dd_FALSE,chosen,stop;
dd_LPStatusType LPSphase1;
long pivots_p1=0;
dd_rowrange i,r_val;
dd_colrange j,l,ms=0,s_val,local_m_size;
mytype x,val,maxcost,axvalue,maxratio;
static dd_colrange d_last=0;
static dd_Arow rcost;
static dd_colindex nbindex_ref; /* to be used to store the initial feasible basis for lexico rule */
mytype scaling,svalue; /* random scaling mytype value */
mytype minval;
if (dd_debug) localdebug=dd_debug;
dd_init(x); dd_init(val); dd_init(scaling); dd_init(svalue); dd_init(axvalue);
dd_init(maxcost); dd_set(maxcost,dd_minuszero);
dd_init(maxratio); dd_set(maxratio,dd_minuszero);
if (d_last0) {
for (j=1; j<=d_last; j++){ dd_clear(rcost[j-1]);}
free(rcost);
free(nbindex_ref);
}
rcost=(mytype*) calloc(d_size,sizeof(mytype));
nbindex_ref=(long*) calloc(d_size+1,sizeof(long));
for (j=1; j<=d_size; j++){ dd_init(rcost[j-1]);}
}
d_last=d_size;
*err=dd_NoError; *lps=dd_LPSundecided; *s=0;
local_m_size=m_size+1; /* increase m_size by 1 */
ms=0; /* ms will be the index of column which has the largest reduced cost */
for (j=1; j<=d_size; j++){
if (j!=rhscol){
dd_TableauEntry(&(rcost[j-1]),local_m_size,d_size,A,T,objrow,j);
if (dd_Larger(rcost[j-1],maxcost)) {dd_set(maxcost,rcost[j-1]); ms = j;}
}
}
if (dd_Positive(maxcost)) dualfeasible=dd_FALSE;
if (!dualfeasible){
for (j=1; j<=d_size; j++){
dd_set(A[local_m_size-1][j-1], dd_purezero);
for (l=1; l<=d_size; l++){
if (nbindex[l]>0) {
dd_set_si(scaling,l+10);
dd_mul(svalue,A[nbindex[l]-1][j-1],scaling);
dd_sub(A[local_m_size-1][j-1],A[local_m_size-1][j-1],svalue);
/* To make the auxiliary row (0,-11,-12,...,-d-10).
It is likely to be better than (0, -1, -1, ..., -1)
to avoid a degenerate LP. Version 093c. */
}
}
}
if (localdebug){
fprintf(stderr,"\ndd_FindDualFeasibleBasis: curruent basis is not dual feasible.\n");
fprintf(stderr,"because of the column %ld assoc. with var %ld dual cost =",
ms,nbindex[ms]);
dd_WriteNumber(stderr, maxcost);
if (localdebug) {
if (m_size <=100 && d_size <=30){
printf("\ndd_FindDualFeasibleBasis: the starting dictionary.\n");
dd_WriteTableau(stdout,m_size+1,d_size,A,T,nbindex,bflag);
}
}
}
ms=0;
/* Ratio Test: ms will be now the index of column which has the largest reduced cost
over the auxiliary row entry */
for (j=1; j<=d_size; j++){
if ((j!=rhscol) && dd_Positive(rcost[j-1])){
dd_TableauEntry(&axvalue,local_m_size,d_size,A,T,local_m_size,j);
if (dd_Nonnegative(axvalue)) {
*err=dd_NumericallyInconsistent;
/* This should not happen as they are set negative above. Quit the phase I.*/
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected.\n");
goto _L99;
}
dd_neg(axvalue,axvalue);
dd_div(axvalue,rcost[j-1],axvalue); /* axvalue is the negative of ratio that is to be maximized. */
if (dd_Larger(axvalue,maxratio)) {
dd_set(maxratio,axvalue);
ms = j;
}
}
}
if (ms==0) {
*err=dd_NumericallyInconsistent; /* This should not happen. Quit the phase I.*/
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected.\n");
goto _L99;
}
/* Pivot on (local_m_size,ms) so that the dual basic solution becomes feasible */
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,local_m_size,ms);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: Pivot on %ld %ld.\n",local_m_size,ms);
}
for (j=1; j<=d_size; j++) nbindex_ref[j]=nbindex[j];
/* set the reference basis to be the current feasible basis. */
if (localdebug){
fprintf(stderr, "Store the current feasible basis:");
for (j=1; j<=d_size; j++) fprintf(stderr, " %ld", nbindex_ref[j]);
fprintf(stderr, "\n");
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,m_size+1,d_size,A,T,nbindex_ref,nbindex,bflag);
}
phase1=dd_TRUE; stop=dd_FALSE;
do { /* Dual Simplex Phase I */
chosen=dd_FALSE; LPSphase1=dd_LPSundecided;
if (pivots_p1>maxpivots) {
*err=dd_LPCycling;
fprintf(stderr,"max number %ld of pivots performed in Phase I. Switch to the anticycling phase.\n", maxpivots);
goto _L99; /* failure due to max no. of pivots performed */
}
dd_SelectDualSimplexPivot(local_m_size,d_size,phase1,A,T,OV,nbindex_ref,nbindex,bflag,
objrow,rhscol,lexicopivot,&r_val,&s_val,&chosen,&LPSphase1);
if (!chosen) {
/* The current dictionary is terminal. There are two cases:
dd_TableauEntry(local_m_size,d_size,A,T,objrow,ms) is negative or zero.
The first case implies dual infeasible,
and the latter implies dual feasible but local_m_size is still in nonbasis.
We must pivot in the auxiliary variable local_m_size.
*/
dd_TableauEntry(&x,local_m_size,d_size,A,T,objrow,ms);
if (dd_Negative(x)){
*err=dd_NoError; *lps=dd_DualInconsistent; *s=ms;
}
if (localdebug) {
fprintf(stderr,"\ndd_FindDualFeasibleBasis: the auxiliary variable was forced to enter the basis (# pivots = %ld).\n",pivots_p1);
fprintf(stderr," -- objrow %ld, ms %ld entry: ",objrow,ms);
dd_WriteNumber(stderr, x); fprintf(stderr,"\n");
if (dd_Negative(x)){
fprintf(stderr,"->The basis is dual inconsistent. Terminate.\n");
} else {
fprintf(stderr,"->The basis is feasible. Go to phase II.\n");
}
}
dd_init(minval);
r_val=0;
for (i=1; i<=local_m_size; i++){
if (bflag[i]<0) {
/* i is basic and not the objective variable */
dd_TableauEntry(&val,local_m_size,d_size,A,T,i,ms); /* auxiliary column*/
if (dd_Smaller(val, minval)) {
r_val=i;
dd_set(minval,val);
}
}
}
dd_clear(minval);
if (r_val==0) {
*err=dd_NumericallyInconsistent; /* This should not happen. Quit the phase I.*/
if (localdebug) fprintf(stderr,"dd_FindDualFeasibleBasis: Numerical Inconsistency detected (r_val is 0).\n");
goto _L99;
}
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,r_val,ms);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: make the %ld-th pivot on %ld %ld to force the auxiliary variable to enter the basis.\n",pivots_p1,r_val,ms);
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,m_size+1,d_size,A,T,nbindex_ref,nbindex,bflag);
}
stop=dd_TRUE;
} else {
dd_GaussianColumnPivot2(local_m_size,d_size,A,T,nbindex,bflag,r_val,s_val);
pivots_p1=pivots_p1+1;
if (localdebug) {
printf("\ndd_FindDualFeasibleBasis: make a %ld-th pivot on %ld %ld\n",pivots_p1,r_val,s_val);
if (m_size <=100 && d_size <=30)
dd_WriteSignTableau2(stdout,local_m_size,d_size,A,T,nbindex_ref,nbindex,bflag);
}
if (bflag[local_m_size]<0) {
stop=dd_TRUE;
if (localdebug)
fprintf(stderr,"\nDualSimplex Phase I: the auxiliary variable entered the basis (# pivots = %ld).\nGo to phase II\n",pivots_p1);
}
}
} while(!stop);
}
_L99:
*pivot_no=pivots_p1;
dd_statDS1pivots+=pivots_p1;
dd_clear(x); dd_clear(val); dd_clear(maxcost); dd_clear(maxratio);
dd_clear(scaling); dd_clear(svalue); dd_clear(axvalue);
}
void dd_DualSimplexMinimize(dd_LPPtr lp,dd_ErrorType *err)
{
dd_colrange j;
*err=dd_NoError;
for (j=1; j<=lp->d; j++)
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
dd_DualSimplexMaximize(lp,err);
dd_neg(lp->optvalue,lp->optvalue);
for (j=1; j<=lp->d; j++){
if (lp->LPS!=dd_Inconsistent) {
/* Inconsistent certificate stays valid for minimization, 0.94e */
dd_neg(lp->dsol[j-1],lp->dsol[j-1]);
}
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
}
}
void dd_DualSimplexMaximize(dd_LPPtr lp,dd_ErrorType *err)
/*
When LP is inconsistent then lp->re returns the evidence row.
When LP is dual-inconsistent then lp->se returns the evidence column.
*/
{
int stop,chosen,phase1,found;
long pivots_ds=0,pivots_p0=0,pivots_p1=0,pivots_pc=0,maxpivots,maxpivfactor=20;
dd_boolean localdebug=dd_FALSE,localdebug1=dd_FALSE;
#if !defined GMPRATIONAL
long maxccpivots,maxccpivfactor=100;
/* criss-cross should not cycle, but with floating-point arithmetics, it happens
(very rarely). Jorg Rambau reported such an LP, in August 2003. Thanks Jorg!
*/
#endif
dd_rowrange i,r;
dd_colrange j,s;
static dd_rowindex bflag;
static long mlast=0,nlast=0;
static dd_rowindex OrderVector; /* the permutation vector to store a preordered row indeces */
static dd_colindex nbindex_ref; /* to be used to store the initial feasible basis for lexico rule */
double redpercent=0;
unsigned int rseed=1;
/* *err=dd_NoError; */
if (dd_debug) localdebug=dd_debug;
set_emptyset(lp->redset_extra);
for (i=0; i<= 4; i++) lp->pivots[i]=0;
maxpivots=maxpivfactor*lp->d; /* maximum pivots to be performed before cc pivot is applied. */
#if !defined GMPRATIONAL
maxccpivots=maxccpivfactor*lp->d; /* maximum pivots to be performed with emergency cc pivots. */
#endif
if (mlast!=lp->m || nlast!=lp->d){
if (mlast>0) { /* called previously with different lp->m */
free(OrderVector);
free(bflag);
free(nbindex_ref);
}
OrderVector=(long *)calloc(lp->m+1,sizeof(*OrderVector));
bflag=(long *) calloc(lp->m+2,sizeof(*bflag)); /* one more element for an auxiliary variable */
nbindex_ref=(long*) calloc(lp->d+1,sizeof(long));
mlast=lp->m;nlast=lp->d;
}
/* Initializing control variables. */
dd_ComputeRowOrderVector2(lp->m,lp->d,lp->A,OrderVector,dd_MinIndex,rseed);
lp->re=0; lp->se=0;
dd_ResetTableau(lp->m,lp->d,lp->B,lp->nbindex,bflag,lp->objrow,lp->rhscol);
dd_FindLPBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->equalityset,lp->nbindex,bflag,
lp->objrow,lp->rhscol,&s,&found,&(lp->LPS),&pivots_p0);
lp->pivots[0]=pivots_p0;
if (!found){
lp->se=s;
goto _L99;
/* No LP basis is found, and thus Inconsistent.
Output the evidence column. */
}
dd_FindDualFeasibleBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->nbindex,bflag,
lp->objrow,lp->rhscol,lp->lexicopivot,&s, err,&(lp->LPS),&pivots_p1, maxpivots);
lp->pivots[1]=pivots_p1;
for (j=1; j<=lp->d; j++) nbindex_ref[j]=lp->nbindex[j];
/* set the reference basis to be the current feasible basis. */
if (localdebug){
fprintf(stderr, "dd_DualSimplexMaximize: Store the current feasible basis:");
for (j=1; j<=lp->d; j++) fprintf(stderr, " %ld", nbindex_ref[j]);
fprintf(stderr, "\n");
if (lp->m <=100 && lp->d <=30)
dd_WriteSignTableau2(stdout,lp->m+1,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
if (*err==dd_LPCycling || *err==dd_NumericallyInconsistent){
if (localdebug) fprintf(stderr, "Phase I failed and thus switch to the Criss-Cross method\n");
dd_CrissCrossMaximize(lp,err);
return;
}
if (lp->LPS==dd_DualInconsistent){
lp->se=s;
goto _L99;
/* No dual feasible basis is found, and thus DualInconsistent.
Output the evidence column. */
}
/* Dual Simplex Method */
stop=dd_FALSE;
do {
chosen=dd_FALSE; lp->LPS=dd_LPSundecided; phase1=dd_FALSE;
if (pivots_dsm,lp->d,phase1,lp->A,lp->B,OrderVector,nbindex_ref,lp->nbindex,bflag,
lp->objrow,lp->rhscol,lp->lexicopivot,&r,&s,&chosen,&(lp->LPS));
}
if (chosen) {
pivots_ds=pivots_ds+1;
if (lp->redcheck_extensive) {
dd_GetRedundancyInformation(lp->m,lp->d,lp->A,lp->B,lp->nbindex, bflag, lp->redset_extra);
set_uni(lp->redset_accum, lp->redset_accum,lp->redset_extra);
redpercent=100*(double)set_card(lp->redset_extra)/(double)lp->m;
if (localdebug1){
fprintf(stderr,"\ndd_DualSimplexMaximize: Phase II pivot %ld on (%ld, %ld).\n",pivots_ds,r,s);
fprintf(stderr," redundancy %f percent: redset size = %ld\n",redpercent,set_card(lp->redset_extra));
}
}
}
if (!chosen && lp->LPS==dd_LPSundecided) {
if (localdebug1){
fprintf(stderr,"Warning: an emergency CC pivot in Phase II is performed\n");
/* In principle this should not be executed because we already have dual feasibility
attained and dual simplex pivot should have been chosen. This might occur
under floating point computation, or the case of cycling.
*/
if (localdebug && lp->m <=100 && lp->d <=30){
fprintf(stderr,"\ndd_DualSimplexMaximize: The current dictionary.\n");
dd_WriteSignTableau2(stdout,lp->m,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
}
#if !defined GMPRATIONAL
if (pivots_pc>maxccpivots) {
*err=dd_LPCycling;
stop=dd_TRUE;
goto _L99;
}
#endif
dd_SelectCrissCrossPivot(lp->m,lp->d,lp->A,lp->B,bflag,
lp->objrow,lp->rhscol,&r,&s,&chosen,&(lp->LPS));
if (chosen) pivots_pc=pivots_pc+1;
}
if (chosen) {
dd_GaussianColumnPivot2(lp->m,lp->d,lp->A,lp->B,lp->nbindex,bflag,r,s);
if (localdebug && lp->m <=100 && lp->d <=30){
fprintf(stderr,"\ndd_DualSimplexMaximize: The current dictionary.\n");
dd_WriteSignTableau2(stdout,lp->m,lp->d,lp->A,lp->B,nbindex_ref,lp->nbindex,bflag);
}
} else {
switch (lp->LPS){
case dd_Inconsistent: lp->re=r;
case dd_DualInconsistent: lp->se=s;
default: break;
}
stop=dd_TRUE;
}
} while(!stop);
_L99:
lp->pivots[2]=pivots_ds;
lp->pivots[3]=pivots_pc;
dd_statDS2pivots+=pivots_ds;
dd_statACpivots+=pivots_pc;
dd_SetSolutions(lp->m,lp->d,lp->A,lp->B,lp->objrow,lp->rhscol,lp->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lp->nbindex,lp->re,lp->se,bflag);
}
void dd_CrissCrossMinimize(dd_LPPtr lp,dd_ErrorType *err)
{
dd_colrange j;
*err=dd_NoError;
for (j=1; j<=lp->d; j++)
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
dd_CrissCrossMaximize(lp,err);
dd_neg(lp->optvalue,lp->optvalue);
for (j=1; j<=lp->d; j++){
if (lp->LPS!=dd_Inconsistent) {
/* Inconsistent certificate stays valid for minimization, 0.94e */
dd_neg(lp->dsol[j-1],lp->dsol[j-1]);
}
dd_neg(lp->A[lp->objrow-1][j-1],lp->A[lp->objrow-1][j-1]);
}
}
void dd_CrissCrossMaximize(dd_LPPtr lp,dd_ErrorType *err)
/*
When LP is inconsistent then lp->re returns the evidence row.
When LP is dual-inconsistent then lp->se returns the evidence column.
*/
{
int stop,chosen,found;
long pivots0,pivots1;
#if !defined GMPRATIONAL
long maxpivots,maxpivfactor=1000;
/* criss-cross should not cycle, but with floating-point arithmetics, it happens
(very rarely). Jorg Rambau reported such an LP, in August 2003. Thanks Jorg!
*/
#endif
dd_rowrange i,r;
dd_colrange s;
static dd_rowindex bflag;
static long mlast=0;
static dd_rowindex OrderVector; /* the permutation vector to store a preordered row indeces */
unsigned int rseed=1;
dd_colindex nbtemp;
*err=dd_NoError;
#if !defined GMPRATIONAL
maxpivots=maxpivfactor*lp->d; /* maximum pivots to be performed when floating-point arithmetics is used. */
#endif
nbtemp=(long *) calloc(lp->d+1,sizeof(long));
for (i=0; i<= 4; i++) lp->pivots[i]=0;
if (bflag==NULL || mlast!=lp->m){
if (mlast!=lp->m && mlast>0) {
free(bflag); /* called previously with different lp->m */
free(OrderVector);
}
bflag=(long *) calloc(lp->m+1,sizeof(long));
OrderVector=(long *)calloc(lp->m+1,sizeof(long));
/* initialize only for the first time or when a larger space is needed */
mlast=lp->m;
}
/* Initializing control variables. */
dd_ComputeRowOrderVector2(lp->m,lp->d,lp->A,OrderVector,dd_MinIndex,rseed);
lp->re=0; lp->se=0; pivots1=0;
dd_ResetTableau(lp->m,lp->d,lp->B,lp->nbindex,bflag,lp->objrow,lp->rhscol);
dd_FindLPBasis(lp->m,lp->d,lp->A,lp->B,OrderVector,lp->equalityset,
lp->nbindex,bflag,lp->objrow,lp->rhscol,&s,&found,&(lp->LPS),&pivots0);
lp->pivots[0]+=pivots0;
if (!found){
lp->se=s;
goto _L99;
/* No LP basis is found, and thus Inconsistent.
Output the evidence column. */
}
stop=dd_FALSE;
do { /* Criss-Cross Method */
#if !defined GMPRATIONAL
if (pivots1>maxpivots) {
*err=dd_LPCycling;
fprintf(stderr,"max number %ld of pivots performed by the criss-cross method. Most likely due to the floating-point arithmetics error.\n", maxpivots);
goto _L99; /* failure due to max no. of pivots performed */
}
#endif
dd_SelectCrissCrossPivot(lp->m,lp->d,lp->A,lp->B,bflag,
lp->objrow,lp->rhscol,&r,&s,&chosen,&(lp->LPS));
if (chosen) {
dd_GaussianColumnPivot2(lp->m,lp->d,lp->A,lp->B,lp->nbindex,bflag,r,s);
pivots1++;
} else {
switch (lp->LPS){
case dd_Inconsistent: lp->re=r;
case dd_DualInconsistent: lp->se=s;
default: break;
}
stop=dd_TRUE;
}
} while(!stop);
_L99:
lp->pivots[1]+=pivots1;
dd_statCCpivots+=pivots1;
dd_SetSolutions(lp->m,lp->d,lp->A,lp->B,
lp->objrow,lp->rhscol,lp->LPS,&(lp->optvalue),lp->sol,lp->dsol,lp->posset_extra,lp->nbindex,lp->re,lp->se,bflag);
free(nbtemp);
}
void dd_SetSolutions(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,
dd_rowrange objrow,dd_colrange rhscol,dd_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol,dd_rowset posset, dd_colindex nbindex,
dd_rowrange re,dd_colrange se,dd_rowindex bflag)
/*
Assign the solution vectors to sol,dsol,*optvalue after solving
the LP.
*/
{
dd_rowrange i;
dd_colrange j;
mytype x,sw;
int localdebug=dd_FALSE;
dd_init(x); dd_init(sw);
if (localdebug) fprintf(stderr,"SetSolutions:\n");
switch (LPS){
case dd_Optimal:
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][rhscol-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
dd_TableauEntry(optvalue,m_size,d_size,A,T,objrow,rhscol);
if (localdebug) {fprintf(stderr,"dsol[%ld]= ",nbindex[j]); dd_WriteNumber(stderr, dsol[j-1]); }
}
for (i=1; i<=m_size; i++) {
if (bflag[i]==-1) { /* i is a basic variable */
dd_TableauEntry(&x,m_size,d_size,A,T,i,rhscol);
if (dd_Positive(x)) set_addelem(posset, i);
}
}
break;
case dd_Inconsistent:
if (localdebug) fprintf(stderr,"SetSolutions: LP is inconsistent.\n");
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][rhscol-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,re,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]=",nbindex[j]);
dd_WriteNumber(stderr,dsol[j-1]);
fprintf(stderr,"\n");
}
}
break;
case dd_DualInconsistent:
if (localdebug) printf( "SetSolutions: LP is dual inconsistent.\n");
for (j=1;j<=d_size; j++) {
dd_set(sol[j-1],T[j-1][se-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]=",nbindex[j]);
dd_WriteNumber(stderr,dsol[j-1]);
fprintf(stderr,"\n");
}
}
break;
case dd_StrucDualInconsistent:
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,se);
if (dd_Positive(x)) dd_set(sw,dd_one);
else dd_neg(sw,dd_one);
for (j=1;j<=d_size; j++) {
dd_mul(sol[j-1],sw,T[j-1][se-1]);
dd_TableauEntry(&x,m_size,d_size,A,T,objrow,j);
dd_neg(dsol[j-1],x);
if (localdebug) {fprintf(stderr,"dsol[%ld]= ",nbindex[j]);dd_WriteNumber(stderr,dsol[j-1]);}
}
if (localdebug) fprintf(stderr,"SetSolutions: LP is dual inconsistent.\n");
break;
default:break;
}
dd_clear(x); dd_clear(sw);
}
void dd_RandomPermutation2(dd_rowindex OV,long t,unsigned int seed)
{
long k,j,ovj;
double u,xk,r,rand_max=(double) RAND_MAX;
int localdebug=dd_FALSE;
srand(seed);
for (j=t; j>1 ; j--) {
r=rand();
u=r/rand_max;
xk=(double)(j*u +1);
k=(long)xk;
if (localdebug) fprintf(stderr,"u=%g, k=%ld, r=%g, randmax= %g\n",u,k,r,rand_max);
ovj=OV[j];
OV[j]=OV[k];
OV[k]=ovj;
if (localdebug) fprintf(stderr,"row %ld is exchanged with %ld\n",j,k);
}
}
void dd_ComputeRowOrderVector2(dd_rowrange m_size,dd_colrange d_size,dd_Amatrix A,
dd_rowindex OV,dd_RowOrderType ho,unsigned int rseed)
{
long i,itemp;
OV[0]=0;
switch (ho){
case dd_MaxIndex:
for(i=1; i<=m_size; i++) OV[i]=m_size-i+1;
break;
case dd_LexMin:
for(i=1; i<=m_size; i++) OV[i]=i;
dd_QuickSort(OV,1,m_size,A,d_size);
break;
case dd_LexMax:
for(i=1; i<=m_size; i++) OV[i]=i;
dd_QuickSort(OV,1,m_size,A,d_size);
for(i=1; i<=m_size/2;i++){ /* just reverse the order */
itemp=OV[i];
OV[i]=OV[m_size-i+1];
OV[m_size-i+1]=itemp;
}
break;
case dd_RandomRow:
for(i=1; i<=m_size; i++) OV[i]=i;
if (rseed<=0) rseed=1;
dd_RandomPermutation2(OV,m_size,rseed);
break;
case dd_MinIndex:
for(i=1; i<=m_size; i++) OV[i]=i;
break;
default:
for(i=1; i<=m_size; i++) OV[i]=i;
break;
}
}
void dd_SelectPreorderedNext2(dd_rowrange m_size,dd_colrange d_size,
rowset excluded,dd_rowindex OV,dd_rowrange *hnext)
{
dd_rowrange i,k;
*hnext=0;
for (i=1; i<=m_size && *hnext==0; i++){
k=OV[i];
if (!set_member(k,excluded)) *hnext=k ;
}
}
#ifdef GMPRATIONAL
ddf_LPObjectiveType Obj2Obj(dd_LPObjectiveType obj)
{
ddf_LPObjectiveType objf=ddf_LPnone;
switch (obj) {
case dd_LPnone: objf=ddf_LPnone; break;
case dd_LPmax: objf=ddf_LPmax; break;
case dd_LPmin: objf=ddf_LPmin; break;
}
return objf;
}
ddf_LPPtr dd_LPgmp2LPf(dd_LPPtr lp)
{
dd_rowrange i;
dd_colrange j;
ddf_LPType *lpf;
double val;
dd_boolean localdebug=dd_FALSE;
if (localdebug) fprintf(stderr,"Converting a GMP-LP to a float-LP.\n");
lpf=ddf_CreateLPData(Obj2Obj(lp->objective), ddf_Real, lp->m, lp->d);
lpf->Homogeneous = lp->Homogeneous;
lpf->eqnumber=lp->eqnumber; /* this records the number of equations */
for (i = 1; i <= lp->m; i++) {
if (set_member(i, lp->equalityset)) set_addelem(lpf->equalityset,i);
/* it is equality. Its reversed row will not be in this set */
for (j = 1; j <= lp->d; j++) {
val=mpq_get_d(lp->A[i-1][j-1]);
ddf_set_d(lpf->A[i-1][j-1],val);
} /*of j*/
} /*of i*/
return lpf;
}
#endif
dd_boolean dd_LPSolve(dd_LPPtr lp,dd_LPSolverType solver,dd_ErrorType *err)
/*
The current version of dd_LPSolve that solves an LP with floating-arithmetics first
and then with the specified arithimetics if it is GMP.
When LP is inconsistent then *re returns the evidence row.
When LP is dual-inconsistent then *se returns the evidence column.
*/
{
int i;
dd_boolean found=dd_FALSE;
#ifdef GMPRATIONAL
ddf_LPPtr lpf;
ddf_ErrorType errf;
dd_boolean LPScorrect=dd_FALSE;
dd_boolean localdebug=dd_FALSE;
if (dd_debug) localdebug=dd_debug;
#endif
*err=dd_NoError;
lp->solver=solver;
time(&lp->starttime);
#ifndef GMPRATIONAL
switch (lp->solver) {
case dd_CrissCross:
dd_CrissCrossSolve(lp,err);
break;
case dd_DualSimplex:
dd_DualSimplexSolve(lp,err);
break;
}
#else
lpf=dd_LPgmp2LPf(lp);
switch (lp->solver) {
case dd_CrissCross:
ddf_CrissCrossSolve(lpf,&errf); /* First, run with double float. */
if (errf==ddf_NoError){ /* 094a: fix for a bug reported by Dima Pasechnik */
dd_BasisStatus(lpf,lp, &LPScorrect); /* Check the basis. */
} else {LPScorrect=dd_FALSE;}
if (!LPScorrect) {
if (localdebug) printf("BasisStatus: the current basis is NOT verified with GMP. Rerun with GMP.\n");
dd_CrissCrossSolve(lp,err); /* Rerun with GMP if fails. */
} else {
if (localdebug) printf("BasisStatus: the current basis is verified with GMP. The LP Solved.\n");
}
break;
case dd_DualSimplex:
ddf_DualSimplexSolve(lpf,&errf); /* First, run with double float. */
if (errf==ddf_NoError){ /* 094a: fix for a bug reported by Dima Pasechnik */
dd_BasisStatus(lpf,lp, &LPScorrect); /* Check the basis. */
} else {LPScorrect=dd_FALSE;}
if (!LPScorrect){
if (localdebug) printf("BasisStatus: the current basis is NOT verified with GMP. Rerun with GMP.\n");
dd_DualSimplexSolve(lp,err); /* Rerun with GMP if fails. */
if (localdebug){
printf("*total number pivots = %ld (ph0 = %ld, ph1 = %ld, ph2 = %ld, ph3 = %ld, ph4 = %ld)\n",
lp->total_pivots,lp->pivots[0],lp->pivots[1],lp->pivots[2],lp->pivots[3],lp->pivots[4]);
ddf_WriteLPResult(stdout, lpf, errf);
dd_WriteLP(stdout, lp);
}
} else {
if (localdebug) printf("BasisStatus: the current basis is verified with GMP. The LP Solved.\n");
}
break;
}
ddf_FreeLPData(lpf);
#endif
time(&lp->endtime);
lp->total_pivots=0;
for (i=0; i<=4; i++) lp->total_pivots+=lp->pivots[i];
if (*err==dd_NoError) found=dd_TRUE;
return found;
}
dd_boolean dd_LPSolve0(dd_LPPtr lp,dd_LPSolverType solver,dd_ErrorType *err)
/*
The original version of dd_LPSolve that solves an LP with specified arithimetics.
When LP is inconsistent then *re returns the evidence row.
When LP is dual-inconsistent then *se returns the evidence column.
*/
{
int i;
dd_boolean found=dd_FALSE;
*err=dd_NoError;
lp->solver=solver;
time(&lp->starttime);
switch (lp->solver) {
case dd_CrissCross:
dd_CrissCrossSolve(lp,err);
break;
case dd_DualSimplex:
dd_DualSimplexSolve(lp,err);
break;
}
time(&lp->endtime);
lp->total_pivots=0;
for (i=0; i<=4; i++) lp->total_pivots+=lp->pivots[i];
if (*err==dd_NoError) found=dd_TRUE;
return found;
}
dd_LPPtr dd_MakeLPforInteriorFinding(dd_LPPtr lp)
/* Delete the objective row,
add an extra column with -1's to the matrix A,
add an extra row with (bceil, 0,...,0,-1),
add an objective row with (0,...,0,1), and
rows & columns, and change m_size and d_size accordingly, to output new_A.
This sets up the LP:
maximize x_{d+1}
s.t. A x + x_{d+1} <= b
x_{d+1} <= bm * bmax,
where bm is set to 2 by default, and bmax=max{1, b[1],...,b[m_size]}.
Note that the equalitions (linearity) in the input lp will be ignored.
*/
{
dd_rowrange m;
dd_colrange d;
dd_NumberType numbtype;
dd_LPObjectiveType obj;
dd_LPType *lpnew;
dd_rowrange i;
dd_colrange j;
mytype bm,bmax,bceil;
int localdebug=dd_FALSE;
dd_init(bm); dd_init(bmax); dd_init(bceil);
dd_add(bm,dd_one,dd_one); dd_set(bmax,dd_one);
numbtype=lp->numbtype;
m=lp->m+1;
d=lp->d+1;
obj=dd_LPmax;
lpnew=dd_CreateLPData(obj, numbtype, m, d);
for (i=1; i<=lp->m; i++) {
if (dd_Larger(lp->A[i-1][lp->rhscol-1],bmax))
dd_set(bmax,lp->A[i-1][lp->rhscol-1]);
}
dd_mul(bceil,bm,bmax);
if (localdebug) {fprintf(stderr,"bceil is set to "); dd_WriteNumber(stderr, bceil);}
for (i=1; i <= lp->m; i++) {
for (j=1; j <= lp->d; j++) {
dd_set(lpnew->A[i-1][j-1],lp->A[i-1][j-1]);
}
}
for (i=1;i<=lp->m; i++){
dd_neg(lpnew->A[i-1][lp->d],dd_one); /* new column with all minus one's */
}
for (j=1;j<=lp->d;j++){
dd_set(lpnew->A[m-2][j-1],dd_purezero); /* new row (bceil, 0,...,0,-1) */
}
dd_set(lpnew->A[m-2][0],bceil); /* new row (bceil, 0,...,0,-1) */
for (j=1;j<= d-1;j++) {
dd_set(lpnew->A[m-1][j-1],dd_purezero); /* new obj row with (0,...,0,1) */
}
dd_set(lpnew->A[m-1][d-1],dd_one); /* new obj row with (0,...,0,1) */
if (localdebug) dd_WriteAmatrix(stderr, lp->A, lp->m, lp->d);
if (localdebug) dd_WriteAmatrix(stderr, lpnew->A, lpnew->m, lpnew->d);
dd_clear(bm); dd_clear(bmax); dd_clear(bceil);
return lpnew;
}
void dd_WriteLPResult(FILE *f,dd_LPPtr lp,dd_ErrorType err)
{
long j;
fprintf(f,"* cdd LP solver result\n");
if (err!=dd_NoError) {
dd_WriteErrorMessages(f,err);
goto _L99;
}
dd_WriteProgramDescription(f);
fprintf(f,"* #constraints = %ld\n",lp->m-1);
fprintf(f,"* #variables = %ld\n",lp->d-1);
switch (lp->solver) {
case dd_DualSimplex:
fprintf(f,"* Algorithm: dual simplex algorithm\n");break;
case dd_CrissCross:
fprintf(f,"* Algorithm: criss-cross method\n");break;
}
switch (lp->objective) {
case dd_LPmax:
fprintf(f,"* maximization is chosen\n");break;
case dd_LPmin:
fprintf(f,"* minimization is chosen\n");break;
case dd_LPnone:
fprintf(f,"* no objective type (max or min) is chosen\n");break;
}
if (lp->objective==dd_LPmax||lp->objective==dd_LPmin){
fprintf(f,"* Objective function is\n");
for (j=0; jd; j++){
if (j>0 && dd_Nonnegative(lp->A[lp->objrow-1][j]) ) fprintf(f," +");
if (j>0 && (j % 5) == 0) fprintf(f,"\n");
dd_WriteNumber(f,lp->A[lp->objrow-1][j]);
if (j>0) fprintf(f," X[%3ld]",j);
}
fprintf(f,"\n");
}
switch (lp->LPS){
case dd_Optimal:
fprintf(f,"* LP status: a dual pair (x,y) of optimal solutions found.\n");
fprintf(f,"begin\n");
fprintf(f," primal_solution\n");
for (j=1; jd; j++) {
fprintf(f," %3ld : ",j);
dd_WriteNumber(f,lp->sol[j]);
fprintf(f,"\n");
}
fprintf(f," dual_solution\n");
for (j=1; jd; j++){
if (lp->nbindex[j+1]>0) {
fprintf(f," %3ld : ",lp->nbindex[j+1]);
dd_WriteNumber(f,lp->dsol[j]); fprintf(f,"\n");
}
}
fprintf(f," optimal_value : "); dd_WriteNumber(f,lp->optvalue);
fprintf(f,"\nend\n");
break;
case dd_Inconsistent:
fprintf(f,"* LP status: LP is inconsistent.\n");
fprintf(f,"* The positive combination of original inequalities with\n");
fprintf(f,"* the following coefficients will prove the inconsistency.\n");
fprintf(f,"begin\n");
fprintf(f," dual_direction\n");
fprintf(f," %3ld : ",lp->re);
dd_WriteNumber(f,dd_one); fprintf(f,"\n");
for (j=1; jd; j++){
if (lp->nbindex[j+1]>0) {
fprintf(f," %3ld : ",lp->nbindex[j+1]);
dd_WriteNumber(f,lp->dsol[j]); fprintf(f,"\n");
}
}
fprintf(f,"end\n");
break;
case dd_DualInconsistent: case dd_StrucDualInconsistent:
fprintf(f,"* LP status: LP is dual inconsistent.\n");
fprintf(f,"* The linear combination of columns with\n");
fprintf(f,"* the following coefficients will prove the dual inconsistency.\n");
fprintf(f,"* (It is also an unbounded direction for the primal LP.)\n");
fprintf(f,"begin\n");
fprintf(f," primal_direction\n");
for (j=1; jd; j++) {
fprintf(f," %3ld : ",j);
dd_WriteNumber(f,lp->sol[j]);
fprintf(f,"\n");
}
fprintf(f,"end\n");
break;
default:
break;
}
fprintf(f,"* number of pivot operations = %ld (ph0 = %ld, ph1 = %ld, ph2 = %ld, ph3 = %ld, ph4 = %ld)\n",lp->total_pivots,lp->pivots[0],lp->pivots[1],lp->pivots[2],lp->pivots[3],lp->pivots[4]);
dd_WriteLPTimes(f, lp);
_L99:;
}
dd_LPPtr dd_CreateLP_H_ImplicitLinearity(dd_MatrixPtr M)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+1;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=M->colsize+1;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->objective = dd_LPmax;
lp->eqnumber=linc; /* this records the number of equations */
lp->redcheck_extensive=dd_FALSE; /* this is default */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
} /*of j*/
} else {
dd_set(lp->A[i-1][d-1],dd_minusone); /* b_I + A_I x - 1 z >= 0 (z=x_d) */
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && irowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
dd_set(lp->A[m-2][0],dd_one); dd_set(lp->A[m-2][d-1],dd_minusone);
/* make the LP bounded. */
dd_set(lp->A[m-1][d-1],dd_one);
/* objective is to maximize z. */
if (localdebug) {
fprintf(stderr,"dd_CreateLP_H_ImplicitLinearity: an new lp is\n");
dd_WriteLP(stderr,lp);
}
return lp;
}
dd_LPPtr dd_CreateLP_V_ImplicitLinearity(dd_MatrixPtr M)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+1;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=(M->colsize)+2;
/* Two more columns. This is different from the H-reprentation case */
/* The below must be modified for V-representation!!! */
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmax;
lp->eqnumber=linc; /* this records the number of equations */
lp->redcheck_extensive=dd_FALSE; /* this is default */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
dd_set(lp->A[i-1][0],dd_purezero); /* It is almost completely degerate LP */
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
} else {
dd_set(lp->A[i-1][d-1],dd_minusone); /* b_I x_0 + A_I x - 1 z >= 0 (z=x_d) */
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
} /*of j*/
} /*of i*/
dd_set(lp->A[m-2][0],dd_one); dd_set(lp->A[m-2][d-1],dd_minusone);
/* make the LP bounded. */
dd_set(lp->A[m-1][d-1],dd_one);
/* objective is to maximize z. */
if (localdebug) {
fprintf(stderr,"dd_CreateLP_V_ImplicitLinearity: an new lp is\n");
dd_WriteLP(stderr,lp);
}
return lp;
}
dd_LPPtr dd_CreateLP_H_Redundancy(dd_MatrixPtr M, dd_rowrange itest)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=M->colsize;
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_TRUE;
lp->objective = dd_LPmin;
lp->eqnumber=linc; /* this records the number of equations */
lp->redcheck_extensive=dd_FALSE; /* this is default */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 1; j <= M->colsize; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-1]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-1]);
if (j==1 && irowsize && dd_Nonzero(M->matrix[i-1][j-1])) lp->Homogeneous = dd_FALSE;
} /*of j*/
} /*of i*/
for (j = 1; j <= M->colsize; j++) {
dd_set(lp->A[m-1][j-1],M->matrix[itest-1][j-1]);
/* objective is to violate the inequality in question. */
} /*of j*/
dd_add(lp->A[itest-1][0],lp->A[itest-1][0],dd_one); /* relax the original inequality by one */
return lp;
}
dd_LPPtr dd_CreateLP_V_Redundancy(dd_MatrixPtr M, dd_rowrange itest)
{
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple. */
d=(M->colsize)+1;
/* One more column. This is different from the H-reprentation case */
/* The below must be modified for V-representation!!! */
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmin;
lp->eqnumber=linc; /* this records the number of equations */
lp->redcheck_extensive=dd_FALSE; /* this is default */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (i==itest){
dd_set(lp->A[i-1][0],dd_one); /* this is to make the LP bounded, ie. the min >= -1 */
} else {
dd_set(lp->A[i-1][0],dd_purezero); /* It is almost completely degerate LP */
}
if (set_member(i, M->linset)) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
} /*of j*/
} /*of i*/
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[m-1][j-1],M->matrix[itest-1][j-2]);
/* objective is to violate the inequality in question. */
} /*of j*/
dd_set(lp->A[m-1][0],dd_purezero); /* the constant term for the objective is zero */
if (localdebug) dd_WriteLP(stdout, lp);
return lp;
}
dd_LPPtr dd_CreateLP_V_SRedundancy(dd_MatrixPtr M, dd_rowrange itest)
{
/*
V-representation (=boundary problem)
g* = maximize
1^T b_{I-itest} x_0 + 1^T A_{I-itest} (the sum of slacks)
subject to
b_itest x_0 + A_itest x = 0 (the point has to lie on the boundary)
b_{I-itest} x_0 + A_{I-itest} x >= 0 (all nonlinearity generators in one side)
1^T b_{I-itest} x_0 + 1^T A_{I-itest} x <= 1 (to make an LP bounded)
b_L x_0 + A_L x = 0. (linearity generators)
The redundant row is strongly redundant if and only if g* is zero.
*/
dd_rowrange m, i, irev, linc;
dd_colrange d, j;
dd_LPPtr lp;
dd_boolean localdebug=dd_FALSE;
linc=set_card(M->linset);
m=M->rowsize+1+linc+2;
/* We represent each equation by two inequalities.
This is not the best way but makes the code simple.
Two extra constraints are for the first equation and the bouding inequality.
*/
d=(M->colsize)+1;
/* One more column. This is different from the H-reprentation case */
/* The below must be modified for V-representation!!! */
lp=dd_CreateLPData(M->objective, M->numbtype, m, d);
lp->Homogeneous = dd_FALSE;
lp->objective = dd_LPmax;
lp->eqnumber=linc; /* this records the number of equations */
irev=M->rowsize; /* the first row of the linc reversed inequalities. */
for (i = 1; i <= M->rowsize; i++) {
if (i==itest){
dd_set(lp->A[i-1][0],dd_purezero); /* this is a half of the boundary constraint. */
} else {
dd_set(lp->A[i-1][0],dd_purezero); /* It is almost completely degerate LP */
}
if (set_member(i, M->linset) || i==itest) {
irev=irev+1;
set_addelem(lp->equalityset,i); /* it is equality. */
/* the reversed row irev is not in the equality set. */
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[irev-1][j-1],M->matrix[i-1][j-2]);
} /*of j*/
if (localdebug) fprintf(stderr,"equality row %ld generates the reverse row %ld.\n",i,irev);
}
for (j = 2; j <= (M->colsize)+1; j++) {
dd_set(lp->A[i-1][j-1],M->matrix[i-1][j-2]);
dd_add(lp->A[m-1][j-1],lp->A[m-1][j-1],lp->A[i-1][j-1]); /* the objective is the sum of all ineqalities */
} /*of j*/
} /*of i*/
for (j = 2; j <= (M->colsize)+1; j++) {
dd_neg(lp->A[m-2][j-1],lp->A[m-1][j-1]);
/* to make an LP bounded. */
} /*of j*/
dd_set(lp->A[m-2][0],dd_one); /* the constant term for the bounding constraint is 1 */
if (localdebug) dd_WriteLP(stdout, lp);
return lp;
}
dd_boolean dd_Redundant(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
/* 092 */
{
/* Checks whether the row itest is redundant for the representation.
All linearity rows are not checked and considered NONredundant.
This code works for both H- and V-representations. A certificate is
given in the case of non-redundancy, showing a solution x violating only the itest
inequality for H-representation, a hyperplane RHS and normal (x_0, x) that
separates the itest from the rest. More explicitly, the LP to be setup is
H-representation
f* = minimize
b_itest + A_itest x
subject to
b_itest + 1 + A_itest x >= 0 (relaxed inequality to make an LP bounded)
b_{I-itest} + A_{I-itest} x >= 0 (all inequalities except for itest)
b_L + A_L x = 0. (linearity)
V-representation (=separation problem)
f* = minimize
b_itest x_0 + A_itest x
subject to
b_itest x_0 + A_itest x >= -1 (to make an LP bounded)
b_{I-itest} x_0 + A_{I-itest} x >= 0 (all nonlinearity generators except for itest in one side)
b_L x_0 + A_L x = 0. (linearity generators)
Here, the input matrix is considered as (b, A), i.e. b corresponds to the first column of input
and the row indices of input is partitioned into I and L where L is the set of linearity.
In both cases, the itest data is nonredundant if and only if the optimal value f* is negative.
The certificate has dimension one more for V-representation case.
*/
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
/* Create an LP data for redundancy checking */
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; jd; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th row is nonredundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th row is redundant.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_RedundantExtensive(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate,
dd_rowset *redset,dd_ErrorType *error)
/* 094 */
{
/* This uses the same LP construction as dd_Reduandant. But, while it is checking
the redundancy of itest, it also tries to find some other variable that are
redundant (i.e. forced to be nonnegative). This is expensive as it used
the complete tableau information at each DualSimplex pivot. The redset must
be initialized before this function is called.
*/
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
/* Create an LP data for redundancy checking */
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
lp->redcheck_extensive=dd_TRUE;
dd_LPSolve0(lp,dd_DualSimplex,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
set_copy(*redset,lp->redset_extra);
set_delelem(*redset, itest);
/* itest row might be redundant in the lp but this has nothing to do with its redundancy
in the original system M. Thus we must delete it. */
if (localdebug){
fprintf(stderr, "dd_RedundantExtensive: checking for %ld, extra redset with cardinality %ld (%ld)\n",itest,set_card(*redset),set_card(lp->redset_extra));
set_fwrite(stderr, *redset); fprintf(stderr, "\n");
}
lps=dd_CopyLPSolution(lp);
for (j=0; jd; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th row is nonredundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th row is redundant.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_rowset dd_RedundantRows(dd_MatrixPtr M, dd_ErrorType *error) /* 092 */
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_Arow cvec; /* certificate */
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
if (M->representation==dd_Generator){
d=(M->colsize)+1;
} else {
d=M->colsize;
}
Mcopy=dd_MatrixCopy(M);
dd_InitializeArow(d,&cvec);
set_initialize(&redset, m);
for (i=m; i>=1; i--) {
if (dd_Redundant(Mcopy, i, cvec, error)) {
if (localdebug) printf("dd_RedundantRows: the row %ld is redundant.\n", i);
set_addelem(redset, i);
dd_MatrixRowRemove(&Mcopy, i);
} else {
if (localdebug) printf("dd_RedundantRows: the row %ld is essential.\n", i);
}
if (*error!=dd_NoError) goto _L99;
}
_L99:
dd_FreeMatrix(Mcopy);
dd_FreeArow(d, cvec);
return redset;
}
dd_boolean dd_MatrixRedundancyRemove(dd_MatrixPtr *M, dd_rowset *redset,dd_rowindex *newpos, dd_ErrorType *error) /* 094 */
{
/* It returns the set of all redundant rows. This should be called after all
implicit linearity are recognized with dd_MatrixCanonicalizeLinearity.
*/
dd_rowrange i,k,m,m1;
dd_colrange d;
dd_rowset redset1;
dd_rowindex newpos1;
dd_MatrixPtr M1=NULL;
dd_Arow cvec; /* certificate */
dd_boolean success=dd_FALSE, localdebug=dd_FALSE;
m=(*M)->rowsize;
set_initialize(redset, m);
M1=dd_MatrixSortedUniqueCopy(*M,newpos);
for (i=1; i<=m; i++){
if ((*newpos)[i]<=0) set_addelem(*redset,i);
if (localdebug) printf(" %ld:%ld",i,(*newpos)[i]);
}
if (localdebug) printf("\n");
if ((*M)->representation==dd_Generator){
d=((*M)->colsize)+1;
} else {
d=(*M)->colsize;
}
m1=M1->rowsize;
if (localdebug){
fprintf(stderr,"dd_MatrixRedundancyRemove: By sorting, %ld rows have been removed. The remaining has %ld rows.\n",m-m1,m1);
/* dd_WriteMatrix(stdout,M1); */
}
dd_InitializeArow(d,&cvec);
set_initialize(&redset1, M1->rowsize);
k=1;
do {
if (dd_RedundantExtensive(M1, k, cvec, &redset1,error)) {
set_addelem(redset1, k);
dd_MatrixRowsRemove2(&M1,redset1,&newpos1);
for (i=1; i<=m; i++){
if ((*newpos)[i]>0){
if (set_member((*newpos)[i],redset1)){
set_addelem(*redset,i);
(*newpos)[i]=0; /* now the original row i is recognized redundant and removed from M1 */
} else {
(*newpos)[i]=newpos1[(*newpos)[i]]; /* update the new pos vector */
}
}
}
set_free(redset1);
set_initialize(&redset1, M1->rowsize);
if (localdebug) {
printf("dd_MatrixRedundancyRemove: the row %ld is redundant. The new matrix has %ld rows.\n", k, M1->rowsize);
/* dd_WriteMatrix(stderr, M1); */
}
free(newpos1);
} else {
if (set_card(redset1)>0) {
dd_MatrixRowsRemove2(&M1,redset1,&newpos1);
for (i=1; i<=m; i++){
if ((*newpos)[i]>0){
if (set_member((*newpos)[i],redset1)){
set_addelem(*redset,i);
(*newpos)[i]=0; /* now the original row i is recognized redundant and removed from M1 */
} else {
(*newpos)[i]=newpos1[(*newpos)[i]]; /* update the new pos vector */
}
}
}
set_free(redset1);
set_initialize(&redset1, M1->rowsize);
free(newpos1);
}
if (localdebug) {
printf("dd_MatrixRedundancyRemove: the row %ld is essential. The new matrix has %ld rows.\n", k, M1->rowsize);
/* dd_WriteMatrix(stderr, M1); */
}
k=k+1;
}
if (*error!=dd_NoError) goto _L99;
} while (k<=M1->rowsize);
if (localdebug) dd_WriteMatrix(stderr, M1);
success=dd_TRUE;
_L99:
dd_FreeMatrix(*M);
*M=M1;
dd_FreeArow(d, cvec);
set_free(redset1);
return success;
}
dd_boolean dd_SRedundant(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
/* 093a */
{
/* Checks whether the row itest is strongly redundant for the representation.
A row is strongly redundant in H-representation if every point in
the polyhedron satisfies it with strict inequality.
A row is strongly redundant in V-representation if this point is in
the interior of the polyhedron.
All linearity rows are not checked and considered NOT strongly redundant.
This code works for both H- and V-representations. A certificate is
given in the case of non-redundancy, showing a solution x violating only the itest
inequality for H-representation, a hyperplane RHS and normal (x_0, x) that
separates the itest from the rest. More explicitly, the LP to be setup is
H-representation
f* = minimize
b_itest + A_itest x
subject to
b_itest + 1 + A_itest x >= 0 (relaxed inequality to make an LP bounded)
b_{I-itest} + A_{I-itest} x >= 0 (all inequalities except for itest)
b_L + A_L x = 0. (linearity)
V-representation (=separation problem)
f* = minimize
b_itest x_0 + A_itest x
subject to
b_itest x_0 + A_itest x >= -1 (to make an LP bounded)
b_{I-itest} x_0 + A_{I-itest} x >= 0 (all nonlinearity generators except for itest in one side)
b_L x_0 + A_L x = 0. (linearity generators)
Here, the input matrix is considered as (b, A), i.e. b corresponds to the first column of input
and the row indices of input is partitioned into I and L where L is the set of linearity.
In H-representation, the itest data is strongly redundant if and only if the optimal value f* is positive.
In V-representation, the itest data is redundant if and only if the optimal value f* is zero (as the LP
is homogeneous and the optimal value is always non-positive). To recognize strong redundancy, one
can set up a second LP
V-representation (=boundary problem)
g* = maximize
1^T b_{I-itest} x_0 + 1^T A_{I-itest} (the sum of slacks)
subject to
b_itest x_0 + A_itest x = 0 (the point has to lie on the boundary)
b_{I-itest} x_0 + A_{I-itest} x >= 0 (all nonlinearity generators in one side)
1^T b_{I-itest} x_0 + 1^T A_{I-itest} x <= 1 (to make an LP bounded)
b_L x_0 + A_L x = 0. (linearity generators)
The redundant row is strongly redundant if and only if g* is zero.
The certificate has dimension one more for V-representation case.
*/
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and strong redundancy checking is skipped.\n",itest);
goto _L99;
}
/* Create an LP data for redundancy checking */
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; jd; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (localdebug){
printf("Optimum value:");
dd_WriteNumber(stdout, lps->optvalue);
printf("\n");
}
if (M->representation==dd_Inequality){
if (dd_Positive(lps->optvalue)){
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th inequality is strongly redundant.\n",itest);
} else {
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th inequality is not strongly redundant.\n",itest);
}
} else {
if (dd_Negative(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th point is not strongly redundant.\n",itest);
} else {
/* for V-representation, we have to solve another LP */
dd_FreeLPData(lp);
dd_FreeLPSolution(lps);
lp=dd_CreateLP_V_SRedundancy(M, itest);
dd_LPSolve(lp,dd_DualSimplex,&err);
lps=dd_CopyLPSolution(lp);
if (localdebug) dd_WriteLPResult(stdout,lp,err);
if (dd_Positive(lps->optvalue)){
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th point is not strongly redundant.\n",itest);
} else {
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th point is strongly redundant.\n",itest);
}
}
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_rowset dd_SRedundantRows(dd_MatrixPtr M, dd_ErrorType *error) /* 093a */
{
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_Arow cvec; /* certificate */
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
if (M->representation==dd_Generator){
d=(M->colsize)+1;
} else {
d=M->colsize;
}
Mcopy=dd_MatrixCopy(M);
dd_InitializeArow(d,&cvec);
set_initialize(&redset, m);
for (i=m; i>=1; i--) {
if (dd_SRedundant(Mcopy, i, cvec, error)) {
if (localdebug) printf("dd_SRedundantRows: the row %ld is strongly redundant.\n", i);
set_addelem(redset, i);
dd_MatrixRowRemove(&Mcopy, i);
} else {
if (localdebug) printf("dd_SRedundantRows: the row %ld is not strongly redundant.\n", i);
}
if (*error!=dd_NoError) goto _L99;
}
_L99:
dd_FreeMatrix(Mcopy);
dd_FreeArow(d, cvec);
return redset;
}
dd_rowset dd_RedundantRowsViaShooting(dd_MatrixPtr M, dd_ErrorType *error) /* 092 */
{
/*
For H-representation only and not quite reliable,
especially when floating-point arithmetic is used.
Use the ordinary (slower) method dd_RedundantRows.
*/
dd_rowrange i,m, ired, irow=0;
dd_colrange j,k,d;
dd_rowset redset;
dd_rowindex rowflag;
/* ith comp is negative if the ith inequality (i-1 st row) is redundant.
zero if it is not decided.
k > 0 if it is nonredundant and assigned to the (k-1)th row of M1.
*/
dd_MatrixPtr M1;
dd_Arow shootdir, cvec=NULL;
dd_LPPtr lp0, lp;
dd_LPSolutionPtr lps;
dd_ErrorType err;
dd_LPSolverType solver=dd_DualSimplex;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
d=M->colsize;
M1=dd_CreateMatrix(m,d);
M1->rowsize=0; /* cheat the rowsize so that smaller matrix can be stored */
set_initialize(&redset, m);
dd_InitializeArow(d, &shootdir);
dd_InitializeArow(d, &cvec);
rowflag=(long *)calloc(m+1, sizeof(long));
/* First find some (likely) nonredundant inequalities by Interior Point Find. */
lp0=dd_Matrix2LP(M, &err);
lp=dd_MakeLPforInteriorFinding(lp0);
dd_FreeLPData(lp0);
dd_LPSolve(lp, solver, &err); /* Solve the LP */
lps=dd_CopyLPSolution(lp);
if (dd_Positive(lps->optvalue)){
/* An interior point is found. Use rayshooting to find some nonredundant
inequalities. */
for (j=1; jsol, shootdir);
if (localdebug) printf("nonredundant row %3ld found by shooting.\n", ired);
if (ired>0 && rowflag[ired]<=0) {
irow++;
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
}
dd_neg(shootdir[j], dd_one); /* negative of the j-th unit vector */
ired=dd_RayShooting(M, lps->sol, shootdir);
if (localdebug) printf("nonredundant row %3ld found by shooting.\n", ired);
if (ired>0 && rowflag[ired]<=0) {
irow++;
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
}
}
M1->rowsize=irow;
if (localdebug) {
printf("The initial nonredundant set is:");
for (i=1; i<=m; i++) if (rowflag[i]>0) printf(" %ld", i);
printf("\n");
}
i=1;
while(i<=m){
if (rowflag[i]==0){ /* the ith inequality is not yet checked */
if (localdebug) fprintf(stderr, "Checking redundancy of %ld th inequality\n", i);
irow++; M1->rowsize=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[i-1][k-1]);
if (!dd_Redundant(M1, irow, cvec, &err)){
for (k=1; k<=d; k++) dd_sub(shootdir[k-1], cvec[k-1], lps->sol[k-1]);
ired=dd_RayShooting(M, lps->sol, shootdir);
rowflag[ired]=irow;
for (k=1; k<=d; k++) dd_set(M1->matrix[irow-1][k-1], M->matrix[ired-1][k-1]);
if (localdebug) {
fprintf(stderr, "The %ld th inequality is nonredundant for the subsystem\n", i);
fprintf(stderr, "The nonredundancy of %ld th inequality is found by shooting.\n", ired);
}
} else {
if (localdebug) fprintf(stderr, "The %ld th inequality is redundant for the subsystem and thus for the whole.\n", i);
rowflag[i]=-1;
set_addelem(redset, i);
i++;
}
} else {
i++;
}
} /* endwhile */
} else {
/* No interior point is found. Apply the standard LP technique. */
redset=dd_RedundantRows(M, error);
}
dd_FreeLPData(lp);
dd_FreeLPSolution(lps);
M1->rowsize=m; M1->colsize=d; /* recover the original sizes */
dd_FreeMatrix(M1);
dd_FreeArow(d, shootdir);
dd_FreeArow(d, cvec);
free(rowflag);
return redset;
}
dd_SetFamilyPtr dd_Matrix2Adjacency(dd_MatrixPtr M, dd_ErrorType *error) /* 093 */
{
/* This is to generate the (facet) graph of a polyheron (H) V-represented by M using LPs.
Since it does not use the representation conversion, it should work for a large
scale problem.
*/
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_SetFamilyPtr F=NULL;
m=M->rowsize;
d=M->colsize;
if (m<=0 ||d<=0) {
*error=dd_EmptyRepresentation;
goto _L999;
}
Mcopy=dd_MatrixCopy(M);
F=dd_CreateSetFamily(m, m);
for (i=1; i<=m; i++) {
if (!set_member(i, M->linset)){
set_addelem(Mcopy->linset, i);
redset=dd_RedundantRows(Mcopy, error); /* redset should contain all nonadjacent ones */
set_uni(redset, redset, Mcopy->linset); /* all linearity elements should be nonadjacent */
set_compl(F->set[i-1], redset); /* set the adjacency list of vertex i */
set_delelem(Mcopy->linset, i);
set_free(redset);
if (*error!=dd_NoError) goto _L99;
}
}
_L99:
dd_FreeMatrix(Mcopy);
_L999:
return F;
}
dd_SetFamilyPtr dd_Matrix2WeakAdjacency(dd_MatrixPtr M, dd_ErrorType *error) /* 093a */
{
/* This is to generate the weak-adjacency (facet) graph of a polyheron (H) V-represented by M using LPs.
Since it does not use the representation conversion, it should work for a large
scale problem.
*/
dd_rowrange i,m;
dd_colrange d;
dd_rowset redset;
dd_MatrixPtr Mcopy;
dd_SetFamilyPtr F=NULL;
m=M->rowsize;
d=M->colsize;
if (m<=0 ||d<=0) {
*error=dd_EmptyRepresentation;
goto _L999;
}
Mcopy=dd_MatrixCopy(M);
F=dd_CreateSetFamily(m, m);
for (i=1; i<=m; i++) {
if (!set_member(i, M->linset)){
set_addelem(Mcopy->linset, i);
redset=dd_SRedundantRows(Mcopy, error); /* redset should contain all weakly nonadjacent ones */
set_uni(redset, redset, Mcopy->linset); /* all linearity elements should be nonadjacent */
set_compl(F->set[i-1], redset); /* set the adjacency list of vertex i */
set_delelem(Mcopy->linset, i);
set_free(redset);
if (*error!=dd_NoError) goto _L99;
}
}
_L99:
dd_FreeMatrix(Mcopy);
_L999:
return F;
}
dd_boolean dd_ImplicitLinearity(dd_MatrixPtr M, dd_rowrange itest, dd_Arow certificate, dd_ErrorType *error)
/* 092 */
{
/* Checks whether the row itest is implicit linearity for the representation.
All linearity rows are not checked and considered non implicit linearity (dd_FALSE).
This code works for both H- and V-representations. A certificate is
given in the case of dd_FALSE, showing a feasible solution x satisfying the itest
strict inequality for H-representation, a hyperplane RHS and normal (x_0, x) that
separates the itest from the rest. More explicitly, the LP to be setup is
the same thing as redundancy case but with maximization:
H-representation
f* = maximize
b_itest + A_itest x
subject to
b_itest + 1 + A_itest x >= 0 (relaxed inequality. This is not necessary but kept for simplicity of the code)
b_{I-itest} + A_{I-itest} x >= 0 (all inequalities except for itest)
b_L + A_L x = 0. (linearity)
V-representation (=separation problem)
f* = maximize
b_itest x_0 + A_itest x
subject to
b_itest x_0 + A_itest x >= -1 (again, this is not necessary but kept for simplicity.)
b_{I-itest} x_0 + A_{I-itest} x >= 0 (all nonlinearity generators except for itest in one side)
b_L x_0 + A_L x = 0. (linearity generators)
Here, the input matrix is considered as (b, A), i.e. b corresponds to the first column of input
and the row indices of input is partitioned into I and L where L is the set of linearity.
In both cases, the itest data is implicit linearity if and only if the optimal value f* is nonpositive.
The certificate has dimension one more for V-representation case.
*/
dd_colrange j;
dd_LPPtr lp;
dd_LPSolutionPtr lps;
dd_ErrorType err=dd_NoError;
dd_boolean answer=dd_FALSE,localdebug=dd_FALSE;
*error=dd_NoError;
if (set_member(itest, M->linset)){
if (localdebug) printf("The %ld th row is linearity and redundancy checking is skipped.\n",itest);
goto _L99;
}
/* Create an LP data for redundancy checking */
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_Redundancy(M, itest);
} else {
lp=dd_CreateLP_H_Redundancy(M, itest);
}
lp->objective = dd_LPmax; /* the lp->objective is set by CreateLP* to LPmin */
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
lps=dd_CopyLPSolution(lp);
for (j=0; jd; j++) {
dd_set(certificate[j], lps->sol[j]);
}
if (lps->LPS==dd_Optimal && dd_EqualToZero(lps->optvalue)){
answer=dd_TRUE;
if (localdebug) fprintf(stderr,"==> %ld th data is an implicit linearity.\n",itest);
} else {
answer=dd_FALSE;
if (localdebug) fprintf(stderr,"==> %ld th data is not an implicit linearity.\n",itest);
}
dd_FreeLPSolution(lps);
}
_L999:
dd_FreeLPData(lp);
_L99:
return answer;
}
int dd_FreeOfImplicitLinearity(dd_MatrixPtr M, dd_Arow certificate, dd_rowset *imp_linrows, dd_ErrorType *error)
/* 092 */
{
/* Checks whether the matrix M constains any implicit linearity at all.
It returns 1 if it is free of any implicit linearity. This means that
the present linearity rows define the linearity correctly. It returns
nonpositive values otherwise.
H-representation
f* = maximize z
subject to
b_I + A_I x - 1 z >= 0
b_L + A_L x = 0 (linearity)
z <= 1.
V-representation (=separation problem)
f* = maximize z
subject to
b_I x_0 + A_I x - 1 z >= 0 (all nonlinearity generators in one side)
b_L x_0 + A_L x = 0 (linearity generators)
z <= 1.
Here, the input matrix is considered as (b, A), i.e. b corresponds to the first column of input
and the row indices of input is partitioned into I and L where L is the set of linearity.
In both cases, any implicit linearity exists if and only if the optimal value f* is nonpositive.
The certificate has dimension one more for V-representation case.
*/
dd_LPPtr lp;
dd_rowrange i,m;
dd_colrange j,d1;
dd_ErrorType err=dd_NoError;
dd_Arow cvec; /* certificate for implicit linearity */
int answer=0,localdebug=dd_FALSE;
*error=dd_NoError;
/* Create an LP data for redundancy checking */
if (M->representation==dd_Generator){
lp=dd_CreateLP_V_ImplicitLinearity(M);
} else {
lp=dd_CreateLP_H_ImplicitLinearity(M);
}
dd_LPSolve(lp,dd_choiceRedcheckAlgorithm,&err);
if (err!=dd_NoError){
*error=err;
goto _L999;
} else {
for (j=0; jd; j++) {
dd_set(certificate[j], lp->sol[j]);
}
if (localdebug) dd_WriteLPResult(stderr,lp,err);
/* *posset contains a set of row indices that are recognized as nonlinearity. */
if (localdebug) {
fprintf(stderr,"==> The following variables are not implicit linearity:\n");
set_fwrite(stderr, lp->posset_extra);
fprintf(stderr,"\n");
}
if (M->representation==dd_Generator){
d1=(M->colsize)+1;
} else {
d1=M->colsize;
}
m=M->rowsize;
dd_InitializeArow(d1,&cvec);
set_initialize(imp_linrows,m);
if (lp->LPS==dd_Optimal){
if (dd_Positive(lp->optvalue)){
answer=1;
if (localdebug) fprintf(stderr,"==> The matrix has no implicit linearity.\n");
} else if (dd_Negative(lp->optvalue)) {
answer=-1;
if (localdebug) fprintf(stderr,"==> The matrix defines the trivial system.\n");
} else {
answer=0;
if (localdebug) fprintf(stderr,"==> The matrix has some implicit linearity.\n");
}
} else {
answer=-2;
if (localdebug) fprintf(stderr,"==> The LP fails.\n");
}
if (answer==0){
/* List the implicit linearity rows */
for (i=m; i>=1; i--) {
if (!set_member(i,lp->posset_extra)) {
if (dd_ImplicitLinearity(M, i, cvec, error)) {
set_addelem(*imp_linrows, i);
if (localdebug) {
fprintf(stderr," row %ld is implicit linearity\n",i);
fprintf(stderr,"\n");
}
}
if (*error!=dd_NoError) goto _L999;
}
}
} /* end of if (answer==0) */
if (answer==-1) {
for (i=m; i>=1; i--) set_addelem(*imp_linrows, i);
} /* all rows are considered implicit linearity */
dd_FreeArow(d1,cvec);
}
_L999:
dd_FreeLPData(lp);
return answer;
}
dd_rowset dd_ImplicitLinearityRows(dd_MatrixPtr M, dd_ErrorType *error) /* 092 */
{
dd_colrange d;
dd_rowset imp_linset;
dd_Arow cvec; /* certificate */
int foi;
dd_boolean localdebug=dd_FALSE;
if (M->representation==dd_Generator){
d=(M->colsize)+2;
} else {
d=M->colsize+1;
}
dd_InitializeArow(d,&cvec);
if (localdebug) fprintf(stdout, "\ndd_ImplicitLinearityRows: Check whether the system contains any implicit linearity.\n");
foi=dd_FreeOfImplicitLinearity(M, cvec, &imp_linset, error);
if (localdebug){
switch (foi) {
case 1:
fprintf(stdout, " It is free of implicit linearity.\n");
break;
case 0:
fprintf(stdout, " It is not free of implicit linearity.\n");
break;
case -1:
fprintf(stdout, " The input system is trivial (i.e. the empty H-polytope or the V-rep of the whole space.\n");
break;
default:
fprintf(stdout, " The LP was not solved correctly.\n");
break;
}
}
if (localdebug){
fprintf(stderr, " Implicit linearity rows are:\n");
set_fwrite(stderr,imp_linset);
fprintf(stderr, "\n");
}
dd_FreeArow(d, cvec);
return imp_linset;
}
dd_boolean dd_MatrixCanonicalizeLinearity(dd_MatrixPtr *M, dd_rowset *impl_linset,dd_rowindex *newpos,
dd_ErrorType *error) /* 094 */
{
/* This is to recongnize all implicit linearities, and put all linearities at the top of
the matrix. All implicit linearities will be returned by *impl_linset.
*/
dd_rowset linrows,ignoredrows,basisrows;
dd_colset ignoredcols,basiscols;
dd_rowrange i,k,m;
dd_rowindex newpos1;
dd_boolean success=dd_FALSE;
linrows=dd_ImplicitLinearityRows(*M, error);
if (*error!=dd_NoError) goto _L99;
m=(*M)->rowsize;
set_uni((*M)->linset, (*M)->linset, linrows);
/* add the implicit linrows to the explicit linearity rows */
/* To remove redundancy of the linearity part,
we need to compute a basis of the linearity part. */
set_initialize(&ignoredrows, (*M)->rowsize);
set_initialize(&ignoredcols, (*M)->colsize);
set_compl(ignoredrows, (*M)->linset);
dd_MatrixRank(*M,ignoredrows,ignoredcols,&basisrows,&basiscols);
set_diff(ignoredrows, (*M)->linset, basisrows);
dd_MatrixRowsRemove2(M,ignoredrows,newpos);
dd_MatrixShiftupLinearity(M,&newpos1);
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) {
(*newpos)[i]=newpos1[k];
}
}
*impl_linset=linrows;
success=dd_TRUE;
free(newpos1);
set_free(basisrows);
set_free(basiscols);
set_free(ignoredrows);
set_free(ignoredcols);
_L99:
return success;
}
dd_boolean dd_MatrixCanonicalize(dd_MatrixPtr *M, dd_rowset *impl_linset, dd_rowset *redset,
dd_rowindex *newpos, dd_ErrorType *error) /* 094 */
{
/* This is to find a canonical representation of a matrix *M by
recognizing all implicit linearities and all redundancies.
All implicit linearities will be returned by *impl_linset and
redundancies will be returned by *redset.
*/
dd_rowrange i,k,m;
dd_rowindex newpos1,revpos;
dd_rowset redset1;
dd_boolean success=dd_TRUE;
m=(*M)->rowsize;
set_initialize(redset, m);
revpos=(long *)calloc(m+1,sizeof(long));
success=dd_MatrixCanonicalizeLinearity(M, impl_linset, newpos, error);
if (!success) goto _L99;
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) revpos[k]=i; /* inverse of *newpos[] */
}
success=dd_MatrixRedundancyRemove(M, &redset1, &newpos1, error); /* 094 */
if (!success) goto _L99;
for (i=1; i<=m; i++){
k=(*newpos)[i];
if (k>0) {
(*newpos)[i]=newpos1[k];
if (newpos1[k]<0) (*newpos)[i]=-revpos[-newpos1[k]]; /* update the certificate of its duplicate removal. */
if (set_member(k,redset1)) set_addelem(*redset, i);
}
}
_L99:
set_free(redset1);
free(newpos1);
free(revpos);
return success;
}
dd_boolean dd_ExistsRestrictedFace(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_ErrorType *err)
/* 0.94 */
{
/* This function checkes if there is a point that satifies all the constraints of
the matrix M (interpreted as an H-representation) with additional equality contraints
specified by R and additional strict inequality constraints specified by S.
The set S is supposed to be disjoint from both R and M->linset. When it is not,
the set S will be considered as S\(R U M->linset).
*/
dd_boolean answer=dd_FALSE;
dd_LPPtr lp=NULL;
/*
printf("\n--- ERF ---\n");
printf("R = "); set_write(R);
printf("S = "); set_write(S);
*/
lp=dd_Matrix2Feasibility2(M, R, S, err);
if (*err!=dd_NoError) goto _L99;
/* Solve the LP by cdd LP solver. */
dd_LPSolve(lp, dd_DualSimplex, err); /* Solve the LP */
if (*err!=dd_NoError) goto _L99;
if (lp->LPS==dd_Optimal && dd_Positive(lp->optvalue)) {
answer=dd_TRUE;
}
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_ExistsRestrictedFace2(dd_MatrixPtr M, dd_rowset R, dd_rowset S, dd_LPSolutionPtr *lps, dd_ErrorType *err)
/* 0.94 */
{
/* This function checkes if there is a point that satifies all the constraints of
the matrix M (interpreted as an H-representation) with additional equality contraints
specified by R and additional strict inequality constraints specified by S.
The set S is supposed to be disjoint from both R and M->linset. When it is not,
the set S will be considered as S\(R U M->linset).
This function returns a certificate of the answer in terms of the associated LP solutions.
*/
dd_boolean answer=dd_FALSE;
dd_LPPtr lp=NULL;
/*
printf("\n--- ERF ---\n");
printf("R = "); set_write(R);
printf("S = "); set_write(S);
*/
lp=dd_Matrix2Feasibility2(M, R, S, err);
if (*err!=dd_NoError) goto _L99;
/* Solve the LP by cdd LP solver. */
dd_LPSolve(lp, dd_DualSimplex, err); /* Solve the LP */
if (*err!=dd_NoError) goto _L99;
if (lp->LPS==dd_Optimal && dd_Positive(lp->optvalue)) {
answer=dd_TRUE;
}
(*lps)=dd_CopyLPSolution(lp);
dd_FreeLPData(lp);
_L99:
return answer;
}
dd_boolean dd_FindRelativeInterior(dd_MatrixPtr M, dd_rowset *ImL, dd_rowset *Lbasis, dd_LPSolutionPtr *lps, dd_ErrorType *err)
/* 0.94 */
{
/* This function computes a point in the relative interior of the H-polyhedron given by M.
Even the representation is V-representation, it simply interprete M as H-representation.
lps returns the result of solving an LP whose solution is a relative interior point.
ImL returns all row indices of M that are implicit linearities, i.e. their inqualities
are satisfied by equality by all points in the polyhedron. Lbasis returns a row basis
of the submatrix of M consisting of all linearities and implicit linearities. This means
that the dimension of the polyhedron is M->colsize - set_card(Lbasis) -1.
*/
dd_rowset S;
dd_colset T, Lbasiscols;
dd_boolean success=dd_FALSE;
dd_rowrange i;
*ImL=dd_ImplicitLinearityRows(M, err);
if (*err!=dd_NoError) goto _L99;
set_initialize(&S, M->rowsize); /* the empty set */
for (i=1; i <=M->rowsize; i++) {
if (!set_member(i, M->linset) && !set_member(i, *ImL)){
set_addelem(S, i); /* all nonlinearity rows go to S */
}
}
if (dd_ExistsRestrictedFace2(M, *ImL, S, lps, err)){
/* printf("a relative interior point found\n"); */
success=dd_TRUE;
}
set_initialize(&T, M->colsize); /* empty set */
dd_MatrixRank(M,S,T,Lbasis,&Lbasiscols); /* the rank of the linearity submatrix of M. */
set_free(S);
set_free(T);
set_free(Lbasiscols);
_L99:
return success;
}
dd_rowrange dd_RayShooting(dd_MatrixPtr M, dd_Arow p, dd_Arow r)
{
/* 092, find the first inequality "hit" by a ray from an intpt. */
dd_rowrange imin=-1,i,m;
dd_colrange j, d;
dd_Arow vecmin, vec;
mytype min,t1,t2,alpha, t1min;
dd_boolean started=dd_FALSE;
dd_boolean localdebug=dd_FALSE;
m=M->rowsize;
d=M->colsize;
if (!dd_Equal(dd_one, p[0])){
fprintf(stderr, "Warning: RayShooting is called with a point with first coordinate not 1.\n");
dd_set(p[0],dd_one);
}
if (!dd_EqualToZero(r[0])){
fprintf(stderr, "Warning: RayShooting is called with a direction with first coordinate not 0.\n");
dd_set(r[0],dd_purezero);
}
dd_init(alpha); dd_init(min); dd_init(t1); dd_init(t2); dd_init(t1min);
dd_InitializeArow(d,&vecmin);
dd_InitializeArow(d,&vec);
for (i=1; i<=m; i++){
dd_InnerProduct(t1, d, M->matrix[i-1], p);
if (dd_Positive(t1)) {
dd_InnerProduct(t2, d, M->matrix[i-1], r);
dd_div(alpha, t2, t1);
if (!started){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1); /* store the denominator. */
started=dd_TRUE;
if (localdebug) {
fprintf(stderr," Level 1: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
} else {
if (dd_Smaller(alpha, min)){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1); /* store the denominator. */
if (localdebug) {
fprintf(stderr," Level 2: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
} else {
if (dd_Equal(alpha, min)) { /* tie break */
for (j=1; j<= d; j++){
dd_div(vecmin[j-1], M->matrix[imin-1][j-1], t1min);
dd_div(vec[j-1], M->matrix[i-1][j-1], t1);
}
if (dd_LexSmaller(vec,vecmin, d)){
imin=i; dd_set(min, alpha);
dd_set(t1min, t1); /* store the denominator. */
if (localdebug) {
fprintf(stderr," Level 3: imin = %ld and min = ", imin);
dd_WriteNumber(stderr, min);
fprintf(stderr,"\n");
}
}
}
}
}
}
}
dd_clear(alpha); dd_clear(min); dd_clear(t1); dd_clear(t2); dd_clear(t1min);
dd_FreeArow(d, vecmin);
dd_FreeArow(d, vec);
return imin;
}
#ifdef GMPRATIONAL
void dd_BasisStatusMaximize(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowset equalityset,
dd_rowrange objrow,dd_colrange rhscol,ddf_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol,dd_rowset posset, ddf_colindex nbindex,
ddf_rowrange re,ddf_colrange se, dd_colrange *nse, long *pivots, int *found, int *LPScorrect)
/* This is just to check whether the status LPS of the basis given by
nbindex with extra certificates se or re is correct. It is done
by recomputing the basis inverse matrix T. It does not solve the LP
when the status *LPS is undecided. Thus the input is
m_size, d_size, A, equalityset, LPS, nbindex, re and se.
Other values will be recomputed from scratch.
The main purpose of the function is to verify the correctness
of the result of floating point computation with the GMP rational
arithmetics.
*/
{
long pivots0,pivots1,fbasisrank;
dd_rowrange i,is;
dd_colrange s,senew,j;
static dd_rowindex bflag;
static long mlast=0;
static dd_rowindex OrderVector; /* the permutation vector to store a preordered row indices */
unsigned int rseed=1;
mytype val;
dd_colindex nbtemp;
dd_LPStatusType ddlps;
dd_boolean localdebug=dd_FALSE;
if (dd_debug) localdebug=dd_debug;
if (localdebug){
printf("\nEvaluating dd_BasisStatusMaximize:\n");
}
dd_init(val);
nbtemp=(long *) calloc(d_size+1,sizeof(long));
for (i=0; i<= 4; i++) pivots[i]=0;
if (bflag==NULL || mlast!=m_size){
if (mlast!=m_size && mlast>0) {
free(bflag); /* called previously with different m_size */
free(OrderVector);
}
bflag=(long *) calloc(m_size+1,sizeof(long));
OrderVector=(long *)calloc(m_size+1,sizeof(long));
/* initialize only for the first time or when a larger space is needed */
mlast=m_size;
}
/* Initializing control variables. */
dd_ComputeRowOrderVector2(m_size,d_size,A,OrderVector,dd_MinIndex,rseed);
pivots1=0;
dd_ResetTableau(m_size,d_size,T,nbtemp,bflag,objrow,rhscol);
if (localdebug){
printf("\nnbindex:");
for (j=1; j<=d_size; j++) printf(" %ld", nbindex[j]);
printf("\n");
printf("re = %ld, se=%ld\n", re, se);
}
is=nbindex[se];
if (localdebug) printf("se=%ld, is=%ld\n", se, is);
fbasisrank=d_size-1;
for (j=1; j<=d_size; j++){
if (nbindex[j]<0) fbasisrank=fbasisrank-1;
/* fbasisrank=the basis rank computed by floating-point */
}
if (fbasisrank0) { /* i is nonbasic variable */
dd_TableauEntry(&val,m_size,d_size,A,T,objrow,bflag[i]);
if (dd_Positive(val)) {
if (localdebug) printf("Reduced cost entry for %ld is positive\n", i);
*LPScorrect=dd_FALSE;
break;
}
}
};
break;
case dd_Inconsistent:
for (j=1; j<=d_size; j++){
dd_TableauEntry(&val,m_size,d_size,A,T,re,j);
if (j==rhscol){
if (dd_Nonnegative(val)){
if (localdebug) printf("RHS entry for %ld is nonnegative\n", re);
*LPScorrect=dd_FALSE;
break;
}
} else if (dd_Positive(val)){
if (localdebug) printf("the row entry for(%ld, %ld) is positive\n", re, j);
*LPScorrect=dd_FALSE;
break;
}
};
break;
case dd_DualInconsistent:
for (i=1; i<=m_size; i++){
dd_TableauEntry(&val,m_size,d_size,A,T,i,bflag[is]);
if (i==objrow){
if (dd_Nonpositive(val)){
if (localdebug) printf("Reduced cost entry for %ld is nonpositive\n", bflag[is]);
*LPScorrect=dd_FALSE;
break;
}
} else if (dd_Negative(val)){
if (localdebug) printf("the column entry for(%ld, %ld) is positive\n", i, bflag[is]);
*LPScorrect=dd_FALSE;
break;
}
};
break;
;
default: break;
}
ddlps=LPSf2LPS(LPS);
dd_SetSolutions(m_size,d_size,A,T,
objrow,rhscol,ddlps,optvalue,sol,dsol,posset,nbindex,re,senew,bflag);
*nse=senew;
_L99:
dd_clear(val);
free(nbtemp);
}
void dd_BasisStatusMinimize(dd_rowrange m_size,dd_colrange d_size,
dd_Amatrix A,dd_Bmatrix T,dd_rowset equalityset,
dd_rowrange objrow,dd_colrange rhscol,ddf_LPStatusType LPS,
mytype *optvalue,dd_Arow sol,dd_Arow dsol, dd_rowset posset, ddf_colindex nbindex,
ddf_rowrange re,ddf_colrange se,dd_colrange *nse,long *pivots, int *found, int *LPScorrect)
{
dd_colrange j;
for (j=1; j<=d_size; j++) dd_neg(A[objrow-1][j-1],A[objrow-1][j-1]);
dd_BasisStatusMaximize(m_size,d_size,A,T,equalityset, objrow,rhscol,
LPS,optvalue,sol,dsol,posset,nbindex,re,se,nse,pivots,found,LPScorrect);
dd_neg(*optvalue,*optvalue);
for (j=1; j<=d_size; j++){
if (LPS!=dd_Inconsistent) {
/* Inconsistent certificate stays valid for minimization, 0.94e */
dd_neg(dsol[j-1],dsol[j-1]);
}
dd_neg(A[objrow-1][j-1],A[objrow-1][j-1]);
}
}
#endif
/* end of cddlp.c */
pplacer-1.1.alpha19/cdd_src/cddmp.c 0000664 0000000 0000000 00000010162 13031546015 0017071 0 ustar 00root root 0000000 0000000 /* cddmp.c (cddlib arithmetic operations using gmp)
Copyright: Komei Fukuda 2000, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* 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 of the License, or
(at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "setoper.h" /* set operation library header (Ver. March 16,1995 or later) */
#include "cdd.h"
void dd_set_global_constants()
{
dd_init(dd_zero);
dd_init(dd_minuszero);
dd_init(dd_one);
dd_init(dd_minusone);
dd_init(dd_purezero);
time(&dd_statStartTime); /* cddlib starting time */
dd_statBApivots=0; /* basis finding pivots */
dd_statCCpivots=0; /* criss-cross pivots */
dd_statDS1pivots=0; /* phase 1 pivots */
dd_statDS2pivots=0; /* phase 2 pivots */
dd_statACpivots=0; /* anticycling (cc) pivots */
dd_choiceLPSolverDefault=dd_DualSimplex; /* Default LP solver Algorithm */
dd_choiceRedcheckAlgorithm=dd_DualSimplex; /* Redundancy Checking Algorithm */
dd_choiceLexicoPivotQ=dd_TRUE; /* whether to use the lexicographic pivot */
#if defined GMPRATIONAL
dd_statBSpivots=0; /* basis status checking pivots */
mpq_set_ui(dd_zero,0U,1U);
mpq_set_ui(dd_purezero,0U,1U);
mpq_set_ui(dd_one,1U,1U);
mpq_set_si(dd_minusone,-1L,1U);
ddf_set_global_constants();
#elif defined GMPFLOAT
mpf_set_d(dd_zero,dd_almostzero);
mpf_set_ui(dd_purezero,0U);
mpf_set_ui(dd_one,1U);
mpf_set_si(dd_minusone,-1L,1U);
#else
dd_zero[0]= dd_almostzero; /*real zero */
dd_purezero[0]= 0.0;
dd_one[0]= 1L;
dd_minusone[0]= -1L;
#endif
dd_neg(dd_minuszero,dd_zero);
}
void dd_free_global_constants()
{
dd_clear(dd_zero);
dd_clear(dd_minuszero);
dd_clear(dd_one);
dd_clear(dd_minusone);
dd_clear(dd_purezero);
time(&dd_statStartTime); /* cddlib starting time */
dd_statBApivots=0; /* basis finding pivots */
dd_statCCpivots=0; /* criss-cross pivots */
dd_statDS1pivots=0; /* phase 1 pivots */
dd_statDS2pivots=0; /* phase 2 pivots */
dd_statACpivots=0; /* anticycling (cc) pivots */
dd_choiceLPSolverDefault=dd_DualSimplex; /* Default LP solver Algorithm */
dd_choiceRedcheckAlgorithm=dd_DualSimplex; /* Redundancy Checking Algorithm */
dd_choiceLexicoPivotQ=dd_TRUE; /* whether to use the lexicographic pivot */
#if defined GMPRATIONAL
dd_statBSpivots=0; /* basis status checking pivots */
ddf_free_global_constants();
#endif
}
#if defined GMPRATIONAL
void ddd_mpq_set_si(mytype a,signed long b)
{
mpz_t nz, dz;
mpz_init(nz); mpz_init(dz);
mpz_set_si(nz, b);
mpz_set_ui(dz, 1U);
mpq_set_num(a, nz);
mpq_set_den(a, dz);
mpz_clear(nz); mpz_clear(dz);
}
#endif
#if defined dd_CDOUBLE
void ddd_init(mytype a)
{
a[0]=0L;
}
void ddd_clear(mytype a)
{
/* a[0]=0L; */
}
void ddd_set(mytype a,mytype b)
{
a[0]=b[0];
}
void ddd_set_d(mytype a,double b)
{
a[0]=b;
}
void ddd_set_si(mytype a,signed long b)
{
a[0]=(double)b;
}
void ddd_set_si2(mytype a,signed long b, unsigned long c)
{
a[0]=(double)b/(double)c;
}
void ddd_add(mytype a,mytype b,mytype c)
{
a[0]=b[0]+c[0];
}
void ddd_sub(mytype a,mytype b,mytype c)
{
a[0]=b[0]-c[0];
}
void ddd_mul(mytype a,mytype b,mytype c)
{
a[0]=b[0]*c[0];
}
void ddd_div(mytype a,mytype b,mytype c)
{
a[0]=b[0]/c[0];
}
void ddd_neg(mytype a,mytype b)
{
a[0]=-b[0];
}
void ddd_inv(mytype a,mytype b)
{
a[0]=1/b[0];
}
int ddd_cmp(mytype a,mytype b)
{
if (a[0]-b[0]>0) return 1;
else if (a[0]-b[0]>=0) return 0;
else return -1;
}
int ddd_sgn(mytype a)
{
if (a[0]>0) return 1;
else if (a[0]>=0) return 0;
else return -1;
}
double ddd_get_d(mytype a)
{
return a[0];
}
#endif
/* end of cddmp.h */
pplacer-1.1.alpha19/cdd_src/cddmp.h 0000664 0000000 0000000 00000011125 13031546015 0017076 0 ustar 00root root 0000000 0000000 /* cddmp.h (cddlib arithmetic operations using gmp)
Copyright: Komei Fukuda 2000, fukuda@ifor.math.ethz.ch
Version 0.94f, February 7, 2008
*/
/* 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 of the License, or
(at your option) any later version.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __CDDMP_H
#define __CDDMP_H
#endif /* __CDDMP_H */
/**********************************/
/* MACROS */
/* dependent on mp implementation */
/**********************************/
#if defined GMPRATIONAL
#include "gmp.h"
#define dd_ARITHMETIC "GMP rational"
#define dd_init(a) mpq_init(a)
#define dd_clear(a) mpq_clear(a)
#define dd_set(a, b) mpq_set(a,b)
#define dd_set_si(a, b) ddd_mpq_set_si(a,b) /* defined in cddgmp.c */
#define dd_set_si2(a, b, c) mpq_set_si(a,b,c) /* gmp 3.1 or higher */
#define dd_add(a, b, c) mpq_add(a,b,c)
#define dd_sub(a, b, c) mpq_sub(a,b,c)
#define dd_mul(a, b, c) mpq_mul(a,b,c)
#define dd_div(a, b, c) mpq_div(a,b,c)
#define dd_neg(a, b) mpq_neg(a,b)
#define dd_inv(a, b) mpq_inv(a,b)
#define dd_cmp(a, b) mpq_cmp(a,b)
/* returns pos if a>b, 0 if a=b, negative if ab, 0 if a=b, negative if ab, 0 if a=b, negative if a