# [Ifeffit] Re: Artemis question

Matt Newville newville at cars.uchicago.edu
Thu Jan 22 10:57:05 CST 2004

```Hi Bruce,

and restraints, but I think I'd fail the 'quiz' you gave:

> A word of caution.  Restraints can be dangerous.  Here is a quiz:  Why
> is this definition of the restraint a bad idea?
>
>       set      scale = -100
>       restrain amp   = abs(amp_guess - amp_target) * scale
>

>     guess    amp_guess  = 0.85
>     set      amp_target = 0.85
>     set      scale      = 100
>     restrain amp        = abs(amp_guess - amp_target) * scale

as a recommended way to set just such a constraint. I believe
there's no difference.  Am I missing something?

The sign of the restraint's value won't matter, and
restrain amp    = 100 * (amp_guess - amp_target)

would be equivalent to both of the above.  The restraint's value is
jsut another element of the array of 'misfit', can be negative, and
the fit will attempt to bring the restraint close to zero.

> Finally, I never actually told you how to set up a restraint that
> offers no penalty if the s02 is between 0.7 and 1.0 but to start
> applying a penalty if it drifts out of that range.  I'm leaving that
> as an exercise for the reader.  I am doing so largely because I can't
> think of the answer off the top of my head. ;-)

It's not pretty, but I think this will effectively set penalties for
going above and below some value:

guess  target   = 0.8

set    lo_val   = 0.7
set    up_val   = 1.0
set    scale    = 100.0
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 could then be used as a restraint.  Whereas contraints
give an infinite penalty for going above some value, this allows the
target value to fall outside the desired range, but gives a finite
penalty that increases linearly as with 'distance' from the desired
range. Setting just a  lower or upper bound would go like this:

lower_penalty =  max((target-lo_val), abs(target-lo_val))-(target-lo_val)
upper_penalty = -min((target-up_val),-abs(target-up_val))+(target-up_val)

To visualize this, an array of penalties can be plotted v. value
(with scale set to 1):

lo_val   = 0.7
up_val   = 1.0
target   = 0.8

# array of target values
m.vals = range(0,2,0.05)

m.lower_p =  max((m.vals-lo_val), abs(m.vals-lo_val))-(m.vals-lo_val)
m.upper_p = -min((m.vals-up_val),-abs(m.vals-up_val))+(m.vals-up_val)

m.penalty = (max((m.vals-lo_val), abs(m.vals-lo_val)) -
min((m.vals-up_val),-abs(m.vals-up_val))+
lo_val-up_val)

newplot m.vals, m.penalty, style=linespoints2
plot    m.vals, m.lower_p
plot    m.vals, m.upper_p

--Matt

```