def generate_penalty(conditions, ptype=None, **kwds): """Converts a penalty constraint function to a mystic.penalty function. Inputs: conditions -- a penalty constraint function, or list of constraint functions ptype -- a mystic.penalty type, or a list of mystic.penalty types of the same length as the given conditions For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> ineqf,eqf = generate_conditions(constraints, nvars=3) >>> penalty = generate_penalty((ineqf,eqf)) >>> penalty([1.,2.,0.]) 25.0 >>> penalty([1.,2.,0.5]) 0.0 Additional Inputs: k -- penalty multiplier h -- iterative multiplier """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions, )) else: pass #XXX: should be fine... conditions = list(flatten(conditions)) # allow for single ptype, list of ptypes, or nested list if ptype is None: ptype = [] from mystic.penalty import quadratic_equality, quadratic_inequality for condition in conditions: if 'inequality' in condition.__name__: ptype.append(quadratic_inequality) else: ptype.append(quadratic_equality) elif not list_or_tuple_or_ndarray(ptype): ptype = list((ptype, )) * len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ptype = list(flatten(ptype)) # iterate through penalties, building a compound penalty function pf = lambda x: 0.0 pfdoc = "" for penalty, condition in zip(ptype, conditions): pfdoc += "%s: %s\n" % (penalty.__name__, condition.__doc__) apply = penalty(condition, **kwds) pf = apply(pf) pf.__doc__ = pfdoc.rstrip('\n') pf.__name__ = 'penalty' return pf
def generate_penalty(conditions, ptype=None, **kwds): """Converts a penalty constraint function to a mystic.penalty function. Inputs: conditions -- a penalty constraint function, or list of constraint functions ptype -- a mystic.penalty type, or a list of mystic.penalty types of the same length as the given conditions For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> ineqf,eqf = generate_conditions(constraints, nvars=3) >>> penalty = generate_penalty((ineqf,eqf)) >>> penalty([1.,2.,0.]) 25.0 >>> penalty([1.,2.,0.5]) 0.0 Additional Inputs: k -- penalty multiplier h -- iterative multiplier """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions,)) else: pass #XXX: should be fine... conditions = list(flatten(conditions)) # allow for single ptype, list of ptypes, or nested list if ptype is None: ptype = [] from mystic.penalty import quadratic_equality, quadratic_inequality for condition in conditions: if 'inequality' in condition.__name__: ptype.append(quadratic_inequality) else: ptype.append(quadratic_equality) elif not list_or_tuple_or_ndarray(ptype): ptype = list((ptype,))*len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ptype = list(flatten(ptype)) # iterate through penalties, building a compound penalty function pf = lambda x:0.0 pfdoc = "" for penalty, condition in zip(ptype, conditions): pfdoc += "%s: %s\n" % (penalty.__name__, condition.__doc__) apply = penalty(condition, **kwds) pf = apply(pf) pf.__doc__ = pfdoc.rstrip('\n') pf.__name__ = 'penalty' return pf
def _flat(params): """ converts a nested parameter list into flat parameter list Inputs: params -- a nested list of weights or positions For example: >>> par = [['x','x','x'], ['y','y'], ['z']] >>> _flat(par) ['x','x','x','y','y','z'] """ from mystic.tools import flatten return list(flatten(params))
# else: select[i] = _select[i] #for i in range(len(select)): # p = select[i].split(":") # if p[0][0] == '-': p[0] = "len(x)"+p[0] # if p[1][0] == '-': p[1] = "len(x)"+p[1] # select[i] = p[0]+":"+p[1] #steps = [eval("range(%s)" % sel.replace(":",",")) for sel in select] steps = [eval("[int(%s)]" % sel) for sel in select] # at this point, we should have: #xyz = [(2,3),(6,7),(10,11)] for any length tuple #wxyz = [(0,1),(4,5),(8,9)] for any length tuple (should match up with xyz) #steps = [[0],[1],[3],[8]] or similar if flatten: from mystic.tools import flatten steps = [list(flatten(steps))] # adjust for logarithmic scaling of intensity from numpy import e scale = e**(scale - 1.0) # dot color is based on a product of weights t = [] for v in range(len(steps)): t.append([]) for s in steps[v]: for i in eval("[params[q][%s] for q in wxyz[0]]" % s): for j in eval("[params[q][%s] for q in wxyz[1]]" % s): for k in eval("[params[q][%s] for q in wxyz[2]]" % s): t[v].append([str((1.0 - i[q]*j[q]*k[q])**scale) for q in range(len(i))]) if float(t[v][-1][-1]) > 1.0 or float(t[v][-1][-1]) < 0.0:
def generate_constraint(conditions, ctype=None, **kwds): """Converts a constraint solver to a mystic.constraints function. Inputs: conditions -- a constraint solver, or list of constraint solvers ctype -- a mystic.constraints type, or a list of mystic.constraints types of the same length as the given conditions NOTES: This simple constraint generator doesn't check for conflicts in conditions, but simply applies conditions in the given order. This constraint generator assumes that a single variable has been isolated on the left-hand side of each constraints equation, thus all constraints are of the form "x_i = f(x)". This solver picks speed over robustness, and thus relies on the user to formulate the constraints so that they do not conflict. For example: >>> constraints = ''' ... x0 = cos(x1) + 2. ... x1 = x2*2.''' >>> solv = generate_solvers(constraints) >>> constraint = generate_constraint(solv) >>> constraint([1.0, 0.0, 1.0]) [1.5838531634528576, 2.0, 1.0] Standard python math conventions are used. For example, if an 'int' is used in a constraint equation, one or more variable may be evaluate to an 'int' -- this can affect solved values for the variables. For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> solv = generate_solvers(constraints, nvars=3) >>> print solv[0].__doc__ 'x[2] = x[0]/2.' >>> print solv[1].__doc__ 'x[0] = max(0., x[0])' >>> constraint = generate_constraint(solv) >>> constraint([1,2,3]) [1, 2, 0.5] >>> constraint([-1,2,-3]) [0.0, 2, 0.0] """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions,)) else: pass #XXX: should be fine... conditions = list(flatten(conditions)) # allow for single ctype, list of ctypes, or nested list if ctype is None: from mystic.coupler import inner #XXX: outer ? ctype = list((inner,))*len(conditions) elif not list_or_tuple_or_ndarray(ctype): ctype = list((ctype,))*len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ctype = list(flatten(ctype)) # iterate through solvers, building a compound constraints solver cf = lambda x:x cfdoc = "" for wrapper, condition in zip(ctype, conditions): cfdoc += "%s: %s\n" % (wrapper.__name__, condition.__doc__) apply = wrapper(condition, **kwds) cf = apply(cf) cf.__doc__ = cfdoc.rstrip('\n') cf.__name__ = 'constraint' return cf
def __upper(self): "get list of upper bounds" n = (self.n, ) if not hasattr(self.n, '__len__') else self.n xub = (self.xub, ) if not hasattr(self.xub, '__len__') else self.xub return list(flatten(i * [j] for i, j in zip(n, xub)))
def __lower(self): "get list of lower bounds" n = (self.n, ) if not hasattr(self.n, '__len__') else self.n xlb = (self.xlb, ) if not hasattr(self.xlb, '__len__') else self.xlb return list(flatten(i * [j] for i, j in zip(n, xlb)))
def __upper(self): n = (self.n, ) if not hasattr(self.n, '__len__') else self.n wub = (self.wub, ) if not hasattr(self.wub, '__len__') else self.wub xub = (self.xub, ) if not hasattr(self.xub, '__len__') else self.xub return list(flatten(i * [j] + i * [k] for i, j, k in zip(n, wub, xub)))
def __lower(self): n = (self.n, ) if not hasattr(self.n, '__len__') else self.n wlb = (self.wlb, ) if not hasattr(self.wlb, '__len__') else self.wlb xlb = (self.xlb, ) if not hasattr(self.xlb, '__len__') else self.xlb return list(flatten(i * [j] + i * [k] for i, j, k in zip(n, wlb, xlb)))
for i in range(len(_select)): if _select[i][-1] == ':': select[i] = _select[i] + str(len(x)) else: select[i] = _select[i] for i in range(len(select)): p = select[i].split(":") if p[0][0] == '-': p[0] = "len(x)" + p[0] if p[1][0] == '-': p[1] = "len(x)" + p[1] select[i] = p[0] + ":" + p[1] steps = [eval("range(%s)" % sel.replace(":", ",")) for sel in select] # at this point, we should have: #xyz = [(0,1),(4,5),(8,9)] for any length tuple #steps = [[0,1],[1,2],[2,3],[3,4,5,6,7,8]] or similar if flatten: from mystic.tools import flatten steps = [list(flatten(steps))] # build all the plots from numpy import inf, e scale = e**(scale - 1.0) for v in range(len(steps)): if len(steps[v]) > 1: qp = float(max(steps[v])) else: qp = inf for s in steps[v]: # dot color determined by number of simultaneous iterations t = str((s / qp)**scale) for i in eval("[params[q][%s] for q in xyz[0]]" % s): for j in eval("[params[q][%s] for q in xyz[1]]" % s): for k in eval("[params[q][%s] for q in xyz[2]]" % s): a[v].plot(i, j, k, marker='o', color=t, ms=10)
def generate_constraint(conditions, ctype=None, **kwds): """Converts a constraint solver to a mystic.constraints function. Inputs: conditions -- a constraint solver, or list of constraint solvers ctype -- a mystic.constraints type, or a list of mystic.constraints types of the same length as the given conditions NOTES: This simple constraint generator doesn't check for conflicts in conditions, but simply applies conditions in the given order. This constraint generator assumes that a single variable has been isolated on the left-hand side of each constraints equation, thus all constraints are of the form "x_i = f(x)". This solver picks speed over robustness, and thus relies on the user to formulate the constraints so that they do not conflict. For example: >>> constraints = ''' ... x0 = cos(x1) + 2. ... x1 = x2*2.''' >>> solv = generate_solvers(constraints) >>> constraint = generate_constraint(solv) >>> constraint([1.0, 0.0, 1.0]) [1.5838531634528576, 2.0, 1.0] Standard python math conventions are used. For example, if an 'int' is used in a constraint equation, one or more variable may be evaluate to an 'int' -- this can affect solved values for the variables. For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> solv = generate_solvers(constraints, nvars=3) >>> print solv[0].__doc__ 'x[2] = x[0]/2.' >>> print solv[1].__doc__ 'x[0] = max(0., x[0])' >>> constraint = generate_constraint(solv) >>> constraint([1,2,3]) [1, 2, 0.5] >>> constraint([-1,2,-3]) [0.0, 2, 0.0] """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions, )) else: pass #XXX: should be fine... conditions = list(flatten(conditions)) # allow for single ctype, list of ctypes, or nested list if ctype is None: from mystic.coupler import inner #XXX: outer ? ctype = list((inner, )) * len(conditions) elif not list_or_tuple_or_ndarray(ctype): ctype = list((ctype, )) * len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ctype = list(flatten(ctype)) # iterate through solvers, building a compound constraints solver cf = lambda x: x cfdoc = "" for wrapper, condition in zip(ctype, conditions): cfdoc += "%s: %s\n" % (wrapper.__name__, condition.__doc__) apply = wrapper(condition, **kwds) cf = apply(cf) cf.__doc__ = cfdoc.rstrip('\n') cf.__name__ = 'constraint' return cf
def generate_penalty(conditions, ptype=None, join=None, **kwds): """Converts a penalty constraint function to a mystic.penalty function. Inputs: conditions -- a penalty constraint function, or list of constraint functions ptype -- a mystic.penalty type, or a list of mystic.penalty types of the same length as the given conditions join -- either (and_, or_) from mystic.coupler, or None. The default is to iteratively apply the penalties. For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> ineqf,eqf = generate_conditions(constraints, nvars=3) >>> penalty = generate_penalty((ineqf,eqf)) >>> penalty([1.,2.,0.]) 25.0 >>> penalty([1.,2.,0.5]) 0.0 Additional Inputs: k -- penalty multiplier h -- iterative multiplier """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions,)) else: pass #XXX: should be fine... # discover the nested structure of conditions and ptype nc = nt = 0 if ptype is None or not list_or_tuple_or_ndarray(ptype): nt = -1 else: while tuple(flatten(conditions, nc)) != tuple(flatten(conditions)): nc += 1 while tuple(flatten(ptype, nt)) != tuple(flatten(ptype)): nt += 1 if join is None: pass # don't use 'and/or' to join the conditions #elif nc >= 2: # join when is tuple of tuples of conditions else: # always use join, if given (instead of only if nc >= 2) if nt >= nc: # there as many or more nested ptypes than conditions p = iter(ptype) return join(*(generate_penalty(c, next(p), **kwds) for c in conditions)) return join(*(generate_penalty(c, ptype, **kwds) for c in conditions)) # flatten everything and produce the penalty conditions = list(flatten(conditions)) # allow for single ptype, list of ptypes, or nested list if ptype is None: ptype = [] from mystic.penalty import quadratic_equality, quadratic_inequality for condition in conditions: if 'inequality' in condition.__name__: ptype.append(quadratic_inequality) else: ptype.append(quadratic_equality) elif not list_or_tuple_or_ndarray(ptype): ptype = list((ptype,))*len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ptype = list(flatten(ptype)) # iterate through penalties, building a compound penalty function pf = lambda x:0.0 pfdoc = "" for penalty, condition in zip(ptype, conditions): pfdoc += "%s: %s\n" % (penalty.__name__, condition.__doc__) apply = penalty(condition, **kwds) pf = apply(pf) pf.__doc__ = pfdoc.rstrip('\n') pf.__name__ = 'penalty' return pf
def generate_constraint(conditions, ctype=None, join=None, **kwds): """Converts a constraint solver to a mystic.constraints function. Inputs: conditions -- a constraint solver, or list of constraint solvers ctype -- a mystic.coupler type, or a list of mystic.coupler types of the same length as the given conditions join -- either (and_, or_) from mystic.constraints, or None. The default is to iteratively apply the constraints. NOTES: This simple constraint generator doesn't check for conflicts in conditions, but simply applies conditions in the given order. This constraint generator assumes that a single variable has been isolated on the left-hand side of each constraints equation, thus all constraints are of the form "x_i = f(x)". This solver picks speed over robustness, and thus relies on the user to formulate the constraints so that they do not conflict. For example: >>> constraints = ''' ... x0 = cos(x1) + 2. ... x1 = x2*2.''' >>> solv = generate_solvers(constraints) >>> constraint = generate_constraint(solv) >>> constraint([1.0, 0.0, 1.0]) [1.5838531634528576, 2.0, 1.0] Standard python math conventions are used. For example, if an 'int' is used in a constraint equation, one or more variable may be evaluate to an 'int' -- this can affect solved values for the variables. For example: >>> constraints = ''' ... x2 = x0/2. ... x0 >= 0.''' >>> solv = generate_solvers(constraints, nvars=3) >>> print solv[0].__doc__ 'x[2] = x[0]/2.' >>> print solv[1].__doc__ 'x[0] = max(0., x[0])' >>> constraint = generate_constraint(solv) >>> constraint([1,2,3]) [1, 2, 0.5] >>> constraint([-1,2,-3]) [0.0, 2, 0.0] """ # allow for single condition, list of conditions, or nested list if not list_or_tuple_or_ndarray(conditions): conditions = list((conditions,)) else: pass #XXX: should be fine... # discover the nested structure of conditions and ctype nc = nt = 0 if ctype is None or not list_or_tuple_or_ndarray(ctype): nt = -1 else: while tuple(flatten(conditions, nc)) != tuple(flatten(conditions)): nc += 1 while tuple(flatten(ctype, nt)) != tuple(flatten(ctype)): nt += 1 if join is None: pass # don't use 'and/or' to join the conditions #elif nc >= 2: # join when is tuple of tuples of conditions else: # always use join, if given (instead of only if nc >= 2) if nt >= nc: # there as many or more nested ctypes than conditions p = iter(ctype) return join(*(generate_constraint(c, next(p), **kwds) for c in conditions)) return join(*(generate_constraint(c, ctype, **kwds) for c in conditions)) # flatten everything and produce the constraint conditions = list(flatten(conditions)) # allow for single ctype, list of ctypes, or nested list if ctype is None: from mystic.coupler import inner #XXX: outer ? ctype = list((inner,))*len(conditions) elif not list_or_tuple_or_ndarray(ctype): ctype = list((ctype,))*len(conditions) else: pass #XXX: is already a list, should be the same len as conditions ctype = list(flatten(ctype)) # iterate through solvers, building a compound constraints solver cf = lambda x:x cfdoc = "" for wrapper, condition in zip(ctype, conditions): cfdoc += "%s: %s\n" % (wrapper.__name__, condition.__doc__) apply = wrapper(condition, **kwds) cf = apply(cf) cf.__doc__ = cfdoc.rstrip('\n') cf.__name__ = 'constraint' return cf