[Ifeffit] Hard restraints?
Scott Calvin
SCalvin at slc.edu
Wed Feb 9 11:53:28 CST 2005
Hi Matt,
>
>In a simplified case, you'd like to constrain two coordination
>numbers to be positive _and_ to add up to some value, right?
> guess n1_var = 5
> def n1 = abs(n1_var)
> def n2 = 12 - n1
>
>or, if you're worried about n1 > 12, n2<0, you could do:
> guess n1_var = 5
> def n1 = max(0,min(n1_var,12))
> def n2 = 12 - n1
>
>Is that good enough, or am I not seeing the whole complicated
>picture?
That's a very good (less complicated) example of what I'm thinking
of. In the example you just gave, you have to guarantee that n2 is
positive by putting limits on n1. Suppose we make it just slightly
more complicated, with three coordination numbers that have to be
positive and add up to some value. I guess it could be done this way:
guess n1_var = 5
def n1 = max(0,min(n1_var,12))
guess n2_var = 5
def n2 = max(0,min(n2_var,12-n1))
def n3 = 12 - n1 - n2
So that strategy might work. It might get very complicated, though;
we have something like six constrained sums with variables often
appearing in more than one sum. For example, the fraction of copper
atoms in nominally copper sites appears in the sum requiring the
total amount of copper to match the stoichiometry, and in the sum
requiring the total number of atoms + vacancies in nominally copper
sites to match the number of copper sites. We'll look at it, but I
think it may be very unwieldy. Your next suggestion, though, should
do it:
>
>
>
>I think this is possible without a change to the code. You can
>add a restraint penalty when some value is outside a range
>[lo_val,hi_val]. It's a bit scary looking, but this will do it:
>
> lo_val = 0.7 ## lower bound
> up_val = 1.0 ## upper bound
> scale = 1.000 ## scale can be increased to weight this restraint
> target = 0.8 ## this could be a variable, say S02
>
> ## use penalty as a restraint in feffit()
> def penalty = (max((target-lo_val), abs(target-lo_val)) -
> min((target-up_val),-abs(target-up_val)) +
> lo_val - up_val)*scale
>
>This penalty can be used as a restraint, and will be 0 when the
>target value is between the lower and upper bound.
>
>To set a penalty only for going below the lower bound, it's just
> def penalty = max((target-lo_val),abs(target-lo_val))-(target- lo_val)
>
>and if the lower bound is 0, it's even simpler:
> def penalty = max(target,abs(target))-target
Yes! Very clever. I've used a similar strategy to implement
"if-then-else" type assignments. This seems considerably easier to
implement in complicated situations than the previous method.
>Even that is scary enough, and the whole thing may suggest a
>change to the code to make a simple function that provides a
>restraint penalty when a variable is outside some user-selected
>bounds, perhaps as
> bound(x, lo_val, hi_val) # not implemented!
>
>Is this way of setting a penalty what you had in mind, or am I
>missing the point?
Yes, that's exactly what I had in mind. I would certainly find it
very useful...this isn't the first system I've analyzed where it
would have helped, although I've usually been able to get around it
with judicious use of abs() or max/min.
I am curious if others would find this feature helpful. Now that
you've pointed out how to do the same thing with the current
restraints, I don't really need the shortcut...you've seen enough of
my fits to know I don't shy away from long expressions. :) But of
course it would make life easier.
--Scott Calvin
Sarah Lawrence College
More information about the Ifeffit
mailing list