blob: e22643f374503e90d85085183ff634362949e3a5 [file] [log] [blame]
Austin Schuh085eab92020-11-26 13:54:51 -08001#!/usr/bin/python3
brians343bc112013-02-10 01:53:46 +00002"""Wrapper around libcdd, a polytope manipulation library."""
3
4__author__ = 'Austin Schuh (austin.linux@gmail.com)'
5
6import ctypes
Campbell Crowley15e4d7e2015-11-21 18:12:48 -08007import os
Brian Silvermandc3748d2014-03-30 12:41:52 -07008import sys
brians343bc112013-02-10 01:53:46 +00009
brians343bc112013-02-10 01:53:46 +000010# Load and init libcdd. libcdd is a C library that implements algorithm to
11# manipulate half space and vertex representations of polytopes.
12# Unfortunately, the library was compiled with C++ even though it has a lot of C
13# code in it, so all the symbol names are mangled. Ug.
Campbell Crowley15e4d7e2015-11-21 18:12:48 -080014libcdd = None
15for path in os.environ.get('PYTHONPATH').split(':'):
Austin Schuh085eab92020-11-26 13:54:51 -080016 try:
Ravago Jones26f7ad02021-02-05 15:45:59 -080017 libcdd = ctypes.cdll.LoadLibrary(
18 os.path.join(path, 'third_party/cddlib/_cddlib.so'))
Austin Schuh085eab92020-11-26 13:54:51 -080019 except OSError:
20 pass
Campbell Crowley15e4d7e2015-11-21 18:12:48 -080021
22assert libcdd is not None, 'Failed to find _cddlib.so'
23
Austin Schuhbf9d6502015-09-11 23:59:15 -070024libcdd.dd_set_global_constants()
brians343bc112013-02-10 01:53:46 +000025
26# The variable type mytype that libcdd defines (double[1])
27# See http://docs.python.org/2/library/ctypes.html#arrays for the documentation
28# explaining why ctypes.c_double * 1 => double[1]
29# libcdd defines mytype to various things so it can essentially template its
30# functions. What a weird library.
31mytype = ctypes.c_double * 1
32
33
34# Forward declaration for the polyhedra data structure.
35class dd_polyhedradata(ctypes.Structure):
Austin Schuh085eab92020-11-26 13:54:51 -080036 pass
brians343bc112013-02-10 01:53:46 +000037
38
39# Definition of dd_matrixdata
40class dd_matrixdata(ctypes.Structure):
Austin Schuh085eab92020-11-26 13:54:51 -080041 _fields_ = [
42 ("rowsize", ctypes.c_long),
43 ("linset", ctypes.POINTER(ctypes.c_ulong)),
44 ("colsize", ctypes.c_long),
45 ("representation", ctypes.c_int),
46 ("numbtype", ctypes.c_int),
47 ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
48 ("objective", ctypes.c_int),
49 ("rowvec", ctypes.POINTER(mytype)),
50 ]
brians343bc112013-02-10 01:53:46 +000051
Ravago Jones26f7ad02021-02-05 15:45:59 -080052
brians343bc112013-02-10 01:53:46 +000053# Define the input and output types for a bunch of libcdd functions.
Austin Schuhbf9d6502015-09-11 23:59:15 -070054libcdd.dd_CreateMatrix.restype = ctypes.POINTER(dd_matrixdata)
55libcdd.ddd_get_d.argtypes = [mytype]
56libcdd.ddd_get_d.restype = ctypes.c_double
brians343bc112013-02-10 01:53:46 +000057
Ravago Jones26f7ad02021-02-05 15:45:59 -080058libcdd.dd_CopyGenerators.argtypes = [ctypes.POINTER(dd_polyhedradata)]
Austin Schuhbf9d6502015-09-11 23:59:15 -070059libcdd.dd_CopyGenerators.restype = ctypes.POINTER(dd_matrixdata)
brians343bc112013-02-10 01:53:46 +000060
Austin Schuhbf9d6502015-09-11 23:59:15 -070061libcdd.dd_DDMatrix2Poly.argtypes = [
brians343bc112013-02-10 01:53:46 +000062 ctypes.POINTER(dd_matrixdata),
63 ctypes.POINTER(ctypes.c_int)
64]
Ravago Jones26f7ad02021-02-05 15:45:59 -080065libcdd.dd_DDMatrix2Poly.restype = (ctypes.POINTER(dd_polyhedradata))
brians343bc112013-02-10 01:53:46 +000066
Ravago Jones26f7ad02021-02-05 15:45:59 -080067libcdd.dd_FreeMatrix.argtypes = [ctypes.POINTER(dd_matrixdata)]
brians343bc112013-02-10 01:53:46 +000068
Ravago Jones26f7ad02021-02-05 15:45:59 -080069libcdd.dd_FreePolyhedra.argtypes = [ctypes.POINTER(dd_polyhedradata)]
brians343bc112013-02-10 01:53:46 +000070
Ravago Jones26f7ad02021-02-05 15:45:59 -080071libcdd.ddd_set_d.argtypes = [mytype, ctypes.c_double]
brians343bc112013-02-10 01:53:46 +000072
73# Various enums.
74DD_INEQUALITY = 1
75DD_REAL = 1
76DD_NO_ERRORS = 17
77
78
79def dd_CreateMatrix(rows, cols):
Austin Schuh085eab92020-11-26 13:54:51 -080080 return libcdd.dd_CreateMatrix(ctypes.c_long(rows), ctypes.c_long(cols))
brians343bc112013-02-10 01:53:46 +000081
82
83def dd_set_d(mytype_address, double_value):
Austin Schuh085eab92020-11-26 13:54:51 -080084 libcdd.ddd_set_d(mytype_address, ctypes.c_double(double_value))
brians343bc112013-02-10 01:53:46 +000085
86
87def dd_CopyGenerators(polyhedraptr):
Austin Schuh085eab92020-11-26 13:54:51 -080088 return libcdd.dd_CopyGenerators(polyhedraptr)
brians343bc112013-02-10 01:53:46 +000089
90
91def dd_get_d(mytype_address):
Austin Schuh085eab92020-11-26 13:54:51 -080092 return libcdd.ddd_get_d(mytype_address)
brians343bc112013-02-10 01:53:46 +000093
94
95def dd_FreeMatrix(matrixptr):
Austin Schuh085eab92020-11-26 13:54:51 -080096 libcdd.dd_FreeMatrix(matrixptr)
brians343bc112013-02-10 01:53:46 +000097
98
99def dd_FreePolyhedra(polyhedraptr):
Austin Schuh085eab92020-11-26 13:54:51 -0800100 libcdd.dd_FreePolyhedra(polyhedraptr)
brians343bc112013-02-10 01:53:46 +0000101
102
103def dd_DDMatrix2Poly(matrixptr):
Austin Schuh085eab92020-11-26 13:54:51 -0800104 error = ctypes.c_int()
105 polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr, ctypes.byref(error))
brians343bc112013-02-10 01:53:46 +0000106
Austin Schuh085eab92020-11-26 13:54:51 -0800107 # Return None on error.
108 # The error values are enums, so they aren't exposed.
109 if error.value != DD_NO_ERRORS:
110 # TODO(austin): Dump out the errors to stderr
111 #libcdd.dd_WriteErrorMessages(
112 # ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
113 # error)
114 dd_FreePolyhedra(polyhedraptr)
115 return None
116 return polyhedraptr