52 from mongoengine
import *
53 from mongoengine.document
import TopLevelDocumentMetaclass
54 from mongoengine.base
import BaseField
56 from fireworks
import Firework, FireTaskBase
57 from collections
import defaultdict
62 MODENA_URI = os.environ.get(
'MODENA_URI',
'mongodb://localhost:27017/test')
63 (uri, database) = MODENA_URI.rsplit(
'/', 1)
64 connect(database, host=MODENA_URI)
66 MODENA_PARSED_URI = pymongo.uri_parser.parse_uri(
70 MODENA_PARSED_URI[
'host'], MODENA_PARSED_URI[
'port'] = \
71 MODENA_PARSED_URI.pop(
'nodelist')[0]
72 MODENA_PARSED_URI[
'name'] = MODENA_PARSED_URI.pop(
'database')
73 del MODENA_PARSED_URI[
'collection'], MODENA_PARSED_URI[
'options']
89 if name
not in i
or 'argPos' not in i[name]:
90 raise Exception(
'[%s][\'argPos\'] not found' % name)
91 return i[name][
'argPos']
104 if not isinstance(kwargs[name], cls):
105 raise TypeError(
'%s must be of type %s' % (name, cls))
106 kwargs[
'meth_' + name] = kwargs[name].to_dict()
109 raise Exception(
'%s not found' % name)
126 return getattr(obj, n)
128 var = getattr(obj,
'meth_' + name)
130 var = load_object(var)
138 class EmbDoc(DynamicEmbeddedDocument):
139 meta = {
'allow_inheritance':
False}
145 def __setitem__(self, index, value):
146 if index >= len(self):
147 self.extend([
None]*(index + 1 - len(self)))
148 list.__setitem__(self, index, value)
162 name = StringField(primary_key=
True)
163 names = ListField(StringField(required=
True))
164 meta = {
'allow_inheritance':
True}
172 def __init__(self, *args, **kwargs):
173 self.___index___ = {j: i
for i, j
in enumerate(kwargs[
'names'])}
174 super(IndexSet, self).__init__(*args, **kwargs)
184 def get_name(self, index):
186 return self.names[index]
188 raise Exception(
'%i is not in index set %s' % (index, self.name))
197 def get_index(self, name):
199 return self.___index___[name]
201 raise Exception(
'%s is not in index set %s' % (name, self.name))
206 def iterator_end(self):
207 return len(self.names)
212 def iterator_size(self):
213 return len(self.names)
221 def exceptionLoad(self, indexSetId):
230 def load(self, indexSetId):
231 return self.objects.get(name=indexSetId)
246 class MinMax(EmbeddedDocument):
247 min = FloatField(required=
True)
248 max = FloatField(required=
True)
279 min = FloatField(required=
True, default=
None)
280 max = FloatField(required=
True, default=
None)
281 argPos = IntField(required=
True)
282 index = ReferenceField(IndexSet)
284 def __init__(self, *args, **kwargs):
285 super(MinMaxArgPos, self).__init__(*args, **kwargs)
288 def printIndex(self):
289 print str(self.index)
308 index = ReferenceField(IndexSet)
310 def __init__(self, *args, **kwargs):
311 super(MinMaxArgPosOpt, self).__init__(*args, **kwargs)
314 def printIndex(self):
315 print str(self.index)
318 Currently not working 320 class IOP(DictField):
322 def __init__(self, field=None, *args, **kwargs):
326 super(IOP, self).__init__(field=field, *args, **kwargs)
331 for k
in self._fields.keys():
333 size += v.index.iterator_size()
341 for k
in self._fields.keys():
343 for idx
in v.index.names:
344 yield '%s[%s]' % (k, idx), v
350 for k, v
in self._fields.iteritems():
352 for idx
in v.index.names:
353 yield '%s[%s]' % (k, idx)
375 name = StringField(primary_key=
True)
376 inputs = MapField(EmbeddedDocumentField(MinMaxArgPosOpt))
377 outputs = MapField(EmbeddedDocumentField(MinMaxArgPos))
378 parameters = MapField(EmbeddedDocumentField(MinMaxArgPos))
379 functionName = StringField(required=
True)
380 libraryName = StringField(required=
True)
381 indices = MapField(ReferenceField(IndexSet))
382 meta = {
'allow_inheritance':
True}
388 def __init__(self, *args, **kwargs):
389 if kwargs.has_key(
'_cls'):
390 super(SurrogateFunction, self).__init__(*args, **kwargs)
392 super(SurrogateFunction, self).__init__()
394 argPos = kwargs.pop(
'argPos',
False)
397 for k, v
in kwargs[
'inputs'].iteritems():
400 'argPos in function for inputs %s (old format)' % k +
401 ' -- delete argPos from function' 407 for k, v
in kwargs[
'inputs'].iteritems():
410 nInp += v[
'index'].iterator_size()
412 for k, v
in kwargs[
'inputs'].iteritems():
413 if not isinstance(v, MinMaxArgPosOpt):
416 for k, v
in kwargs[
'outputs'].iteritems():
417 if not isinstance(v, MinMaxArgPos):
420 for k, v
in kwargs[
'parameters'].iteritems():
421 if not isinstance(v, MinMaxArgPos):
424 if 'indices' in kwargs:
425 for k, v
in kwargs[
'indices'].iteritems():
426 self.indices[k] = kwargs[
'indices'][k]
428 self.initKwargs(kwargs)
430 for k
in self.inputs.keys():
431 self.checkVariableName(k)
433 for k
in self.outputs.keys():
434 self.checkVariableName(k)
436 for k
in self.parameters.keys():
437 self.checkVariableName(k)
445 def initKwargs(self, kwargs):
446 raise NotImplementedError(
'initKwargs not implemented!')
454 def indexSet(self, name):
455 return self.indices[name]
460 def checkVariableName(self, name):
461 m = re.search(
r'[(.*)]', name)
462 if m
and not m.group(1)
in self.indices:
463 raise Exception(
'Index %s not defined' % m.group(1))
468 def inputs_iterAll(self):
469 for k, v
in self.inputs.iteritems():
471 for idx
in v.index.names:
472 yield '%s[%s]' % (k, idx), v
479 def inputs_size(self):
481 for k, v
in self.inputs.iteritems():
483 size += v.index.iterator_size()
495 def exceptionLoad(self, surrogateFunctionId):
506 def load(self, surrogateFunctionId):
507 return self.objects.get(_id=surrogateFunctionId)
515 def __init__(self, *args, **kwargs):
516 super(CFunction, self).__init__(*args, **kwargs)
528 def initKwargs(self, kwargs):
529 if not kwargs.has_key(
'Ccode'):
530 raise Exception(
'Need Ccode')
532 ln = self.compileCcode(kwargs)
535 '\s*const\s*modena_model_t\s*\*\s*model\s*,' 536 '\s*const\s*double\s*\*\s*inputs\s*,' 537 '\s*double\s*\*\s*outputs\s*\)',
540 fn = fn.strip(
' \t\n\r')
543 self.libraryName = ln
544 self.functionName = fn
549 def compileCcode(self, kwargs):
552 m.update(kwargs[
'Ccode'])
555 ln =
'%s/%s/lib%s.so' % (os.getcwd(), d, h)
557 if(
True or not os.path.exists(ln)):
558 if(
not os.path.isdir(d)): os.mkdir(d)
561 env = jinja2.Environment(lstrip_blocks=
True, trim_blocks=
True)
563 child = env.from_string(
r''' 565 {% block variables %} 566 const double* parameters = model->parameters; 567 {% for k, v in pFunction.inputs.iteritems() %} 568 {% if 'index' in v %} 569 const size_t {{k}}_argPos = {{v.argPos}}; 570 const double* {{k}} = &inputs[{{k}}_argPos]; 571 const size_t {{k}}_size = {{ v.index.iterator_size() }}; 573 const size_t {{k}}_argPos = {{v['argPos']}}; 574 const double {{k}} = inputs[{{k}}_argPos]; 580 parent = env.from_string(kwargs[
'Ccode'])
583 child.stream(pFunction=kwargs, Ccode=parent).dump(
'%s.c' % h)
585 f = open(
'CMakeLists.txt',
'w')
587 cmake_minimum_required (VERSION 2.8) 590 #set(CMAKE_BUILD_TYPE Debug) 592 find_package(MODENA REQUIRED) 593 find_package(LTDL REQUIRED) 595 add_library(%(h)s MODULE %(h)s.c) 596 target_link_libraries(%(h)s MODENA::modena ${LTDL_LIBRARIES}) 598 install(TARGETS %(h)s DESTINATION ${CMAKE_INSTALL_PREFIX}/lib ) 602 from subprocess
import call
616 def __init__(self, *args, **kwargs):
617 if kwargs.has_key(
'_cls'):
618 super(Function, self).__init__(*args, **kwargs)
619 if kwargs.has_key(
'libraryName'):
620 super(Function, self).__init__(*args, **kwargs)
623 if not kwargs.has_key(
'function'):
624 raise Exception(
'Algebraic representation not found')
627 cDouble =
lambda VAR:
'\n'.join(
629 'const double %s = %s[%s];' % (
630 V, VAR, kwargs[VAR][V][
'argPos']
637 outPut =
lambda OUT:
'\n'.join(
639 'outputs[%s] = %s;' % (
640 kwargs[
'outputs'][O][
'argPos'],
641 self.Parse(kwargs[
'function'][O])
654 const modena_model* model, 655 const double* inputs, 664 kwargs[
'Ccode'] = Ccode.format(
665 name=kwargs[
'function'][
'name'],
666 inputs=cDouble(
'inputs'),
667 parameters=cDouble(
'parameters'),
668 outputs=outPut(
'outputs')
671 super(Function, self).__init__(*args, **kwargs)
674 def Parse(self, formula, debug=False, model='', stack={}, delim=0, \
675 var=r'[A-Za-z]+\d*',add=r'\+',sub=r'-',mul=r'\*',\
676 div=r'/',pow=r'\^',dig=r'\d+\.?\d*'\
678 operators=
r'%s|%s|%s|%s|%s' %(add,sub,mul,div,pow)
683 empty = re.match(
'\s',formula)
685 print 'Error: The string is empty' 688 formula = re.sub(
r'\s+',
'',formula)
695 re_var = re.match(var,formula)
696 re_dig = re.match(dig,formula)
697 re_ldel = re.match(ldel,formula)
698 re_rdel = re.match(rdel,formula)
699 re_oper = re.match(operators,formula)
703 tail = formula[len(re_var.group(0)):]
704 head = re_var.group(0)
707 tail = formula[len(re_dig.group(0)):]
708 head = re_dig.group(0)
711 head = re_oper.group(0)
716 head = re_ldel.group(0)
722 head = re_rdel.group(0)
723 tail = formula[len(re_rdel.group(0)):]
728 raise Exception(
'Unmatched parenthesis.')
732 raise Exception(
'The expression syntax is not suported.')
738 return self.Parse(tail,debug,model,stack,delim)
770 _id = StringField(primary_key=
True)
771 surrogateFunction = ReferenceField(SurrogateFunction, required=
True)
772 parameters = ListField(FloatField())
773 meta = {
'allow_inheritance':
True}
777 def __init__(self, *args, **kwargs):
778 self.___refs___.append(weakref.ref(self))
780 if kwargs.has_key(
'_cls'):
781 super(SurrogateModel, self).__init__(*args, **kwargs)
782 self.___indices___ = self.parseIndices(self._id)
785 if hasattr(self,
'importFrom'):
786 __import__(self.importFrom)
789 if not kwargs.has_key(
'_id'):
790 raise Exception(
'Need _id')
794 if not kwargs.has_key(
'surrogateFunction'):
795 raise Exception(
'Need surrogateFunction')
796 if not isinstance(kwargs[
'surrogateFunction'], SurrogateFunction):
797 raise TypeError(
'Need surrogateFunction')
799 self.___indices___ = self.parseIndices(kwargs[
'_id'])
801 kwargs[
'fitData'] = {}
802 kwargs[
'inputs'] = {}
803 for k, v
in kwargs[
'surrogateFunction'].inputs_iterAll():
804 kwargs[
'inputs'][k] = v.to_mongo()
805 if 'index' in kwargs[
'inputs'][k]:
806 del kwargs[
'inputs'][k][
'index']
807 if 'argPos' in kwargs[
'inputs'][k]:
808 del kwargs[
'inputs'][k][
'argPos']
810 kwargs[
'outputs'] = {}
811 for k, v
in kwargs[
'surrogateFunction'].outputs.iteritems():
812 k = self.expandIndices(k)
813 kwargs[
'fitData'][k] = []
816 for k, v
in kwargs[
'inputs'].iteritems():
817 kwargs[
'fitData'][k] = []
820 for k, v
in kwargs[
'inputs'].iteritems():
821 if 'argPos' in v
and not v[
'argPos'] == kwargs[
'surrogateFunction'].inputs[k].argPos:
822 raise Exception(
'argPos in function and model must be the same -- delete argPos from model')
824 self.initKwargs(kwargs)
828 'initialisationStrategy',
829 InitialisationStrategy
832 super(SurrogateModel, self).__init__(*args, **kwargs)
835 for m
in self.substituteModels:
836 if not isinstance(m, SurrogateModel):
838 'Elements of substituteModels ' 839 'must be derived from SurrogateModel' 841 subOutputs.update(m.outputsToModels())
847 nInp = len(self.inputs)
848 for o
in subOutputs.keys():
850 self.inputs_argPos(o)
854 for k, v
in subOutputs[o].inputs.iteritems():
856 self.inputs_argPos(k)
857 except ArgPosNotFound:
858 self.inputs[k] = subOutputs[o].inputs[k]
859 self.inputs[k].argPos = nInp
862 except ArgPosNotFound:
876 def initKwargs(self, kwargs):
877 raise NotImplementedError(
'initKwargs not implemented!')
886 def parseIndices(self, name):
888 m = re.search(
'\[(.*)\]', name)
890 for exp
in m.group(1).split(
','):
891 m = re.search(
'(.*)=(.*)', exp)
893 indices[m.group(1)] = m.group(2)
895 raise Exception(
'Unable to parse %s' % exp)
906 def expandIndices(self, name):
907 m = re.search(
'\[(.*)\]', name)
913 '%s' % self.___indices___[exp]
914 for exp
in m.group(1).split(
',')
918 except ArgPosNotFound:
919 raise Exception(
'Unable to expand indices in %s' % name)
924 def expandIndicesWithName(self, name):
925 m = re.search(
'\[(.*)\]', name)
931 '%s=%s' % (exp, self.___indices___[exp])
932 for exp
in m.group(1).split(
',')
936 except ArgPosNotFound:
937 raise Exception(
'Unable to expand indices in %s' % name)
946 def outputsToModels(self):
947 o = { k: self
for k
in self.outputs.keys() }
948 for m
in self.substituteModels:
949 o.update(m.outputsToModels())
958 def inputsMinMax(self):
965 obj = type(
'MinMax', (object,), {})
970 i = { k: new(v.min, v.max)
for k, v
in self.surrogateFunction.inputs_iterAll() }
972 for m
in self.substituteModels:
973 for k, v
in m.inputsMinMax().iteritems():
975 v.min = max(v.min, i[k].min)
976 v.max = min(v.max, i[k].max)
978 i[k] = new(v.min, v.max)
986 def inputs_argPos(self, name):
987 m = re.search(
'(.*)\[(.*=)?(.*)]', name)
992 + self.surrogateFunction.inputs[base].index.get_index(m.group(3))
994 raise ArgPosNotFound(
'argPos for ' + name +
' not found in inputs')
1002 raise ArgPosNotFound(
'argPos for ' + name +
' not found in inputs')
1007 def outputs_argPos(self, name):
1013 self.surrogateFunction.outputs,
1017 raise ArgPosNotFound(
'argPos for ' + name +
' not found in outputs')
1022 def parameters_argPos(self, name):
1028 self.surrogateFunction.parameters,
1032 raise ArgPosNotFound(
'argPos for ' + name +
' not found in parameters')
1037 def calculate_maps(self, sm):
1041 for k
in self.inputs:
1043 map_inputs.extend([self.inputs_argPos(k), sm.inputs_argPos(k)])
1044 except ArgPosNotFound:
1047 for k, v
in sm.surrogateFunction.outputs.iteritems():
1050 [v.argPos, self.inputs_argPos(sm.expandIndices(k))]
1052 except ArgPosNotFound:
1056 return map_outputs, map_inputs
1062 l = self.surrogateFunction.inputs_size()
1063 minValues = [-9e99] * l
1064 maxValues = [9e99] * l
1066 for k, v
in self.inputs.iteritems():
1067 minValues[self.inputs_argPos(k)] = v.min
1068 maxValues[self.inputs_argPos(k)] = v.max
1071 return minValues, maxValues, \
1072 self.inputs.keys(), \
1073 self.outputs.keys(), \
1074 self.surrogateFunction.parameters.keys()
1079 def updateMinMax(self):
1080 if not self.nSamples:
1081 for v
in self.inputs.values():
1085 for v
in self.outputs.values():
1089 for k, v
in self.inputs.iteritems():
1090 v.min = min(self.fitData[k])
1091 v.max = max(max(self.fitData[k]), v.min*1.000001)
1093 for k, v
in self.outputs.iteritems():
1094 v.min = min(self.fitData[k])
1095 v.max = max(self.fitData[k])
1105 def error(self, cModel, **kwargs):
1106 idxGenerator = kwargs.pop(
'idxGenerator', xrange(self.nSamples))
1107 checkBounds = kwargs.pop(
'checkBounds',
True)
1109 i = [0] * self.surrogateFunction.inputs_size()
1112 output = self.fitData[six.next(six.iterkeys(self.outputs))]
1114 for idx
in idxGenerator:
1116 for k, v
in self.inputs.iteritems():
1117 i[self.inputs_argPos(k)] = self.fitData[k][idx]
1125 out = cModel(i, checkBounds= checkBounds)
1130 yield out[0] - output[idx]
1139 def __getattribute__(self, name):
1140 if name.startswith(
'___' ):
1141 return object.__getattribute__(self, name)
1143 return super(SurrogateModel, self).__getattribute__(name)
1152 def __setattribute__(self, name, value):
1153 if name.startswith(
'___' ):
1154 object.__setattribute__(self, name, value)
1156 super(SurrogateModel, self).__setattribute__(name, value)
1165 def exceptionOutOfBounds(self, oPoint):
1167 k: oPoint[self.inputs_argPos(k)]
for k
in self.inputs.keys()
1169 self.outsidePoint =
EmbDoc(**oPointDict)
1185 def exceptionLoad(self, surrogateModelId):
1186 collection = self._get_collection()
1188 {
'_id': surrogateModelId },
1189 {
'_id': surrogateModelId },
1200 def exceptionParametersNotValid(self, surrogateModelId):
1209 def callModel(self, inputs):
1212 cModel = modena.libmodena.modena_model_t(model=self)
1214 i = [0] * self.surrogateFunction.inputs_size()
1216 for m
in self.substituteModels:
1217 inputs.update(m.callModel(inputs))
1222 for k, v
in self.inputs.iteritems():
1223 i[self.inputs_argPos(k)] = inputs[k]
1229 self.expandIndices(k): out[v.argPos]
1230 for k, v
in self.surrogateFunction.outputs.iteritems()
1240 def updateFitDataFromFwSpec(self, fw_spec):
1245 for k, v
in self.inputs.iteritems():
1246 if fw_spec[k][0].__class__ == list:
1247 self.fitData[k].extend(fw_spec[k][0])
1249 self.fitData[k].extend(fw_spec[k])
1251 for k
in self.outputs:
1252 if fw_spec[k][0].__class__ == list:
1253 self.fitData[k].extend(fw_spec[k][0])
1255 self.fitData[k].extend(fw_spec[k])
1258 firstSet = six.next(six.itervalues(self.fitData))
1259 self.nSamples = len(firstSet)
1264 def initialisationStrategy(self):
1267 'initialisationStrategy',
1268 InitialisationStrategy
1275 def load(self, surrogateModelId):
1280 return self.objects.get(_id=surrogateModelId)
1286 def loadFailing(self):
1291 return self.objects(
1292 __raw__={
'outsidePoint': {
'$exists':
True}}
1299 def loadFromModule(self):
1300 collection = self._get_collection()
1301 doc = collection.find_one({
'_cls': {
'$exists':
False}})
1302 modName = re.search(
'(.*)(\[.*\])?', doc[
'_id']).group(1)
1306 mod = __import__(modName)
1307 return (m
for m
in modena.BackwardMappingModel.get_instances()
if m._id == modName).next()
1309 print "MoDeNa framework error: could not find '%s' " %(modName)
1315 def loadParametersNotValid(self):
1316 return self.objects(
1317 __raw__={
'parameters': {
'$size': 0 } }
1324 def get_instances(self):
1325 for inst_ref
in self.___refs___:
1327 if inst
is not None:
1349 inputs = MapField(EmbeddedDocumentField(MinMaxArgPosOpt))
1350 outputs = MapField(EmbeddedDocumentField(MinMaxArgPosOpt))
1351 substituteModels = ListField(ReferenceField(SurrogateModel))
1352 meta = {
'allow_inheritance':
True}
1354 def __init__(self, *args, **kwargs):
1355 super(ForwardMappingModel, self).__init__(*args, **kwargs)
1358 def initKwargs(self, kwargs):
1359 if 'initialisationStrategy' not in kwargs:
1360 kwargs[
'initialisationStrategy'] = \
1361 EmptyInitialisationStrategy()
1368 def exactTasks(self, points):
1377 inputs =
IOP(EmbeddedDocumentField(MinMaxArgPosOpt))
1378 outputs = MapField(EmbeddedDocumentField(MinMaxArgPosOpt))
1379 fitData = MapField(ListField(FloatField(required=
True)))
1380 substituteModels = ListField(ReferenceField(SurrogateModel))
1381 outsidePoint = EmbeddedDocumentField(EmbDoc)
1382 meta = {
'allow_inheritance':
True}
1385 def __init__(self, *args, **kwargs):
1386 super(BackwardMappingModel, self).__init__(*args, **kwargs)
1389 def initKwargs(self, kwargs):
1394 'outOfBoundsStrategy',
1400 'parameterFittingStrategy',
1401 ParameterFittingStrategy
1409 def exactTasks(self, points):
1412 et = load_object(self.meth_exactTask)
1415 e = six.next(six.itervalues(points))
1416 for i
in xrange(len(e)):
1417 p = { k: points[k][i]
for k
in points }
1421 t[
'indices'] = self.___indices___
1422 t[
'modelId'] = self._id
1427 return Workflow(tl, name=
'exact tasks for new points')
1430 def parameterFittingStrategy(self):
1433 'parameterFittingStrategy',
1434 ParameterFittingStrategy
1438 self._changed_fields = filter(
1439 lambda a: a !=
u'improveErrorStrategy._fw_name', self._changed_fields
1445 def outOfBoundsStrategy(self):
1448 'outOfBoundsStrategy',
1480 def extendedRange(self, outsidePoint, expansion_factor=1.2):
1485 for k, v
in self.inputs.iteritems():
1487 outsideValue = outsidePoint[k]
1488 inputsMinMax = self.inputsMinMax()
1493 if outsideValue > v[
'max']:
1494 if outsideValue > inputsMinMax[k].max:
1496 'new value is larger than function min for %s' % k
1500 outsideValue*expansion_factor,
1504 sampleRange[k][
'min'] = v[
'max']
1505 sampleRange[k][
'max'] = value
1506 limitPoint[k] = value
1508 elif outsideValue < v[
'min']:
1509 if outsideValue < inputsMinMax[k].min:
1511 'new value is smaller than function max for %s' % k
1515 outsideValue/expansion_factor,
1519 sampleRange[k][
'min'] = value
1520 sampleRange[k][
'max'] = v[
'min']
1521 limitPoint[k] = value
1524 sampleRange[k][
'min'] = v[
'min']
1525 sampleRange[k][
'max'] = v[
'max']
1526 limitPoint[k] = random.uniform(v[
'min'], v[
'max'])
1528 return sampleRange, limitPoint
def checkAndConvertType(kwargs, name, cls)
Function checking if the type of the strategy "name" provided by the user is correct, i.e.
Class for defining 'backward mapping' models.
Class list that is automatically extended when index is out of range.
def existsAndHasArgPos(i, name)
Function checking whether the model inputs corresponds to the arguments.
def loadType(obj, name, cls)
Function that helps loading strategy "name" from model "obj".
Class for defining 'forward mapping' models.
Class wrapper for DynamicEmbeddedDocument from MongeEngine.
Class for defining Surrogate Functions where the executable code is a C- function.