2013-02-18 2 views
3

Я бы хотел позвонить PARI/GP из Python только для вычисления функции nextprime(n) для разных n s, которые я определяю. К сожалению, я не могу установить pari-python, поэтому я думал, что просто позвоню ему, используя командную строку через os.system в Python. Тем не менее, я не вижу на странице руководства, как сделать PARI/GP для работы в неинтерактивном режиме. Есть ли способ достичь этого?Вызов PARI/GP из Python

ответ

4

Вы можете ввести трубу в стандартный ввод ВОП, как это так, используя -q флаг отменить подробность:

senderle:~ $ echo "print(isprime(5))" | gp -q 
1 

Однако, это не намного сложнее, чтобы создать простое расширение питона, который позволяет передавать строки в Pari ВНУТРЕННЕГО парсер и вернуть результаты (как строки). Вот версия bare-bones, которую я написал некоторое время назад, так что я мог бы вызвать реализацию pari из APRT test из python. Вы можете продолжить это, чтобы сделать соответствующие преобразования и так далее.

//pariparse.c 

#include<Python.h> 
#include<pari/pari.h> 

static PyObject * pariparse_run(PyObject *self, PyObject *args) { 
    pari_init(40000000, 2); 
    const char *pari_code; 
    char *outstr; 

    if (!PyArg_ParseTuple(args, "s", &pari_code)) { return NULL; } 
    outstr = GENtostr(gp_read_str(pari_code)); 
    pari_close(); 
    return Py_BuildValue("s", outstr); 
} 

static PyMethodDef PariparseMethods[] = { 
    {"run", pariparse_run, METH_VARARGS, "Run a pari command."}, 
    {NULL, NULL, 0, NULL} 
}; 

PyMODINIT_FUNC initpariparse(void) { 
    (void) Py_InitModule("pariparse", PariparseMethods); 
} 

И файл установки:

#setup.py 

from distutils.core import setup, Extension 

module1 = Extension('pariparse', 
        include_dirs = ['/usr/include', '/usr/local/include'], 
        libraries = ['pari'], 
        library_dirs = ['/usr/lib', '/usr/local/lib'], 
        sources = ['pariparse.c']) 

setup (name = 'pariparse', 
     version = '0.01a', 
     description = 'A super tiny python-pari interface', 
     ext_modules = [module1]) 

Тогда просто напечатайте python setup.py build построить расширение. Вы можете назвать это так:

>>> pariparse.run('nextprime(5280)') 
'5281' 

Я испытал это только сейчас, и он составлен для меня с последней версией Pari доступной через самогон (на OS X). YMMV!

+0

Большое спасибо! – felipa

2

Возможно, вы захотите использовать математический инструмент Sage. Sage использует Python для склеивания всех видов математических библиотек, включая PARI. Некоторые из математических библиотек хорошо интегрированы, другие используют хаки (передавая строки в библиотеку, а затем анализируя результаты строки), но во всех случаях кто-то другой выполнял интеграционную работу для вас, и вы можете просто использовать ее.

Вы можете настроить свою собственную систему Sage или получить бесплатную учетную запись и попробовать Sage на серверах Университета Вашингтона.

+0

Спасибо. Это хорошая идея. – felipa

1

Я не думаю, что это хорошая идея, чтобы позвонить os.system, за исключением быстрого и грязного обходного пути, когда у вас есть надежная библиотека C за ней. Очень легко вызвать функции C из Python; вот две функции для вызова nextprime. Один использует целые числа long (несмотря на название, это означает, что вы используете маленькие целые числа); другой использует тип string (для более длинных целых чисел).

Сначала проверьте, что у вас установлен libpari. Решение ниже для Linux и предполагает, что ваша библиотека называется libpari.so. В Windows это, вероятно, будет вызываться с суффиксом .dll. Возможно, вам придется набирать весь путь к файлу DLL, если он не найден с первой попытки:

import ctypes 

# load the library 
pari=ctypes.cdll.LoadLibrary("libpari.so") 

# set the right return type of the functions 
pari.stoi.restype = ctypes.POINTER(ctypes.c_long) 
pari.nextprime.restype = ctypes.POINTER(ctypes.c_long) 
pari.strtoGENstr.restype = ctypes.POINTER(ctypes.c_long) 
pari.geval.restype = ctypes.POINTER(ctypes.c_long) 
pari.itostr.restype = ctypes.c_char_p 

# initialize the library 
pari.pari_init(2**19,0) 

def nextprime(v): 
    g = pari.nextprime(pari.stoi(ctypes.c_long(v))) 
    return pari.itos(g) 

def nextprime2(v): 
    g = pari.nextprime(pari.geval(pari.strtoGENstr(str(v)))) 
    return int(pari.itostr(g)) 

print(nextprime(456)) 
print(nextprime2(456))