This repository has been archived by the owner on Aug 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathhungarian.cpp
executable file
·147 lines (123 loc) · 3.21 KB
/
hungarian.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
hungarian
Harold Cooper <[email protected]>
hungarian.cpp 2004-09-02
*/
#include "Python.h"
#include "numpy/arrayobject.h"
#include "asp.h"
static PyObject *
hungarian(PyObject *self, PyObject *args)
//hungarian(costs)
{
PyObject *ocosts;
PyArrayObject *costs;
int n;
npy_intp n2;
long *rowsol;
long *colsol;
cost *buf,**ccosts;
npy_intp *strides;
PyObject * rowo;
PyObject * colo;
if (!PyArg_ParseTuple(args, "O", &ocosts))
return NULL;
costs = (PyArrayObject*)PyArray_FromAny(
ocosts,PyArray_DescrFromType(COST_TYPE_NPY),2,2,
NPY_CONTIGUOUS|NPY_ALIGNED|NPY_FORCECAST,0
);
if (costs->nd!=2)
{
PyErr_SetString(PyExc_ValueError,"lap() requires a 2-D matrix");
goto error;
}
n = costs->dimensions[0];
n2 = costs->dimensions[0];
if (costs->dimensions[1]!=n)
{
PyErr_SetString(PyExc_ValueError,"lap() requires a square matrix");
goto error;
}
//get inputted matrix as a 1-D C array:
buf = (cost*)PyArray_DATA(costs);
//copy inputted matrix into a 2-dimensional C array:
strides = PyArray_STRIDES(costs);
assert(strides[1] == sizeof(cost));
ccosts = (cost **)malloc(sizeof(cost *)*n);
if(!ccosts)
{
PyErr_NoMemory();
free(ccosts);
goto error;
}
for(int i=0;i<n;i++)
ccosts[i] = buf+i*(strides[0]/sizeof(cost));
//allocate data for the output array
rowo = PyArray_SimpleNew(1, &n2, NPY_LONG);
colo = PyArray_SimpleNew(1, &n2, NPY_LONG);
rowsol = (long *) PyArray_DATA(rowo);
colsol = (long *) PyArray_DATA(colo);
if(!(rowsol&&colsol))
{
PyErr_NoMemory();
free(ccosts);
goto error;
}
//run hungarian!:
asp(n,ccosts,rowsol,colsol);
//NA_InputArray() incremented costs, but now we're done with it, so let it get GC'ed:
Py_XDECREF(costs);
free(ccosts);
return Py_BuildValue("(NN)",
rowo, colo
);
error:
Py_XDECREF(costs);
return NULL;
}
static char module_docstring[] = "Solves the linear assignment problem using the Hungarian\nalgorithm.\n\nhungarian() takes a single argument - a square cost matrix - and returns a\ntuple of the form\n(row_assigns,col_assigns).";
static PyMethodDef HungarianMethods[] = {
{"lap", hungarian, METH_VARARGS,
module_docstring},
{NULL, NULL, 0, NULL} /* Sentinel (terminates structure) */
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef Hungarian =
{
PyModuleDef_HEAD_INIT,
"hungarian",
module_docstring,
-1,
HungarianMethods
};
PyMODINIT_FUNC PyInit_hungarian(void)
{
import_array();
return PyModule_Create(&Hungarian);
}
#else
PyMODINIT_FUNC
inithungarian(void)
{
(void) Py_InitModule("hungarian", HungarianMethods);
import_array();
}
#endif
int main(int argc, char *argv[])
{
/* Pass argv[0] to the Python interpreter */
#if PY_MAJOR_VERSION >= 3
Py_SetProgramName((wchar_t*)argv[0]);
#else
Py_SetProgramName(argv[0]);
#endif
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
#if PY_MAJOR_VERSION >= 3
PyInit_hungarian();
#else
inithungarian();
#endif
return 0;
}