Constraining an expression in LMFIT to 0 - lmfit

I am just beginning to use LMFIT on a manetostatic problem and wish to enforce that a dot product of vectors be zero. I have defined the parameters (vector components) n0_x, n0_y, n0_z, a0_x, a0_y, and a0_z and given them initial values. Then I define the parameter:
param.add('a0dotn0',expr='n0_x*a0_x+n0_y*a0_y+n0_z*a0_z')
but a0dotn0 is given the value of the dot product of the initial vectors a0 and n0. How do I enforce the constraint that a0dotn0 is always zero?

The standard recommendation is to provide a complete example to show what you are trying to do. Without that, anyone trying to help you has to guess what you're doing and might get it wrong.
If you're defining parameters with something like
params = lmfit.Parameters()
param.add('n0_x', 1.0)
param.add('n0_y', 0.9)
param.add('n0_z', 0.8)
param.add('a0_x', 0.5)
param.add('a0_y', 0.4)
param.add('a0_z', 0.6)
and want these values to be constrained such that n0_x*a0_x+n0_y*a0_y+n0_z*a0_z = 0 then the easiest way to change one of the parameters to be defined to satisfy that constraint, say by replacing that last parameter definition with
## a0_z = -(n0_x*a0_x + n0_y*a0_y)/n0_z
param.add('a0_z', expr='-(n0_x*a0_x + n0_y*a0_y)/n0_z')
You might want to ensure that n0_z cannot be zero.

Related

Is it possible to pre-assign values to decision variables in CPLEX OPL

I have a large number of variables ( both Binary and Continuous). Therefore I have determined a logic to assign some variables set to 0 so that they do not become part of the optimisation process.
For example I have a binary decision variable y[b][t]:
where b varies from 1 to 100
and t from 1 to 5.
I could determine using some logic that y[20][2] onwards to y[100][2] would be 0. I want to assign the fixed value of 0 to these variables y[20][2] onwards to y[100][2] thereby reducing the number of variables in my optimisation problem. While y is a binary decision variable I have other continuous variable as well which I would like to similarly set to 0 in advance.
Is there a way how this can be achieved ? I haven't used Python with CPEX but hear that this can be probably be achieved by setting a lower and upper bound of the variables. Is there a similar method in OPL.
----Added 13th Aug
May be I was not very clear or I could not understand the solution suggested.
What I wanted is say I have the following decision variable Xbmt ...(I have a few of them)
Originally declared as :
dvar float+ Xbmt[PitBlocks][Plants][TimePeriods];
But for some of the PitBlocks and some time periods I want to define this decision variable as 0. Those time periods for which I want to set the decision variable as 0 are defined in a tuple nullVariables. It has block id same as PitBlocks, and it has time_period same as TimePeriod. Hence I want something like below. But I cannot declare the decision variable twice. I need it 0 only for those ids in the nullVariable set.
dvar float+ Xbmt[NullVariablesSet.block_id][Plants][NullVariablesSet.time_period] in 0..0;
How can this be achieved where some of Xbmt remain as decision variables where as some are removed by setting as 0
see https://github.com/AlexFleischerParis/zooopl/blob/master/zoopreassign.mod
within
Making Decision Optimization Simple
int nbKids=300;
{int} seats={40,30}; // how many seats, {} means this is a set
float costBus[seats]=[500,400];
// Now let s see how preassign some decision variables
// Suppose we know that we have exactly 6 buses 40 seats
{int} preassignedseats={40};
int preassignedvalues[preassignedseats]=[6];
dvar int+ nbBus[s in seats]
in
((s in preassignedseats)?preassignedvalues[s]:0)
..
((s in preassignedseats)?preassignedvalues[s]:maxint);
minimize sum(b in seats) costBus[b]*nbBus[b];
subject to
{
sum(b in seats) b*nbBus[b]>=nbKids;
}

How do I set a max value for a parameter to be dependent on the value of another parameter in lmfit?

I am currently trying to estimate a Voigt profile on a measurement. I want to set an upper limit for the parameter 'amplitude', where the value of the upper limit is decided by another parameter, gamma:
Voigt_dBm = Model(V_dBm) #V_dBm is defined as a Voigt profile
params = Voigt_dBm.make_params(gamma=5, alpha=720, ...
amplitude=2e-8, offset=1e-9, max_lin=max(y_lin)) #Values for parameters are appropriate for the data
params.add('max_lin', vary=False) #This value comes from the data and should be kept static
params.add('amplitude',max=max_lin**(gamma*2)**2) <--- This is where I want to add the gamma-dependt limit
result = Voigt_dBm.fit(y,params,x=f,nan_policy='propagate')
lmfit does not allow using expressions for bounds - the bounds need to have values known before the fit begins and cannot change during the fit.
You could do something like this:
params = Voigt_dBm.make_params(gamma=5, alpha=720, offset=1e-9, ...)
params.add('max_lin', value=maxy(y_lin), vary=False)
params.add('amp_offset', value=max(y_lin)**(gamma*2)**2/4.0, min=0)
params.add('amplitude', expr='max_lin**(gamma*2)**2 - amp_offset')
This will constrain amplitude to be max_lin**(gamma*2)**2 minus some variable amount. By putting a limit on that amplitude offset that it must be positive,
the resulting amplitude cannot exceed your max_lin**(gamma*2)**2, even if gamma changes during the fit. I guessed an initial value of 1/4 of that amount, but maybe you would have a better idea of what a reasonable initial value should be.
You can put bounds on parameters constrained by a mathematical expression, so if you wanted to ensure amplitude was positive, you could add min=0 to params.add('amplitude', ....).

