{"id":1221,"date":"2009-05-13T19:29:05","date_gmt":"2009-05-13T18:29:05","guid":{"rendered":"http:\/\/www.walkingrandomly.com\/?p=1221"},"modified":"2011-08-22T15:48:29","modified_gmt":"2011-08-22T14:48:29","slug":"pynag-a-python-package-for-interfacing-with-the-nag-c-library","status":"publish","type":"post","link":"https:\/\/walkingrandomly.com\/?p=1221","title":{"rendered":"PyNAG &#8211; A Python package for interfacing with the NAG C Library"},"content":{"rendered":"<p><strong>Update (5th November 2009): <\/strong>PyNAG has been updated several times since this post was written. The latest version will always be available from <a href=\"..\/?page_id=1662\">https:\/\/www.walkingrandomly.com\/?page_id=1662<\/a><\/p>\n<p>This is part 6 of a series of articles devoted to demonstrating how to call the <a href=\"http:\/\/www.nag.co.uk\/numeric\/CL\/cldescription.asp\">Numerical Algorithms Group (NAG) C library<\/a> from Python.\u00a0 Click <a href=\"..\/?p=830\">here for the index<\/a> to this series.<\/p>\n<p>Over the last few articles I have demonstrated that it is relatively straightforward to interface Python to the NAG C library.\u00a0 The resulting code, however, looks a bit ugly and overly verbose since you have to include a lot of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Boilerplate_(text)\">boiler plate code<\/a> such as telling Python where the C library is, defining pythonic versions of C structures, defining various constants and so on.\u00a0 I found myself doing a lot of copying and pasting in the early stages of working all this stuff out.<\/p>\n<p>Just recently I made a small step forward by moving all of this boilerplate into a Python package which I have called PyNAG.\u00a0\u00a0 It&#8217;s a relatively simple package since all it does is define Pythonic versions of various C-structures, link to the NAG library, perform restypes on the function names, define a few often used NAG variables such as NAGERR_DEFAULT and so on.<\/p>\n<p>The practical upshot is that you need to write a lot less code when interfacing with the C library.\u00a0 For example here is the Python code to minimise a 2D function via the <a href=\"http:\/\/www.nag.co.uk\/numeric\/CL\/nagdoc_cl08\/xhtml\/E04\/e04ccc.xml\">simplex method using e04ccc<\/a> of the NAG library.<\/p>\n<pre>#!\/usr\/bin\/env python\r\n#Mike Croucher - April 2008\r\n#A minimisation problem solved using e04ccc\r\nfrom PyNAG import e04ccc,NAGERR_DEFAULT,E04_DEFAULT,Nag_Comm\r\nfrom ctypes import *\r\nfrom math import *\r\n\r\n#Create the communication structure\r\ncomm = Nag_Comm() \r\n\r\n#set up the objective function\r\ndef py_obj_func(n,xc,objf,comm):\r\n\tobjf[0] = exp(xc[0]) * (xc[0] * 4.0 * ( xc[0]+xc[1] ) + xc[1] * 2.0 * (xc[1] +1.0) +1.0 )\r\nC_FUNC = CFUNCTYPE(None,c_int,POINTER(c_double),POINTER(c_double),POINTER(Nag_Comm) )\r\nc_obj_func = C_FUNC(py_obj_func)\r\n\r\n#Set up the starting point\r\nn=2\r\nx=(c_double*2)()\r\nx[0]=c_double(0.4)\r\nx[1]=c_double(-0.8)\r\n\r\n#Set up other variables\r\nobjf = c_double()\r\n\r\ne04ccc(n, c_obj_func, byref(x), byref(objf),E04_DEFAULT,comm,NAGERR_DEFAULT)<\/pre>\n<p>It&#8217;s still not as pretty as it would it if it were written in pure python but it&#8217;s a (small) step in the right direction I think.<\/p>\n<h3>The good<\/h3>\n<ul>\n<li>PyNAG is free and always will be.\u00a0 You&#8217;ll obviously need to buy a copy of the NAG C library though.<\/li>\n<li>It includes a definition of one of the largest C-Structures I have ever seen &#8211; <strong>Nag_E04_Opt<\/strong> &#8211; which has over 130 members.\u00a0 This took me quite a while to get working and now you don&#8217;t need to go through the same pain I did.\u00a0 All the C structures mentioned in these tutorials have been included to save your typing fingers.<\/li>\n<li>PyNAG has been tested on 32bit and 64bit flavours of Linux and seems to work fine.<\/li>\n<li>It is relatively easy to add definitions for NAG functions that are not already currently included.\u00a0 In the best case scenario all you need to do is add two lines of code per NAG function. (They&#8217;re not all this easy though!)<\/li>\n<li>It comes with a set of fully functional examples (15 so far with more on the way) along with expected output.\u00a0 This output has been checked against the original C versions of the code to ensure that the results are correct<\/li>\n<\/ul>\n<h3>The bad<\/h3>\n<ul>\n<li>It only works on Linux at the moment.\u00a0 Depending on interest levels (mine and yours) I may get it working on Mac OS X and Windows.<\/li>\n<li>It only includes all the boilerplate needed to interface with 22 NAG functions at the time of writing.\u00a0 This is a very small percentage of the library as a whole.<\/li>\n<li>It doesn&#8217;t include <strong>all<\/strong> of the structures you might need to use throughout the entire library at the moment.<\/li>\n<li>It doesn&#8217;t include any of the enumerations that the NAG C library uses.\u00a0\u00a0 I plan to include some of the most commonly used ones but will simply have to define them as variables since ctypes doesn&#8217;t support enumerations as far as I know.<\/li>\n<li>This is my first ever Python package so things may be a bit rough around the edges. I welcome advice from more experienced Pythonistas concerning things like package deployment.<\/li>\n<li>The Python version of the NagError structure has a member called <strong>pprint<\/strong> rather than the original <strong>print. <\/strong>This is because print is a reserved keyword in Python so I couldn&#8217;t use it.<\/li>\n<li>It has only been tested on Python versions 2.5.x and 2.6.x.\u00a0 I have no idea if it will work on other versions at the moment.<\/li>\n<li>Documentation is rather sparse at the moment.\u00a0 I haven&#8217;t had time to do a better job.<\/li>\n<\/ul>\n<h3>TheUgly<\/h3>\n<ul>\n<li>All PyNAG really does is save you from having to type in a load of boilerplate.\u00a0 It doesn&#8217;t properly &#8216;pythonise&#8217; the NAG C library and so it is painfully obvious that your code is talking to a C library and not a Python library.\u00a0 Ideally I would like to change this and make the user interface a lot more user-friendly.\u00a0 Any input on how best to go about this would be gratefully received.<\/li>\n<\/ul>\n<h3>The Installation<\/h3>\n<p>The first public release of PyNAG is version 0.12 and is <a href=\"\/images\/NAG\/PyNAG-0.12.tar.gz\">currently available here<\/a> (Linux only).\u00a0 Installation instructions are<\/p>\n<ul>\n<li>Download the tar gzip file above and run the following commands<\/li>\n<li>tar -xvzf .\/PyNAG-0.12.tar.gz<br \/>\ncd PyNAG-0.12\/src<\/li>\n<li>edit the following line in the file<strong> __init__.py<\/strong> so that it points to your installation of the library<br \/>\n<strong>C_libnag= ctypes.cdll.LoadLibrary(&#8220;\/opt\/NAG\/cllux08dgl\/lib\/libnagc_nag.so.8&#8221;)<\/strong><\/li>\n<li>Move back into the root PyNAG-0.12 directory:<br \/>\ncd..<\/li>\n<li>run the following command with administrator priviledges<br \/>\npython setup.py install<\/li>\n<\/ul>\n<p>The installer will scatter the PyNAG files where ever your machine is set up to put them.\u00a0 On my machine it was put in the following location but your mileage may vary<\/p>\n<p><strong>\/usr\/local\/lib\/python2.6\/dist-packages\/PyNAG<\/strong><\/p>\n<h3>The Examples<\/h3>\n<p>I have written a set of example scripts that show PyNAG in use and these can be found in the<strong> src\/examples<\/strong> directory of the PyNAG distribution.\u00a0\u00a0 Mathematically speaking they are all rather dull but they do show how you can call the routines I have included so far.\u00a0 More interesting examples will be appearing soon.<\/p>\n<h3>The Future<\/h3>\n<p>Getting the NAG C library to work with Python has always been a side project for me and I never expected to take it even this far.\u00a0 Most of this work has been done on the train while commuting to and from work and, although it is far from perfect, I am happy with it so far.\u00a0 There is much to do though and the rate it gets done depends on user-interest.\u00a0 Things that spring to mind (in no particular order) are<\/p>\n<ul>\n<li>Get PyNAG on a proper CVS system such as github so that other people can easily contribute.<\/li>\n<li>Add support for <a href=\"http:\/\/scipy.org\/NumPy\">Numpy<\/a> matrices.<\/li>\n<li>Add support for more of the most commonly used NAG functions.<\/li>\n<li>Get a windows version up and running.<\/li>\n<li>Write some more interesting demos.<\/li>\n<li>Write some sort of automated test script that runs all the examples and compares the results with a set of expected results.<\/li>\n<li>See if I get any users and take requests :)<\/li>\n<\/ul>\n<h3>Final points.<\/h3>\n<p><strong>I do not work for NAG &#8211; I just like their products. <\/strong>My professional involvement with them is via the University of Manchester where I am the site-license administrator for NAG products (among many other things).\u00a0 I have a vested interest in getting the best out of their products as well as getting the best out of the likes of Wolfram, Mathworks and a shed-load of other software vendors.<\/p>\n<p>One of my hobbies is pointing out to NAG where their library could do with extra functionality.\u00a0 I am aided in this venture by a load of academics who use the library in it&#8217;s various guises and who contact me to say &#8216;I like NAG but it would be much better if it had the ability to do XYZ&#8217;.\u00a0\u00a0 I am very grateful to NAG for accepting my steady stream of emails with good grace and also for implementing some of our suggestions in the latest version of their library.\u00a0 Feel free to point out any of <strong>your<\/strong> favourite algorithms that are missing from the library and why it should have them.<\/p>\n<p>Finally, I&#8217;d like to thank the various people at NAG who helped me get my head around their library and for helping me test my initial tentative steps into the NAG\/Python world.\u00a0 I owe many of you several beverages of your choice.<\/p>\n<p>As always, comments are welcomed.<\/p>\n<p><strong>Update (5th November 2009): <\/strong>PyNAG has been updated several times since this post was written. The latest version will always be available from <a href=\"https:\/\/www.walkingrandomly.com\/?page_id=1662\">https:\/\/www.walkingrandomly.com\/?page_id=1662<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update (5th November 2009): PyNAG has been updated several times since this post was written. The latest version will always be available from https:\/\/www.walkingrandomly.com\/?page_id=1662 This is part 6 of a series of articles devoted to demonstrating how to call the Numerical Algorithms Group (NAG) C library from Python.\u00a0 Click here for the index to this [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[28,7,31],"tags":[],"class_list":["post-1221","post","type-post","status-publish","format-standard","hentry","category-nag-library","category-programming","category-python"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3swhs-jH","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/1221","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1221"}],"version-history":[{"count":23,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/1221\/revisions"}],"predecessor-version":[{"id":3845,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=\/wp\/v2\/posts\/1221\/revisions\/3845"}],"wp:attachment":[{"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/walkingrandomly.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}