blob: a2177283447b47a7d7f5d2e1c39d554d34619851 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#!/usr/bin/python
2
3"""Wrapper around libcdd, a polytope manipulation library."""
4
5__author__ = 'Austin Schuh (austin.linux@gmail.com)'
6
7import ctypes
8
9# Wrapper around PyFile_AsFile so that we can print out the error messages.
10# Set the arg type and return types of the function call.
11class FILE(ctypes.Structure):
12 pass
13
14ctypes.pythonapi.PyFile_AsFile.argtypes = [ctypes.py_object]
15ctypes.pythonapi.PyFile_AsFile.restype = ctypes.POINTER(FILE)
16
17# Load and init libcdd. libcdd is a C library that implements algorithm to
18# manipulate half space and vertex representations of polytopes.
19# Unfortunately, the library was compiled with C++ even though it has a lot of C
20# code in it, so all the symbol names are mangled. Ug.
21libcdd = ctypes.cdll.LoadLibrary('libcdd.so')
22libcdd._Z23dd_set_global_constantsv()
23
24# The variable type mytype that libcdd defines (double[1])
25# See http://docs.python.org/2/library/ctypes.html#arrays for the documentation
26# explaining why ctypes.c_double * 1 => double[1]
27# libcdd defines mytype to various things so it can essentially template its
28# functions. What a weird library.
29mytype = ctypes.c_double * 1
30
31
32# Forward declaration for the polyhedra data structure.
33class dd_polyhedradata(ctypes.Structure):
34 pass
35
36
37# Definition of dd_matrixdata
38class dd_matrixdata(ctypes.Structure):
39 _fields_ = [
40 ("rowsize", ctypes.c_long),
41 ("linset", ctypes.POINTER(ctypes.c_ulong)),
42 ("colsize", ctypes.c_long),
43 ("representation", ctypes.c_int),
44 ("numbtype", ctypes.c_int),
45 ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
46 ("objective", ctypes.c_int),
47 ("rowvec", ctypes.POINTER(mytype)),
48 ]
49
50# Define the input and output types for a bunch of libcdd functions.
51libcdd._Z15dd_CreateMatrixll.restype = ctypes.POINTER(dd_matrixdata)
52libcdd._Z9ddd_get_dPd.argtypes = [mytype]
53libcdd._Z9ddd_get_dPd.restype = ctypes.c_double
54
55libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata.argtypes = [
56 ctypes.POINTER(dd_polyhedradata)
57]
58libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata.restype = ctypes.POINTER(dd_matrixdata)
59
60libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType.argtypes = [
61 ctypes.POINTER(dd_matrixdata),
62 ctypes.POINTER(ctypes.c_int)
63]
64libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType.restype = (
65 ctypes.POINTER(dd_polyhedradata))
66
67libcdd._Z13dd_FreeMatrixP13dd_matrixdata.argtypes = [
68 ctypes.POINTER(dd_matrixdata)
69]
70
71libcdd._Z16dd_FreePolyhedraP16dd_polyhedradata.argtypes = [
72 ctypes.POINTER(dd_polyhedradata)
73]
74
75libcdd._Z9ddd_set_dPdd.argtypes = [
76 mytype,
77 ctypes.c_double
78]
79
80
81# Various enums.
82DD_INEQUALITY = 1
83DD_REAL = 1
84DD_NO_ERRORS = 17
85
86
87def dd_CreateMatrix(rows, cols):
88 return libcdd._Z15dd_CreateMatrixll(
89 ctypes.c_long(rows),
90 ctypes.c_long(cols))
91
92
93def dd_set_d(mytype_address, double_value):
94 libcdd._Z9ddd_set_dPdd(mytype_address,
95 ctypes.c_double(double_value))
96
97
98def dd_CopyGenerators(polyhedraptr):
99 return libcdd._Z17dd_CopyGeneratorsP16dd_polyhedradata(polyhedraptr)
100
101
102def dd_get_d(mytype_address):
103 return libcdd._Z9ddd_get_dPd(mytype_address)
104
105
106def dd_FreeMatrix(matrixptr):
107 libcdd._Z13dd_FreeMatrixP13dd_matrixdata(matrixptr)
108
109
110def dd_FreePolyhedra(polyhedraptr):
111 libcdd._Z16dd_FreePolyhedraP16dd_polyhedradata(polyhedraptr)
112
113
114def dd_DDMatrix2Poly(matrixptr):
115 error = ctypes.c_int()
116 polyhedraptr = libcdd._Z16dd_DDMatrix2PolyP13dd_matrixdataP12dd_ErrorType(
117 matrixptr,
118 ctypes.byref(error))
119
120 # Return None on error.
121 # The error values are enums, so they aren't exposed.
122 if error.value != NO_ERRORS:
123 # Dump out the errors to stderr
124 libcdd._Z21dd_WriteErrorMessagesP8_IO_FILE12dd_ErrorType(
125 ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
126 error)
127 dd_FreePolyhedra(polyhedraptr)
128 return None
129 return polyhedraptr