blob: b46d908a2d2737b56d9d4b7fd6c8c794b2489b18 [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
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
11# Wrapper around PyFile_AsFile so that we can print out the error messages.
12# Set the arg type and return types of the function call.
13class FILE(ctypes.Structure):
14 pass
15
16ctypes.pythonapi.PyFile_AsFile.argtypes = [ctypes.py_object]
17ctypes.pythonapi.PyFile_AsFile.restype = ctypes.POINTER(FILE)
18
19# Load and init libcdd. libcdd is a C library that implements algorithm to
20# manipulate half space and vertex representations of polytopes.
21# Unfortunately, the library was compiled with C++ even though it has a lot of C
22# code in it, so all the symbol names are mangled. Ug.
Campbell Crowley15e4d7e2015-11-21 18:12:48 -080023libcdd = None
24for path in os.environ.get('PYTHONPATH').split(':'):
25 try:
26 libcdd = ctypes.cdll.LoadLibrary(os.path.join(path, 'third_party/cddlib/_cddlib.so'))
27 except OSError, e:
28 pass
29
30assert libcdd is not None, 'Failed to find _cddlib.so'
31
Austin Schuhbf9d6502015-09-11 23:59:15 -070032libcdd.dd_set_global_constants()
brians343bc112013-02-10 01:53:46 +000033
34# The variable type mytype that libcdd defines (double[1])
35# See http://docs.python.org/2/library/ctypes.html#arrays for the documentation
36# explaining why ctypes.c_double * 1 => double[1]
37# libcdd defines mytype to various things so it can essentially template its
38# functions. What a weird library.
39mytype = ctypes.c_double * 1
40
41
42# Forward declaration for the polyhedra data structure.
43class dd_polyhedradata(ctypes.Structure):
44 pass
45
46
47# Definition of dd_matrixdata
48class dd_matrixdata(ctypes.Structure):
49 _fields_ = [
50 ("rowsize", ctypes.c_long),
51 ("linset", ctypes.POINTER(ctypes.c_ulong)),
52 ("colsize", ctypes.c_long),
53 ("representation", ctypes.c_int),
54 ("numbtype", ctypes.c_int),
55 ("matrix", ctypes.POINTER(ctypes.POINTER(mytype))),
56 ("objective", ctypes.c_int),
57 ("rowvec", ctypes.POINTER(mytype)),
58 ]
59
60# Define the input and output types for a bunch of libcdd functions.
Austin Schuhbf9d6502015-09-11 23:59:15 -070061libcdd.dd_CreateMatrix.restype = ctypes.POINTER(dd_matrixdata)
62libcdd.ddd_get_d.argtypes = [mytype]
63libcdd.ddd_get_d.restype = ctypes.c_double
brians343bc112013-02-10 01:53:46 +000064
Austin Schuhbf9d6502015-09-11 23:59:15 -070065libcdd.dd_CopyGenerators.argtypes = [
brians343bc112013-02-10 01:53:46 +000066 ctypes.POINTER(dd_polyhedradata)
67]
Austin Schuhbf9d6502015-09-11 23:59:15 -070068libcdd.dd_CopyGenerators.restype = ctypes.POINTER(dd_matrixdata)
brians343bc112013-02-10 01:53:46 +000069
Austin Schuhbf9d6502015-09-11 23:59:15 -070070libcdd.dd_DDMatrix2Poly.argtypes = [
brians343bc112013-02-10 01:53:46 +000071 ctypes.POINTER(dd_matrixdata),
72 ctypes.POINTER(ctypes.c_int)
73]
Austin Schuhbf9d6502015-09-11 23:59:15 -070074libcdd.dd_DDMatrix2Poly.restype = (
brians343bc112013-02-10 01:53:46 +000075 ctypes.POINTER(dd_polyhedradata))
76
Austin Schuhbf9d6502015-09-11 23:59:15 -070077libcdd.dd_FreeMatrix.argtypes = [
brians343bc112013-02-10 01:53:46 +000078 ctypes.POINTER(dd_matrixdata)
79]
80
Austin Schuhbf9d6502015-09-11 23:59:15 -070081libcdd.dd_FreePolyhedra.argtypes = [
brians343bc112013-02-10 01:53:46 +000082 ctypes.POINTER(dd_polyhedradata)
83]
84
Austin Schuhbf9d6502015-09-11 23:59:15 -070085libcdd.ddd_set_d.argtypes = [
brians343bc112013-02-10 01:53:46 +000086 mytype,
87 ctypes.c_double
88]
89
90
91# Various enums.
92DD_INEQUALITY = 1
93DD_REAL = 1
94DD_NO_ERRORS = 17
95
96
97def dd_CreateMatrix(rows, cols):
Austin Schuhbf9d6502015-09-11 23:59:15 -070098 return libcdd.dd_CreateMatrix(ctypes.c_long(rows), ctypes.c_long(cols))
brians343bc112013-02-10 01:53:46 +000099
100
101def dd_set_d(mytype_address, double_value):
Austin Schuhbf9d6502015-09-11 23:59:15 -0700102 libcdd.ddd_set_d(mytype_address, ctypes.c_double(double_value))
brians343bc112013-02-10 01:53:46 +0000103
104
105def dd_CopyGenerators(polyhedraptr):
Austin Schuhbf9d6502015-09-11 23:59:15 -0700106 return libcdd.dd_CopyGenerators(polyhedraptr)
brians343bc112013-02-10 01:53:46 +0000107
108
109def dd_get_d(mytype_address):
Austin Schuhbf9d6502015-09-11 23:59:15 -0700110 return libcdd.ddd_get_d(mytype_address)
brians343bc112013-02-10 01:53:46 +0000111
112
113def dd_FreeMatrix(matrixptr):
Austin Schuhbf9d6502015-09-11 23:59:15 -0700114 libcdd.dd_FreeMatrix(matrixptr)
brians343bc112013-02-10 01:53:46 +0000115
116
117def dd_FreePolyhedra(polyhedraptr):
Austin Schuhbf9d6502015-09-11 23:59:15 -0700118 libcdd.dd_FreePolyhedra(polyhedraptr)
brians343bc112013-02-10 01:53:46 +0000119
120
121def dd_DDMatrix2Poly(matrixptr):
122 error = ctypes.c_int()
Austin Schuhbf9d6502015-09-11 23:59:15 -0700123 polyhedraptr = libcdd.dd_DDMatrix2Poly(matrixptr, ctypes.byref(error))
brians343bc112013-02-10 01:53:46 +0000124
125 # Return None on error.
126 # The error values are enums, so they aren't exposed.
Austin Schuhf69ef922013-10-07 23:21:12 -0700127 if error.value != DD_NO_ERRORS:
brians343bc112013-02-10 01:53:46 +0000128 # Dump out the errors to stderr
Austin Schuhbf9d6502015-09-11 23:59:15 -0700129 libcdd.dd_WriteErrorMessages(
brians343bc112013-02-10 01:53:46 +0000130 ctypes.pythonapi.PyFile_AsFile(ctypes.py_object(sys.stdout)),
131 error)
132 dd_FreePolyhedra(polyhedraptr)
133 return None
134 return polyhedraptr