root/projects/AsynCluster/trunk/svpmc/weave.py

Revision 198, 6.1 kB (checked in by edsuom, 6 months ago)

Tried Metropolis-within-Gibbs, but ran into the difficulty of getting the proposal density on z for weighting

Line 
1 # svpmc: Stochastic Volatility Inference via Population Monte Carlo
2 #
3 # Copyright (C) 2008 by Edwin A. Suominen, http://www.eepatents.com
4 #
5 # This program is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later
8 # version.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE.  See the file COPYING for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # this program; if not, write to the Free Software Foundation, Inc., 51
16 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17
18 """
19 Convenience class for doing inline C with SciPy.weave.
20
21 You can import from this module instead of scipy.weave. Then you get the
22 convenience class L{Weaver} in addition to the good stuff in scipy.weave.
23 """
24
25 import inspect, re
26 from pkg_resources import resource_string
27 from scipy.weave import *
28 from scipy.weave.base_info import custom_info
29
30
31 class my_info(custom_info):
32     _extra_compile_args = ['-w', '-O3', '-march=native']
33     __macros = [
34         # Access an element i of a 1-D array whose pointer is pa
35         'PA1(pa,i)',
36         "*(pa + i)",
37
38         # Access an element i of a 1-D array whose pointer is pa in a structure
39         # whose pointer is s
40         'SPA1(s,pa,i)',
41         "*(s->pa + i)",
42
43         # Access an element i, j of a 2-D Numpy array object whose pointer is
44         # ppa
45         'PP2(ppa,i,j)',
46         "(*((double*)(ppa->data + (i)*ppa->strides[0] + (j)*ppa->strides[1])))",
47
48         # Access an element i of a 1-D Numpy array object whose pointer is ppa
49         # in a structure whose pointer is s
50         'SPP1(s,ppa,i)',
51         "(*((double*)(s->ppa->data + (i)*s->ppa->strides[0])))",
52        
53         # Access an element i, j of a 2-D Numpy array object whose pointer is
54         # ppa in a structure whose pointer is s
55         'SPP2(s,ppa,i,j)',
56         "(*((double*)(s->ppa->data + "+\
57         "(i)*s->ppa->strides[0] + (j)*s->ppa->strides[1])))",
58         ]
59
60     def __init__(self):
61         k = 0
62         macros = ["'%s'" % (x,) for x in self.__macros]
63         while(k < len(macros)):
64             name, value = macros[k:k+2]
65             self.add_define_macro((name, value))
66             self.add_undefine_macro(name)
67             k += 2
68
69
70 class Weaver(object):
71     """
72     Subclass from me to conveniently use a separate C code file for inline
73     operations.
74
75     The code file is for the entire module in which my sublcass resides, and
76     must be present in that module's directory under the name C{<module>.c}. It
77     is parsed into sections with headings as inline C comments in the following
78     format::
79
80         // <subclass>.<method in which 'c' base class method is called>
81
82     The subclass name must start with a capital letter and the method name with
83     a lowercase letter (possibly followed by one or two underscores), as is
84     conventional. There must not be anything else but whitespace on the comment
85     line.
86     """
87     infoObj = my_info()
88    
89     def _parseCode(self, text):
90         re_delimiter = re.compile(
91             "//\s+([A-Z][A-Za-z0-9_]+)\.(_{0,2}[a-z][A-Za-z0-9_]+)\s*$")
92         cName = self.__class__.__name__
93         key = None
94         lines = []
95         result = {'support':None}
96         for line in text.split("\n"):
97             m = re_delimiter.match(line)
98             if m is None:
99                 if key:
100                     lines.append(line)
101                 continue
102             if lines:
103                 result[key] = "\n".join(lines)
104                 lines = []
105             if m.group(1) == cName:
106                 key = m.group(2)
107             else:
108                 key = None
109         if lines:
110             result[key] = "\n".join(lines)
111         return result
112    
113     def _get_code(self):
114         if not hasattr(self, '_code'):
115             moduleName = self.__class__.__module__.split(".")[-1]
116             self._code = self._parseCode(
117                 resource_string(__name__, "%s.c" % moduleName))
118         return self._code
119     code = property(_get_code)
120
121     def inline(self, *args, **kw):
122         """
123         Call this method to run the inline code for the calling method of the
124         subclass.
125
126         Supply the names of variables to use as arguments in order as
127         arguments. The variables can have their values set via keywords;
128         otherwise they will be retrieved from the caller's namespace or,
129         failing that, from my instance's namespace as C{self.<varname>}.
130
131         A reference to the result of the inline call, set inside the C code via
132         the variable I{return_val}, is returned.
133         """
134         local_dict = kw
135         frame = inspect.currentframe()
136         methodName = frame.f_back.f_code.co_name
137         callerVarNames = frame.f_back.f_locals.keys()
138         try:
139             for varName in args:
140                 if varName in kw:
141                     continue
142                 if varName in callerVarNames:
143                     local_dict[varName] = frame.f_back.f_locals[varName]
144                 elif hasattr(self, varName):
145                     local_dict[varName] = getattr(self, varName)
146                 else:
147                     raise AttributeError(
148                         "Variable '%s' not defined " % varName +\
149                         "in keyword, caller, or instance namespace")
150         finally:
151             # Avoid cycle problems, per Python Library Reference 3.11.4
152             del frame
153         return inline(
154             self.code[methodName], args, local_dict,
155             customize=self.infoObj, support_code=self.code['support'])
156
157     def inlineDirect(self, code, **kw):
158         """
159         Call this method with a string of C I{code} and keywords defining the
160         names and values of variables to be passed to the code function.
161
162         Using this method entails less CPU overhead (but also less convenience
163         and flexibility) than using L{inline}.
164         """
165         return inline(
166             code, kw.keys(), kw,
167             customize=self.infoObj, support_code=self.code['support'])
Note: See TracBrowser for help on using the browser.