blob: 72d5833712eaef6692f05a68e78401a196b053f4 [file] [log] [blame]
Austin Schuh085eab92020-11-26 13:54:51 -08001#!/usr/bin/python3
brians343bc112013-02-10 01:53:46 +00002
3"""Wrapper around libcdd, a polytope manipulation library."""
4
5__author__ = 'Austin Schuh (austin.linux@gmail.com)'
6
7import ctypes
Campbell Crowley15e4d7e2015-11-21 18:12:48 -08008import os
Brian Silvermandc3748d2014-03-30 12:41:52 -07009import sys
brians343bc112013-02-10 01:53:46 +000010
brians343bc112013-02-10 01:53:46 +000011# Load and init libcdd. libcdd is a C library that implements algorithm to
12# manipulate half space and vertex representations of polytopes.
13# Unfortunately, the library was compiled with C++ even though it has a lot of C
14# code in it, so all the symbol names are mangled. Ug.
Campbell Crowley15e4d7e2015-11-21 18:12:48 -080015libcdd = None
16for path in os.environ.get('PYTHONPATH').split(':'):
Austin Schuh085eab92020-11-26 13:54:51 -080017 try:
18 libcdd = ctypes.cdll.LoadLibrary(os.path.join(path, 'third_party/cddlib/_cddlib.so'))
19 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
52# Define the input and output types for a bunch of libcdd functions.
Austin Schuhbf9d6502015-09-11 23:59:15 -070053libcdd.dd_CreateMatrix.restype = ctypes.POINTER(dd_matrixdata)
54libcdd.ddd_get_d.argtypes = [mytype]
55libcdd.ddd_get_d.restype = ctypes.c_double
brians343bc112013-02-10 01:53:46 +000056
Austin Schuhbf9d6502015-09-11 23:59:15 -070057libcdd.dd_CopyGenerators.argtypes = [
brians343bc112013-02-10 01:53:46 +000058 ctypes.POINTER(dd_polyhedradata)
59]
Austin Schuhbf9d6502015-09-11 23:59:15 -070060libcdd.dd_CopyGenerators.restype = ctypes.POINTER(dd_matrixdata)
brians343bc112013-02-10 01:53:46 +000061
Austin Schuhbf9d6502015-09-11 23:59:15 -070062libcdd.dd_DDMatrix2Poly.argtypes = [
brians343bc112013-02-10 01:53:46 +000063 ctypes.POINTER(dd_matrixdata),
64 ctypes.POINTER(ctypes.c_int)
65]
Austin Schuhbf9d6502015-09-11 23:59:15 -070066libcdd.dd_DDMatrix2Poly.restype = (
brians343bc112013-02-10 01:53:46 +000067 ctypes.POINTER(dd_polyhedradata))
68
Austin Schuhbf9d6502015-09-11 23:59:15 -070069libcdd.dd_FreeMatrix.argtypes = [
brians343bc112013-02-10 01:53:46 +000070 ctypes.POINTER(dd_matrixdata)
71]
72
Austin Schuhbf9d6502015-09-11 23:59:15 -070073libcdd.dd_FreePolyhedra.argtypes = [
brians343bc112013-02-10 01:53:46 +000074 ctypes.POINTER(dd_polyhedradata)
75]
76
Austin Schuhbf9d6502015-09-11 23:59:15 -070077libcdd.ddd_set_d.argtypes = [
brians343bc112013-02-10 01:53:46 +000078 mytype,
79 ctypes.c_double
80]
81
82
83# Various enums.
84DD_INEQUALITY = 1
85DD_REAL = 1
86DD_NO_ERRORS = 17
87
88
89def dd_CreateMatrix(rows, cols):
Austin Schuh085eab92020-11-26 13:54:51 -080090 return libcdd.dd_CreateMatrix(ctypes.c_long(rows), ctypes.c_long(cols))
brians343bc112013-02-10 01:53:46 +000091
92
93def dd_set_d(mytype_address, double_value):
Austin Schuh085eab92020-11-26 13:54:51 -080094 libcdd.ddd_set_d(mytype_address, ctypes.c_double(double_value))
brians343bc112013-02-10 01:53:46 +000095
96
97def dd_CopyGenerators(polyhedraptr):
Austin Schuh085eab92020-11-26 13:54:51 -080098 return libcdd.dd_CopyGenerators(polyhedraptr)
brians343bc112013-02-10 01:53:46 +000099
100
101def dd_get_d(mytype_address):
Austin Schuh085eab92020-11-26 13:54:51 -0800102 return libcdd.ddd_get_d(mytype_address)
brians343bc112013-02-10 01:53:46 +0000103
104
105def dd_FreeMatrix(matrixptr):
Austin Schuh085eab92020-11-26 13:54:51 -0800106 libcdd.dd_FreeMatrix(matrixptr)
brians343bc112013-02-10 01:53:46 +0000107
108
109def dd_FreePolyhedra(polyhedraptr):
Austin Schuh085eab92020-11-26 13:54:51 -0800110 libcdd.dd_FreePolyhedra(polyhedraptr)
brians343bc112013-02-10 01:53:46 +0000111
112
113def dd_DDMatrix2Poly(matrixptr):
Austin Schuh085eab92020-11-26 13:54:51 -0800114 error = ctypes.c_int()
115 polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr, ctypes.byref(error))
brians343bc112013-02-10 01:53:46 +0000116
Austin Schuh085eab92020-11-26 13:54:51 -0800117 # Return None on error.
118 # The error values are enums, so they aren't exposed.
119 if error.value != DD_NO_ERRORS:
120 # TODO(austin): Dump out the errors to stderr
121 #libcdd.dd_WriteErrorMessages(
122 # ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
123 # error)
124 dd_FreePolyhedra(polyhedraptr)
125 return None
126 return polyhedraptr