Eigen Matrix Smart pointer move construction

Code as below:
// Generate the returns matrix
boost::shared_ptr<Eigen::MatrixXd> returns_m = boost::make_shared<Eigen::MatrixXd>(factor_size, num_of_obs_per_simulation);
//Generate covariance matrix
boost::shared_ptr<MatrixXd> corMatrix = boost::make_shared<MatrixXd>(factor_size, factor_size);
(*corMatrix) = (*returns_m) * (*returns_m).transpose() / (num_of_obs_per_simulation - 1);
The point is that I want to return the corMatrx as a pointer, not as an object, to be stored as a member of a result class for later use. Above code seems to make a copy of the big matrix, is there any better way to do it?
Thank you and best wishes...
Slight improvement to #ggael's answer, you can directly construct your corMatrix shared pointer from the expression:
boost::shared_ptr<MatrixXd> corMatrix
= boost::make_shared<MatrixXd>((*returns_m) * (*returns_m).transpose() * (1./(num_of_obs_per_simulation - 1));
Or, you can exploit the symmetry of the product using rankUpdate:
boost::shared_ptr<MatrixXd> corMatrix = boost::make_shared<MatrixXd>(MatrixXd::Zero(factor_size, factor_size));
corMatrix->selfadjointView<Eigen::Upper>().rankUpdate(*returns_m, 1.0 / (num_of_obs_per_simulation - 1));
// optionally copy upper half to lower half as well:
corMatrix->triangularView<Eigen::StrictlyLower>() = corMatrix->adjoint();
I don't understand your question as returning corMatrix as a shared_ptr will do exactly what you want, but regarding your product, you can save one temporary using noalias and * (1./x):
(*corMatrix).noalias() = (*returns_m) * (*returns_m).transpose() * (1./(num_of_obs_per_simulation - 1));
The whole expression will be turned as a single call to a gemm-like routine.
To complete the explanation:
Recall that Eigen is an expression template library, so when you do A = 2*B + C.transpose(); with A,B,C matrices, then everything happen in operator=, that is the right-hand-side expression is directly evaluated within A. For products, the story is slightly different because 1) to be efficient it needs to be directly evaluated within something, and 2) it is not possible to directly write to the destination if there is aliasing, e.g.: A = A*B. The noalias tells Eigen that the destination does not not alias and the product can be directly evaluated within it.

Suggest an algorithm/method for finding a proper value

I have a bunch of values, for example: [1,2,14,51,100,103,107,110,300,505,1034].
And I have a pattern values, for example [1,10,20,100,500,1000].
I need to get the best 'suitable' value FROM pattern. In my example it is 100. How can I detect this value?
Example from life. The app has a bunch of distances between user position and some objects. The app also has a preset filter by distance: [1 meter, 10 meters, 20 meters, 100 meters]. I heed to set the filter by default not just to the first value (1 meter in my example), but to the value which match the bunch of distances the best way(100 meter in my example). I need to detect one value.
Thank you for help and any ideas.
I would say create a function like this (this is not real code) :
var ratio1 = 0.66
var ratio2 = 1.5
function Score(currentPatternValue, arrayOfValues)
{
count = 0
for each value in arrayOfValues <br>
if value > ratio1 * currentPatternValue AND value < ratio2 * currentPatternValue<br>
count++<br>
return count
}
then you run this for each value in your pattern values and pick the one with the highest score returned from that function

USing AddExpression / MathExpression in Weka

I am working on a very basic WEKA assignment, and I'm trying to use WEKA to preprocess data from the GUI (most current version). I am trying to do very basic if statements and mathematical statements in the expression box when double clicking on MathExpression and I haven't had any success. For example I want to do
if (a5 == 2 || a5 == 0) then y = 1; else y = 0
Many different variations of this haven't worked for me and I'm also unclear on how to refer to "y" or if it needs a reference within the line.
Another example is -abs(log(a7)–3) which I wasn't able to work out either. Any ideas about how to make these statements work?
From javadoc of MathExpression
The 'A'
letter refers to the value of the attribute being processed.
Other attribute values (numeric only) can be accessed through
the variables A1, A2, A3, ...
Your filter applies to all attributes of your dataset. If I load iris dataset and apply following filter.
weka.filters.unsupervised.attribute.MathExpression -E log(A).
your attribute ,sepallength values change as following.
Before Filter After Filter
Minimum 4.3 Minimum 1.459
Maximum 7.9 Maximum 2.067
Mean 5.843 Mean 1.755
StdDev 0.828 StdDev 0.141
Also if you look to javadoc, there is no if else function but ifelse function. Therefore you should write something like
ifelse ( (A == 2 || A == 0), 1,0 )
Also this filter applies to all attributes. If you want to change only one attribute and according to other attribute values ; then you need to use "Ignore range option" and use A1,A2 to refer to other attribute values.
if you need to add new attribute use AddExpression.
An instance filter that creates a new attribute by applying a mathematical expression to existing attributes.

Resources