ちょっとだけ自分で作ってみたのでメモ
遺伝的アルゴリズムを走らせるときに利用した。気持ち早くなった。。。
作ったものとしては簡単な10進数ー2進数の変換とグレイコード変換もおまけで。
bitstring使えばすぐだけど練習の意味もこめて。
まずはじめにCのコード(一部)。インデントがなんか崩れてるけど、同じ処理何回も書いてるけど、命名規則もでたらめだけど、たたき台として。ちょっと長いですがそのままです。
ちなみにPython側からListを渡してC側で受け取るところでつまりました。
プログラム難しい...
参考(主にAPI関係)
http://stackoverflow.com/questions/5079570/writing-a-python-c-extension-how-to-correctly-load-a-pylistobject
参考(ビット演算など)
http://saeki-ce.xsrv.jp/index.html
その他wikiなどなど
cbinary.c
#include <Python.h>
#define LOWER_BOUND 0
#define UPPER_BOUND 1000
#define MAX_BIT_LENGTH 10
int binaryToValue(int *);
static PyObject *
valueToGray(PyObject *self, PyObject *args)
{
//return gray code
int i, n, m, len;
unsigned int num;
int b[MAX_BIT_LENGTH];
PyListObject *binary;
binary = (PyListObject *) PyList_New(MAX_BIT_LENGTH);
if (!PyArg_ParseTuple(args, "i", &num)){
return NULL;
}
n = (num >> 1) ^ num; //gray codeに変換
//2進数に変換
for (i=0; n>0; i++){
m=n%2; //2で割ったあまり
n=n/2; //2で割る
b[i] = m;
}
len = i; //整数の2進数変換した時の長さ
//10bitになるようにけつに0を追加する
for (i=len; i<MAX_BIT_LENGTH; i++ ){
b[i] = 0;
}
//逆順だったビット列を2進数の順にコピーする
n = 0;
for (i=MAX_BIT_LENGTH-1; i>=0; i--){
//gray に1bitずつint型の値を入れていく
PyList_SET_ITEM(binary, n++, Py_BuildValue("i", b[i]));
}
return Py_BuildValue("O", binary);
}
static PyObject *
make_individual(PyObject *self, PyObject *args)
{
int b[MAX_BIT_LENGTH];
int m,n,i,len;
unsigned int min, max;
unsigned int random_int;
unsigned int gray_int;
PyListObject *gray; //pythonのlistオブジェクトを表現
gray = (PyListObject *) PyList_New(MAX_BIT_LENGTH); //サイズがMAX~のリストを作る
if (!PyArg_ParseTuple(args, "ii", &min, &max)){ //引数が複数の時はiiみたいに並べて書く
return NULL;
}
if (min < LOWER_BOUND){
exit(0);
}
else if (max > UPPER_BOUND){
exit(0);
}
//ランダムに整数を発生させる
random_int = min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
gray_int = (random_int >> 1) ^ random_int; //gray codeに変換
n = gray_int;
//2進数に変換
for (i=0; n>0; i++){
m=n%2; //2で割ったあまり
n=n/2; //2で割る
b[i] = m;
}
len = i; //整数の2進数変換した時の長さ
//10bitになるようにけつに0を追加する
for (i=len; i<MAX_BIT_LENGTH; i++ ){
b[i] = 0;
}
//逆順だったビット列を2進数の順にコピーする
n = 0;
for (i=MAX_BIT_LENGTH-1; i>=0; i--){
//gray に1bitずつint型の値を入れていく
PyList_SET_ITEM(gray, n++, Py_BuildValue("i", b[i]));
}
return Py_BuildValue("O", gray);
}
static PyObject *
grayToBinary(PyObject *self, PyObject *args)
{
unsigned int num;
unsigned int mask;
int m,n,i,len;
int b[MAX_BIT_LENGTH], inputed_binary[MAX_BIT_LENGTH];
PyListObject *binary; //pythonのlistオブジェクトを表現
PyObject *get_list;
binary = (PyListObject *) PyList_New(MAX_BIT_LENGTH);
if (!PyArg_ParseTuple(args, "O", &get_list )){
return NULL;
}
if PyList_Check(get_list) {
for (i=0; i<PyList_Size(get_list); i++){
//リストオブジェクトの中身をCで見れるように変換しながら取り出す?(自信なし)
inputed_binary[i] = PyInt_AsSsize_t(PyList_GetItem(get_list, (Py_ssize_t)i)); //ok
}
}
num = binaryToValue(inputed_binary);
for (mask = num >> 1; mask != 0; mask = mask >> 1){
//gray codeから元に戻す
num = num ^ mask;
}
n = num;
//2進数に変換
for (i=0; n>0; i++){
m=n%2; //2で割ったあまり
n=n/2; //2で割る
b[i] = m;
}
len = i; //整数の2進数変換した時の長さ
//10bitになるようにけつに0を追加する
for (i=len; i<MAX_BIT_LENGTH; i++ ){
b[i] = 0;
}
//逆順だったビット列を2進数の順にコピーする
n = 0;
for (i=MAX_BIT_LENGTH-1; i>=0; i--){
//binary に1bitずつint型の値を入れていく
PyList_SET_ITEM(binary, n++, Py_BuildValue("i", b[i]));
}
return Py_BuildValue("O", binary);
}
int binaryToValue(int *b){
//2進数を整数に変換する
int i,n;
i=0; n=0;
while(i < MAX_BIT_LENGTH){
if (b[i] == 1) n+=1;
i+=1;
if (i == MAX_BIT_LENGTH) break;
n=n*2;
//printf("%d\n", n);
}
return n;
}
static PyObject *
binaryToPtype(PyObject *self, PyObject *args)
{
int i,n;
int inputed_binary[MAX_BIT_LENGTH];
PyListObject *binary; //pythonのlistオブジェクトを表現
PyObject *get_list;
if (!PyArg_ParseTuple(args, "O", &get_list )){ //pythonオブジェクトをそのまま渡す
return NULL;
}
if PyList_Check(get_list) {
for (i=0; i<PyList_Size(get_list); i++){
inputed_binary[i] = PyInt_AsSsize_t(PyList_GetItem(get_list, (Py_ssize_t)i)); //ok
}
}
i=0; n=0;
while(i < MAX_BIT_LENGTH){
if (inputed_binary[i] == 1) n+=1;
i+=1;
if (i == MAX_BIT_LENGTH) break;
n=n*2;
//printf("%d\n", n);
}
return Py_BuildValue("i", n);
}
static PyObject *
hello(PyObject *self)
{
printf("Hello World!!\n");
Py_RETURN_NONE;
}
static char ext_doc[] = "C extention module example\n";
static PyMethodDef methods[] = {
{"hello", (PyCFunction)hello, METH_NOARGS, "print hello world.\n"},
{"value_to_gray", valueToGray, METH_VARARGS, "return gray obj.\n"},
{"make_individual", make_individual, METH_VARARGS, "return gray code.\n"},
{"gray_to_binary", grayToBinary, METH_VARARGS, "return binary code.\n"},
{"binary_to_ptype", binaryToPtype, METH_VARARGS, "return ptype value.\n"},
{NULL, NULL, 0, NULL}
};
void initcbinarymethods(void)
{
Py_InitModule3("cbinarymethods", methods, ext_doc);
}
いつものように? setup.pyを書きます。
setup.py
from distutils.core import setup, Extension
module1 = Extension('cbinarymethods',
sources = ['cbinary.c'])
setup (name = 'cbinarymethods',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1])
これまたいつものようにコマンドラインでビルドします。
$ python setup.py build_ext --inplace #--inplaceをつけるとカレントに.soができるっぽい
無事ビルドできたらcbinarymethods.soができています。
pythonでimportして使ってみよう
>>> import cbinarymethods as cbm
>>> i = cbm.make_individual(200, 250)
>>> i
[0, 0, 1, 0, 0, 0, 1, 0, 1, 1]
>>> a = cbm.gray_to_binary([0,0,1,0,1,0,0,1,0,1])
>>> a
[0, 0, 1, 1, 0, 0, 0, 1, 1, 0]