source: trunk/GSASIImapvars.py @ 411

Last change on this file since 411 was 411, checked in by vondreele, 10 years ago

fix very old (!) bug in psvfcj.for
implement neutron scattering lengths in GSASII including the dozen anomalous scattering isotopes
isotope choice is in General
so GSASII will now do neutron CW Rietveld refinements
some cleanup of the constraints GUI
remove varyList from GSASIImapvars.py globals

File size: 27.7 KB
Line 
1# $Date: 2011-01-07 13:27:24 -0600 (Fri, 07 Jan 2011) $
2# $Author: toby $
3# $Revision: 230 $
4# $URL: https://subversion.xor.aps.anl.gov/pyGSAS/trunk/GSASIImapvars.py $
5# $Id: GSASIImapvars.py 230 2011-01-07 19:27:24Z vondreele $
6########### SVN repository information ###################
7"""Module that implements algebraic contraints, parameter redefinition
8and parameter simplification contraints.
9
10Parameter redefinition is done by creating one or more relationships
11between a set of parameters
12   Mx1 * Px + My1 * Py +...
13   Mx2 * Px + Mz2 * Pz + ...
14where Pj is a parameter name and Mjk is a constant.
15
16Relations are typically supplied as input to InputParse, where either
17of two keywords can be attached to a relationship:
18 * VARY which means the generated parameter name will be included in
19  the list of variables to be refined (varyList)
20 * VARYFREE which means that all generated parameter names for a
21  group, including the ones for generated relationships (see below)
22  will be included in the list of variables to be refined (varyList)
23  The case of VARY and VARYFREE is immaterial.
24
25Relations can also be supplied in the form of an equation:
26  nx1 * Px + ny1 * Py +... = C1
27where Cn is a constant. These equations define an algebraic
28constrant. The keyword VARY makes no sense when used with a constraint
29equation, but VARYFREE can be used.  #RVD??? is VARYFREE required or default??
30
31Unconstrained relations describe a new, independent, parameter, which
32is defined in terms of dependent parameters that are defined in the
33Model, while constrained relations effectively reduce the complexity
34of the Model by removing a degree of freedom.
35
36Relationships are grouped so that a set of dependent parameters appear
37in only one group (done in routine GroupConstraints.) Note that if a
38group contains relationships/equations that involve N dependent
39parameters, there must exist N-C new parameters, where C is the number
40of contraint equations in the group. Routine GenerateConstraints takes
41the output from InputParse and GroupConstraints generates the
42"missing" relationships and saves that information in the module's
43global variables. Each generated parameter is named
44sequentially using paramPrefix.
45
46Parameter redefinition is done by equating one (independent) parameter to several
47(now dependent) parameters, in algebraic form:
48  P1 = n2 * P2 = n3 * P3 ...
49Each equality in the relationship reduces the complexity of the model
50by one potentially variable parameter. Input is provided to routine
51StoreEquivalence in the form of an independent parameter and a list of
52dependent parameters, optionally with a multiplier.
53
54Note that none of the dependent parameters in any constraint or
55reformulation can be refined (see dependentParmList, below).
56
57External Routines:
58   To define a set of constrained and unconstrained relations, one
59     calls InputParse, GroupConstraints and GenerateConstraints. It
60     is best to supply all relations/equations in one call to these
61     routines so that grouping is done correctly.
62
63   To implement parameter redefinition, one calls
64     StoreEquivalence. This should be called for every set of
65     equivalence relationships. There is no harm in using
66     StoreEquivalence with the same independent variable:
67       StoreEquivalence('x',('y',))
68       StoreEquivalence('x',('z',))
69     (though StoreEquivalence('x',('y','z')) will run more
70     efficiently) but mixing independent and dependent variables is
71     problematic. This may not work properly:
72        StoreEquivalence('x',('y',))
73        StoreEquivalence('y',('z',))
74
75   To show a summary of the parameter remapping, one calls
76      VarRemapShow
77
78   To determine values for the parameters created in this module, one
79      calls Map2Dict. This will not apply contraints.
80
81   To take values from the new independent parameters and constraints,
82      one calls Dict2Map. This will apply contraints.
83
84Global Variables:
85   dependentParmList: contains a list by group of lists of
86     parameters used in the group. Note that parameters listed in
87     dependentParmList should not be refined as they will not affect
88     the model
89   indParmList: a list of groups of Independent parameters defined in
90     each group. This contains both parameters used in parameter
91     redefinitions as well as names of generated new parameters.
92   
93   arrayList: a list by group of relationship matrices to relate
94     parameters in dependentParmList to those in indParmList. Unlikely
95     to be used externally.
96   invarrayList: a list by group of relationship matrices to relate
97     parameters in indParmList to those in dependentParmList. Unlikely
98     to be used externally.
99   fixedDict: a dictionary containing the fixed values corresponding
100     to parameter equations.  The dict key is an ascii string, but the
101     dict value is a float.  Unlikely to be used externally.
102"""
103
104import numpy as np
105import re
106# data used for constraints;
107debug = False # turns on printing as constraint input is processed
108# note that constraints are stored listed by contraint groups, where each constraint
109# group contains those parameters that must be handled together
110dependentParmList = [] # contains a list of parameters in each group
111# note that parameters listed in dependentParmList should not be refined
112arrayList = [] # a list of of relationship matrices
113invarrayList = [] # a list of inverse relationship matrices
114indParmList = [] # a list of names for the new parameters
115fixedDict = {} # a dictionary containing the fixed values corresponding to defined parameter equations
116               # key is original ascii string, value is float
117
118# compile regular expressions used for parsing input
119rex_mult = re.compile('[+-]?[0-9.]+[eE]?[+-]?[0-9]*')
120rex_star = re.compile('\s*\*\s*')
121rex_var = re.compile('\w+')
122rex_plusminus = re.compile('\s*[+-=]\s*')
123rex_vary = re.compile('\s*Vary\s*', re.IGNORECASE)
124rex_varyfree = re.compile('(.*)\s*VaryFree\s*', re.IGNORECASE)
125
126# prefix for parameter names
127paramPrefix = "::constr:"
128consNum = 0 # number of the next constraint to be created
129
130def InitVars():
131    '''Initializes all constraint information'''
132    global dependentParmList,arrayList,invarrayList,indParmList,fixedDict,consNum
133    dependentParmList = [] # contains a list of parameters in each group
134    arrayList = [] # a list of of relationship matrices
135    invarrayList = [] # a list of inverse relationship matrices
136    indParmList = [] # a list of names for the new parameters
137    fixedDict = {} # a dictionary containing the fixed values corresponding to defined parameter equations
138    consNum = 0 # number of the next constraint to be created
139
140def InputParse(mapList):
141    '''Converts a set relationships used to remap parameters into composite
142    parameters or to one or more constants.
143       
144    Input:
145      mapList: a list of character strings where each string defines
146    a relationship in form:
147    ('<const11>*<prm1> [+-] <const12>*<prm2> [+-] ... = <value> [VaryFree]',
148    '<const21>*<prm1> [+-] <const22>*<prm2> [+-] ... [Vary/VaryFree]',
149    ...)
150    these define either a constraint or a new independent parameter,
151    where <constXX> is a constant containing an optional sign, digits,
152    optionally a decimal point and/or an exponent, prefixed by e or E,
153    and <prmN> is the name of a parameter defined in the Model.
154    Parameters can be included in any order. Multiplying a parameter
155    by 0 causes that parameter to be included in a group of
156    relationships.  Note that if the same parameter is included twice
157    in a relationship/equation, the coefficients are added.
158   
159    When an equality is defined, a constant, <value>, is
160    included. This then describes a constraint equation.
161   
162    Vary is an optional keyword that indicates the indicated remapped
163    parameter should be varied (note, case insensitive). Should be the
164    last item on the line. Makes no sense with an equation.
165
166    VaryFree is an optional keyword that indicates all possible
167    remapped parameters should be varied (note, case
168    insensitive). Makes most sense with a constraint equation.  Should
169    be the last item on the line.
170
171    returns
172      constrDict: a list with a dict for each item in mapList that
173        defines the relationship. The keys are parameter names and the
174        values are the multiplier for the parameter name
175      constrFlag: a list for each item in mapList with a list contains
176        'Vary' and/or 'VaryFree'
177      fixedList: a list for each item in mapList. Contains the value
178        (as a string) for each contraint equation or None for a
179        constraint relationship.
180    '''
181    i = 0
182    constrDict = []
183    fixedList = []
184    constrFlag = []
185    if debug: print 50*'-','\n(Input)'
186    for line in mapList:
187        line = line.strip()
188        if len(line) == 0: continue # empty lines are ignored
189        constrDict.append({})
190        constrFlag.append([])
191        fixedList.append(None)
192        i += 1
193        fixedval = None
194        if debug: print '\t',line
195        try: 
196            j = 0
197            sign = 1.0
198            while len(line):
199                j += 1
200                m = sign * float(rex_mult.match(line).group())
201                line = line[rex_mult.match(line).end():]
202                j += 1
203                line = line[rex_star.match(line).end():]
204                j += 1
205                v = rex_var.match(line).group()
206                line = line[rex_var.match(line).end():]
207                #print m,'times',v
208                #if v not in varlist: varlist.append(v)
209                if constrDict[i-1].get(v) == None:
210                    constrDict[i-1][v] = m
211                else:
212                    constrDict[i-1][v] += m
213                if len(line.strip()) == 0: break
214                j += 1
215                # advance to next separator (+-=)
216                pm = rex_plusminus.match(line)
217                if pm != None:
218                    line = line[pm.end():]
219                    pm = pm.group()
220                else:
221                    pm = ''
222                if pm.strip() == '+':
223                    sign = 1.0
224                elif pm.strip() == '-':
225                    sign = -1.0
226                elif pm.strip() == '=':
227                    # found a fixed value, also check for a VaryFree flag
228                    if rex_varyfree.match(line):
229                        constrFlag[-1].append('VaryFree')
230                        #fixedval = float(rex_varyfree.split(line)[1])
231                        fixedval = rex_varyfree.split(line)[1].strip()
232                    else:
233                        #fixedval = float(line.strip())
234                        fixedval = line.strip()
235                    fixedList[-1] = fixedval
236                    line = ""
237                elif rex_varyfree.match(line):
238                    constrFlag[-1].append('VaryFree')
239                    line = line[rex_varyfree.match(line).end():]
240                elif rex_vary.match(line):
241                    constrFlag[-1].append('Vary')
242                    line = line[rex_vary.match(line).end():]
243                else:
244                    # something else is on the line, but not a keyword
245                    raise Exception
246        except SyntaxError:
247            if debug: print 'Error in line',i,'token',j,'@','"'+line+'"'
248            raise Exception,'Error in line %d token %d, beginning with %s'% (i,j, line)
249
250    if debug: # on debug, show what is parsed in a semi-readable
251        print 50*'-','\n(parsed relationship/equation & flag)'
252        for i in range(len(constrDict)):
253            flags = ''
254            for f in constrFlag[i]:
255                if flags != '':
256                    flags = flags + ' + ' + f
257                else:
258                    flags = f
259            if fixedList[i] is None:
260                print '#',i+1,constrDict[i],'\t',constrFlag[i]
261            else:
262                print '#',i+1,constrDict[i],'=',fixedList[i],'\t',constrFlag[i]
263
264    return constrDict,constrFlag,fixedList
265
266def GroupConstraints(constrDict):
267    """divide the constraints into groups that share no parameters.
268    Input
269       constrDict: a list of dicts defining relationships/constraints
270       (see InputParse)
271    Returns two lists of lists:
272      a list of relationship list indices for each group and
273      a list containing the parameters used in each group
274      """
275    assignedlist = [] # relationships that have been used
276    groups = [] # contains a list of grouplists
277    ParmList = []
278    for i,consi in enumerate(constrDict):
279        if i in assignedlist: continue # already in a group, skip
280        # starting a new group
281        grouplist = [i,]
282        assignedlist.append(i)
283        groupset = set(consi.keys())
284        changes = True # always loop at least once
285        while(changes): # loop until we can't find anything to add to the current group
286            changes = False # but don't loop again unless we find something
287            for j,consj in enumerate(constrDict):
288                if j in assignedlist: continue # already in a group, skip
289                if len(set(consj.keys()) & groupset) > 0: # true if this needs to be added
290                    changes = True
291                    grouplist.append(j)
292                    assignedlist.append(j)
293                    groupset = groupset | set(consj.keys())
294        group = sorted(grouplist)
295        varlist = sorted(list(groupset))
296        groups.append(group)
297        ParmList.append(varlist)
298    return groups,ParmList
299
300def GenerateConstraints(groups,parmlist,varyList,constrDict,constrFlag,fixedList):
301    '''Takes a list of relationship entries comprising a group of constraints and
302    builds the relationship lists and their inverse and stores them in global variables
303    '''
304    global dependentParmList,arrayList,invarrayList,indParmList,consNum
305    for group,varlist in zip(groups,parmlist):
306        VaryFree = False
307        for row in group:
308            if 'VaryFree' in constrFlag[row]: VaryFree = True
309        arr = MakeArray(constrDict, group, varlist)
310        constrArr = FillInMissingRelations(arr,len(group))
311        mapvar = []
312        group = group[:]
313        for i in range(len(varlist)):
314            vary = VaryFree
315            if len(group) > 0:
316                rel = group.pop(0)
317                fixedval = fixedList[rel]
318                if 'Vary' in constrFlag[rel]: vary = True
319            else:
320                fixedval = None
321            if fixedval is None:
322                varname = paramPrefix + str(consNum)
323                mapvar.append(varname)
324                consNum += 1
325                if vary: varyList.append(varname)
326            else:
327                mapvar.append(fixedval)
328        dependentParmList.append(varlist)
329        arrayList.append(constrArr)
330        invarrayList.append(np.linalg.inv(constrArr))
331        indParmList.append(mapvar)
332    # setup dictionary containing the fixed values
333    global fixedDict
334    # key is original ascii string, value is float
335    for fixedval in fixedList:
336        if fixedval:
337            fixedDict[fixedval] = float(fixedval)
338
339    if debug: # on debug, show what is parsed & generated, semi-readable
340        print 50*'-'
341        for group,varlist,multarr,inv,mapvar in zip(groups,parmlist,arrayList,invarrayList,indParmList):
342            print '\n*** relation(s) in group:',group,'\tvars in group:',varlist
343            print 'new parameters:', mapvar
344            print 'Input relationship matrix'
345            print multarr[:len(group)]
346            added = len(group) - len(varlist)
347            if added < 0:
348                print 'added relationship rows'
349                print multarr[added:]
350            print 'Inverse relationship matrix'
351            print inv
352
353def StoreEquivalence(independentVar,dependentList):
354    '''Takes a list of dependent parameter(s) and stores their
355    relationship to a single independent parameter (independentVar)
356    input:
357       independentVar -- name of parameter that will set others (may
358         be varied)
359       dependentList -- list of parameter that will set from
360         independentVar (may not be varied). Each item can be a parameter
361         name or a tuple containing a name and multiplier:
362         ('parm1',('parm2',.5),)
363    '''
364   
365    global dependentParmList,arrayList,invarrayList,indParmList
366    mapList = []
367    multlist = []
368    for var in dependentList:
369        if isinstance(var, basestring):
370            mult = 1.0
371        elif len(var) == 2:
372            var,mult = var
373        else:
374            raise Exception, "Cannot parse "+repr(var) + " as var or (var,multiplier)"
375        mapList.append(var)
376        multlist.append(tuple((mult,)))
377    # added relationships to stored values
378    arrayList.append(None)
379    invarrayList.append(np.array(multlist))
380    indParmList.append(tuple((independentVar,)))
381    dependentParmList.append(mapList)
382    return
383
384def VarRemapShow(varyList):
385    '''List out the saved relationships.
386    Returns a string containing the details.
387    '''
388    s = 'Mapping relations:\n'
389    global dependentParmList,arrayList,invarrayList,indParmList,fixedDict
390    for varlist,mapvars,multarr in zip(dependentParmList,indParmList,arrayList):
391        i = 0
392        for mv in mapvars:
393            if multarr is None:
394                s += '  ' + str(mv) + ' defines parameter(s): '
395                j = 0
396                for v in varlist:
397                    if j > 0: s += '  & '
398                    j += 1
399                    s += str(v)
400                s += '\n'
401                continue
402            s += %s = ' % mv
403            j = 0
404            for m,v in zip(multarr[i,:],varlist):
405                if m == 0: continue
406                if j > 0: s += ' + '
407                j += 1
408                s += '(%s * %s)' % (m,v)
409            if mv in varyList: s += ' VARY'
410            s += '\n'
411            i += 1
412    s += 'Inverse mapping relations:\n'
413    for varlist,mapvars,invmultarr in zip(dependentParmList,indParmList,invarrayList):
414        i = 0
415        for mv in varlist:
416            s += %s = ' % mv
417            j = 0
418            for m,v in zip(invmultarr[i,:],mapvars):
419                if m == 0: continue
420                if j > 0: s += ' + '
421                j += 1
422                s += '(%s * %s)' % (m,v)
423            s += '\n'
424            i += 1
425    return s
426
427def Map2Dict(parmDict,varyList):
428    '''Create (or update) the Independent Parameters from the original
429    set of Parameters
430
431    This should be done once, before any variable refinement is done
432    to complete the parameter dictionary with the Independent Parameters
433    '''
434    global dependentParmList,arrayList,invarrayList,indParmList,fixedDict
435    for varlist,mapvars,multarr in zip(dependentParmList,indParmList,arrayList):
436        for item in varlist:
437            try:
438                varyList.remove(item)
439            except ValueError:
440                pass
441        if multarr is None: continue
442        valuelist = [parmDict[var] for var in varlist]
443        parmDict.update(zip(mapvars,
444                            np.dot(multarr,np.array(valuelist)))
445                        )
446    # overwrite dict with constraints - why not parmDict.update(fixDict)?
447    parmDict.update(fixedDict)
448
449def Dict2Map(parmDict,varyList):
450    #I think this needs fixing to update parmDict with new values
451    #   from the constraints based on what is in varyList - RVD
452    '''Convert the remapped values back to the original parameters
453   
454    This should be done to apply constraints to parameter values (use
455    Map2Dict first). It should be done as part of the Model function
456    evaluation, before any computation is done
457    '''
458    global dependentParmList,arrayList,invarrayList,indParmList,fixedDict
459    # reset fixed values (should not be needed, but very quick)
460    # - this seems to update parmDict with {'0':0.0} & {'1.0':1.0} - probably not what was intended
461    parmDict.update(fixedDict)
462    for varlist,mapvars,invmultarr in zip(dependentParmList,indParmList,invarrayList):
463        if invmultarr is None: continue
464        valuelist = [parmDict[var] for var in mapvars]
465        parmDict.update(zip(varlist,
466                            np.dot(invmultarr,np.array(valuelist)))
467                        )
468
469#======================================================================
470# internal routines follow (these routines are unlikely to be called
471# from outside the module)
472def FillInMissingRelations(arrayin,nvars):
473    '''Fill in unspecified rows in array with non-colinear unit vectors
474    arrayin is a square array, where only the first nvars rows are defined.
475   
476    Returns a new array where all rows are defined
477
478    Throws an exception if there is no non-signular result
479    (likely because two or more input rows are co-linear)
480    '''
481    a = arrayin.copy()
482    n = nvars
483    # fill in the matrix with basis vectors not colinear with any of the starting set
484    for i in range(n,len(a)):
485        try:
486            a[n] = VectorProduct(a[:n])
487        except:
488            raise Exception,"VectorProduct failed, singular input?"
489        n += 1
490    # use the G-S algorithm to compute a complete set of unit vectors orthogonal
491    # to the first in array
492    gs = GramSchmidtOrtho(a) 
493    n = nvars
494    # now replace the created vectors with the ones least correlated to the
495    # initial set
496    vlist = [v for v in gs[1:]] # drop the first row
497    for j in range(n,len(a)):
498        minavg = None
499        droplist = []
500        for k in range(len(vlist)):
501            v = vlist[k]
502            avgcor = 0
503            for i in range(n):
504                cor = np.dot(a[i],vlist[k])/(np.linalg.norm(a[i]) * np.linalg.norm(vlist[k]) )
505                if np.allclose(cor, 1.0):
506                    droplist.append(k) # found a vector co-linear to one we already have
507                                       # don't need it again
508                    #vlist.pop(k)
509                    break 
510                avgcor += cor
511            else:
512                if minavg == None:
513                    minavg = abs(avgcor/n)
514                    minnum = k
515                elif abs(avgcor/n) < minavg:
516                    minavg = abs(avgcor/n)
517                    minnum = k
518        if minavg == None:
519            raise Exception,"Failed to find a non-colinear G-S vector for row %d. Should not happen!" % n
520        a[j] = vlist[minnum]
521        droplist.append(minnum) # don't need to use this vector again
522        for i in sorted(droplist,reverse=True):
523            vlist.pop(i) 
524        n += 1
525    return a
526
527
528def MakeArray(constrDict, group, varlist):
529    """Convert the multipliers in a constraint group to an array of
530    coefficients and place in a square numpy array, adding empty rows as
531    needed.
532
533    Throws an exception if some sanity checks fail.
534    """
535    # do some error checks
536    if len(varlist) < len(group): # too many relationships -- no can do
537        raise Exception,'The number of relationships (%d) exceeds the number of parameters (%d):\n\t%s\n\t%s'% (
538            len(group),len(varlist),group,varlist)
539    if len(varlist) == 1: # one to one mapping -- something is probably wrong
540        raise Exception,'Why remap a single parameter? (%s)'% (varlist[0])
541    # put the coefficients into an array
542    multarr = np.zeros(2*[len(varlist),])
543    i = 0
544    for cnum in group:
545        cdict = constrDict[cnum]
546        j = 0
547        for var in varlist:
548            m = cdict.get(var)
549            if m != None:
550                multarr[i,j] = m
551            j += 1
552        i += 1
553    return multarr
554
555def GramSchmidtOrtho(arrayin):
556    '''Use the Gram-Schmidt process (http://en.wikipedia.org/wiki/Gram-Schmidt) to
557    find orthonormal unit vectors relative to first row.
558    input:
559       arrayin: a 2-D non-signular square array
560    returns:
561       a orthonormal set of unit vectors as a square array
562    '''
563    def proj(a,b):
564        'Projection operator'
565        return a*(np.dot(a,b)/np.dot(a,a))
566    a = arrayin.copy()
567    for j in range (len(a)):
568        for i in range(j):
569            a[j] = a[j] - proj(a[i],a[j])
570        if np.allclose(np.linalg.norm(a[j]),0.0):
571            raise Exception,"Singular input to GramSchmidtOrtho"
572        a[j] = a[j]/np.linalg.norm(a[j])
573    return a
574
575def VectorProduct(vl):
576    '''Evaluate the n-dimensional "cross" product of the list of vectors in vl
577    vl can be any length. The length of each vector is arbitrary, but
578    all must be the same length. See http://en.wikipedia.org/wiki/Levi-Civita_symbol
579
580    This appears to return a vector perpendicular to the supplied set.
581
582    Throws an exception if a vector can not be obtained because the input set of
583    vectors is already complete or contains any redundancies.
584   
585    Uses LeviCitvitaMult recursively to obtain all permutations of vector elements
586    '''
587    i = 0
588    newvec = []
589    for e in vl[0]:
590        i += 1
591        tl = [([i,],1),]
592        seq = LeviCitvitaMult(tl ,vl)
593        tsum = 0
594        for terms,prod in seq:
595            tsum += EvalLCterm(terms) * prod
596        newvec.append(tsum)
597    if np.allclose(newvec,0.0):
598        raise Exception,"VectorProduct failed, singular or already complete input"
599    return newvec
600
601def LeviCitvitaMult(tin,vl):
602    '''Recursion formula to compute all permutations of vector element products
603    The first term in each list is the indices of the Levi-Civita symbol, note
604    that if an index is repeated, the value is zero, so the element is not included.
605    The second term is the product of the vector elements
606    '''
607    v = vl[0]
608    vl1 = vl[1:]       
609
610    j = 0
611    tl = []
612    for e in vl[0]:
613        j += 1
614        for ind,vals in tin:
615            if j in ind: continue
616            tl.append((ind+[j,],vals*e))
617    if len(vl1):
618        return LeviCitvitaMult(tl,vl1)
619    else:
620        return tl
621
622def EvalLCterm(term):
623    '''Evaluate the Levi-Civita symbol Epsilon(i,j,k,...)'''
624    p = 1
625    for i in range(len(term)):
626        for j in range(i+1,len(term)):
627            p *= (term[j] - term[i])
628            if p == 0: return 0
629    return p/abs(p)
630
631
632if __name__ == "__main__":
633    import sys
634    #remap = MapParameters() # create an object (perhaps better as a module)
635    #remap.debug = 1
636    #debug = 1
637    parmdict = {}
638    StoreEquivalence('2::atomx:3',('2::atomy:3', ('2::atomz:3',2,), ))
639    print VarRemapShow()
640
641    parmdict = {
642        '2::atomx:3':.1 ,
643        '2::atomy:3':.2 , # conflicts with constraint
644        '2::atomz:3':.3 ,
645    }
646
647    mapList = [
648        "1*p1 + 2e0*p2 - 1.0*p3",
649        "1*p4 + 1*p7",
650        "1*p1+2*p2-3.0*p2 VARY",
651        "1*p21 + 0*p22 - 0*p23 + 0*p24 varyfree",
652        "1*p5 + 2*p6 = 1 varyfree",
653        "-1 * p6 + 1*p5",
654        "-10e-1 * p1 - -2*p2 + 3.0*p4",
655        ]
656    constrDict,constrFlag,fixedList = InputParse(mapList)
657    print constrDict
658    print constrFlag
659    print fixedList
660    groups,parmlist = GroupConstraints(constrDict)
661    GenerateConstraints(groups,parmlist,constrDict,constrFlag,fixedList)
662    print VarRemapShow()
663    parmdict.update( {'p1':1,'p2':2,'p3':3,'p4':4,
664                      'p6':6,'p5':5,  # conflicts with constraint
665                      'p7':7,
666                      "p21":.1,"p22":.2,"p23":.3,"p24":.4,
667                      })
668    #print 'parmdict start',parmdict
669    before = parmdict.copy()
670    Map2Dict(parmdict,[])
671    print 'parmdict before and after Map2Dict'
672    print '  key / before / after'
673    for key in sorted(parmdict.keys()):
674        print '  '+key,'\t',before.get(key),'\t',parmdict[key]
675
676    before = parmdict.copy()
677    Dict2Map(parmdict,[])
678    print 'after Dict2Map'
679    print '  key / before / after'
680    for key in sorted(parmdict.keys()):
681        print '  '+key,'\t',before.get(key),'\t',parmdict[key]
Note: See TracBrowser for help on using the repository browser.