How to select model constraints dynamically based on the obtained solution? - pyomo

I had a general pyomo question. In a concrete model (say) Ax = b; Cx < d; x > 0. here C is nxd (say n constraints).
Now If the solution obtained for C_n-1 is x'. Is there a way to reset the constraints to C_n or C'_n with in the same model and in the same run. i.e. I want to select the nth constraint depending on the solution of that iteration.
Is this possible? If yes could you please indicate how?

Related

Solve ILP with Branch and Bound and CPLEX C++

I want to solve an ILP using a branch and bound algorithm for a graph labelling problem. My ILP has an objective function and constraints for every possible pair of nodes from the graph. So I have n^2 / 2 possible constraints, and the constraints have following shape:
for two vertices i, j \in V(G) add the constraints:
|X_i - X_j| >= k + 1 - d(i,j)
its obvious that this isn't linear. So i want to implement my algorithm that uses binary branch and bound:
start with empty LP only with the objective function
start with empty branch tree with start node
then at every node in the branch tree, create two child nodes.
in the first child node
add the constraints X_i - X_j >= k + 1 - d(i,j)
and constraint X_i >= X_j
for the second child node
add the constraint -(X_i - X_j) >= k + 1 - d(i,j)
and the constraint X_j >= X_i
repeat this step and possibly bound, until we find best solution
If I do this branch and bound algorithm, and search for the best solution, I would get the best occupancy of which variable should be greater than which.
Then I would get a LP, with constant constraints and I would get the optimal integer solution.
My question now is, what is the best way of doing that in c++ and cplex?
Should I always create a new IloModel in CPLEX? Or can I do it all in the same IloEnv?
I know that there are built in options, to specify the branch and bound in CPLEX, but I would like to do it "manually", so I can also implement functions that selects the "best" next constraint to add.
Thank you very much in advance!
Within CPLEX you also have Constraint Programmming and with OPL for example you can directly write
forall( ordered c1, c2 in Cells: distance[c1,c2] > 0) {
forall(t1 in 1..nbTrans[c1]) {
forall(t2 in 1..nbTrans[c2] )
abs(freq[<c1,t1>] - freq[<c2,t2>]) >= distance[c1,c2];
}
}
which is part of a frequency allocation model
The same can be done in C++

If x is y then z, else x without repeating x in Google Sheets

In a cell, is it possible to do if(x=y, z, x) without having to repeat x in the value_if_false argument? Whether there is a way of using if() to make this work or another function doesn't matter, and there isn't a specific formula I'm struggling with as I come across this blocker quite often (hence posting).
To help illustrate the need, if we take x as a complex or more advanced formula, such as
ARRAYFORMULA(IF(E$6:Q$6 < EoMONTH($P$4,0), "Not Active", IF(E$6:Q$6<$Q$4 + ISBLANK($Q$4) > 0,
COUNTIF({'Data'!$B$3:$B&'Data'!$I$3:$I&'Data'!$K$3:$K},$B$4&$C9&E$6:Q$6), "Not Active")))
and I wanted to put an if statement in there that changed the result only if a condition was true, the formula would more than double in size due to having to reference x twice:
=ARRAYFORMULA(IF(IF(E$6:Q$6 < EoMONTH($P$4,0), "Not Active", IF(E$6:Q$6<$Q$4 + ISBLANK($Q$4) > 0,
COUNTIF({'Data'!$B$3:$B&'Data'!$I$3:$I&'Data'!$K$3:$K},$B$4&$C9&E$6:Q$6), "Not Active"))) = 0, "No data", IF(E$6:Q$6 < EoMONTH($P$4,0), "Not Active", IF(E$6:Q$6<$Q$4 + ISBLANK($Q$4) > 0,
COUNTIF({'Data'!$B$3:$B&'Data'!$I$3:$I&'Data'!$K$3:$K},$B$4&$C9&E$6:Q$6), "Not Active"))))
This is just an example (the code is irrelevant), I'm trying to keep my formulas neat, tidy and efficient so that handing off to others is easier. Then I'm also mindful that it is calculating the same complex formula twice, which would probably slow the spreadsheet down especially when iterated throughout a spreadsheet.
Interested to hear the community thoughts and suggestions on this, hopefully I was clear in explaining it. :)
The only simple way to achieve this would be with the use of helper columns. They don't need to be in the same sheet as your main equation, but they do need to be within that same spreadsheet as a whole (ie you could have a sheet named "calc" that's specifically used to calculate intermediate steps and set "variables" by referencing those cells).
The only other option (which gets a bit complicated) is to create a custom function within Google Apps Script. For example, if you wanted to calculate (B1*A4)/C5 in multiple places, you could create a custom function like this:
/**
* Returns a calculation using cells A4, B1, and C5.
* #return A calculation using cells A4, B1, and C5.
* #customfunction
*/
function x() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('MainSheet');
var val1 = ss.getRange('B1').getValue();
var val2 = ss.getRange('A4').getValue();
var val3 = ss.getRange('C5').getValue();
return (val1*val2)/val3;
}
Then in your sheet, you could use this within a formula like this:
=if(A1="yes", x(), "no")
This custom function could obviously be altered to fit one's needs (ex taking in arguments to define the cells that the calculations should be done on instead of hard coding them, etc).
Other than this, there is currently no way to define variables within a formula itself.
This is possible to a certain extent, using TEXT's Meta Instructions, if you're using numbers and simple math conditions.
x
y
z
output
10
10
5
10
=TEXT(A3,"[="&B3&"]0;"&C3&"")
x
y
z
output
11
10
5
5
As long as your complex formula returns a number for x(or the output can be coerced to a number), this should be possible and it avoids repetition.
I agree, I would love if there was like a DECODE or NVL type function you could use so that you didn't need to repeat the original statement multiple times.
However, in many cases, when I encounter this, I can often reference another cell. Not in the way that has been suggested already, where the formula exists in another cell, but rather that the decision to perform the formula is based on another cell.
For example, using your values, lets assume the formula ((if(x=y, z, x)) only gets calculated when column 'w' is populated. Maybe column 'w' is a key component of the formula. Then you can write the formula as: if(w="",z,x). It's not exactly the same as testing the answer to the equation first and doesn't work in all situations, but in many cases I can find another field that's of key relevance to the formula that lets me get around this.

Search similar object

Assume I have the following array of objects:
Object 0:
[0]=1.1344
[1]=2.18
...
[N]=1.86
-----------
Object 1 :
[0]=1.1231
[1]=2.16781
...
[N]=1.8765
-------------
Object 2 :
[0]=1.2311
[1]=2.14781
...
[N]=1.5465
--------
Object 17:
[0]=1.31
[1]=2.55
...
[N]=0.75
How can I compare those objects?
You can see that object 0 and object 1 are very similar but object 17 not like any of them.
I would like to have algorithm tha twill give me all the similar object in my array
You tag this question with Algorithm (and I am not expert in C++) so lets give a pseudo code.
First, you should set a threshold which define 2 var with different under that threshold as similar. Second step will be to loop over all pair of elements and check for similarity.
Consider A to be array with n objects and m to be number of fields in each object.
threshold = 0.1
for i in (0, n):
for j in (i+1,n):
flag = true;
for k in (1,m):
if (abs(A[i][k] - A[j][k]) > threshold)
flag = false // if the absolute value of the diff is above the threshold object are not similar
break // no need to continue checks
if (flag)
print: element i and j similar // and do what ever
Time complexity is O(m * n^2).
Notice that you can use the same algorithm to sort the objects array - declare compare function as the max diff between field and then sort accordingly.
Hope that helps!
Your problem essentially boils down to nearest neighbor search which is a well researched problem in data mining.
There are diffent approaches to this problem.
I would suggest to decide first what number of similar elements you want OR to set a given threshold for the similarity. Than you have to iterate through all the vectors and compute a distance function between the query vector and each vector in the database.
I would suggest you to use Euclidean distance in your case since you have real nominal data.
You can read more about the topic of nearest neighbor search and Euclidean distancehere and here. Good luck!
What you need is a classifier, for your problem there are 2 algorithms depends on what you wanted.
If you need to find which object is most similar to the choosen object-m, you can use nearest neighbor algorithm or else if you need to find similar sets of objects you can use k-means algorithm to find k sets.

Excel: Multiple IF AND OR statements to select values based on different hierarchies

I have 2 columns of data in columns AX and AY. Each value in the cell represents a categorical value, namely "Strong", "Good", "Moderate", "Weak", arranged in decreasing order of strength of evidence, i.e. Weak evidence to support... Strong evidence to support etc.
I want to create a new column that chooses the lower strength of evidence category. For e.g, if AX2 = Weak, and AY2 = Strong, AZ2 = Weak (where AZ is the new column I want the new values to fall into). Similarly, if AX3 = Good, and AY3 = Moderate, then AZ3 = "Moderate".
If there was some way for me to set a hierarchy, similar to spatial thinking concepts in GIS where the minimal value is selected, whereby the value in AZ will be the minimum value (i.e. of lower strength of evidence) between AX and AY, i.e. choosing one of the 2 cell values.
In Excel, I tried doing this using the IF, AND, OR statements, and was thinking of doing e.g. If AX = Weak and AY is any of the four, AZ = Weak. And I was thinking of repeating this for the other scenarios e.g. If AX = Moderate and AY is any of the 3 (Moderate, Good, Strong), AZ = Moderate.
(My code)
=IF(AND(AX4="Weak",OR(AY4="Weak",AY4="Moderate",AY4="Good",AY4="Strong")),"Weak"," ")
Then I realized, while currently I am attempting to fix the value for AX, while using OR functions for AY, I would have to repeat the same thing in the other direction, i.e. fix a value for AY, then using OR functions for AX, to prevent myself from excluding certain scenarios
My current code only works for creating AZ values = Weak, and when I attempted to have multiple OR functions at the start to define different scenarios, I received the error message telling me that was too many arguments.
I have come to the conclusion that the way I am attempting to perform this task is very inefficient, and would greatly value any and all advice.
Yes, often inefficient to apply Excel, designed for numbers, to text. However, possible (with 'conversion' on the fly and back again):
=CHOOSE(MAX(MATCH(AX2,{"Strong","Good","Moderate","Weak"},0),MATCH(AY2,{"Strong","Good","Moderate","Weak"},0)),"Strong","Good","Moderate","Weak")

How to check if a constraint already exists in CPLEX C++?

I have some constraints of the form Sizes[i1] + Sizes[i2] + Sizes[i3]<=1, which I add by
model.add(Sizes[i1] + Sizes[i2] + Sizes[i3]<=1)
for some specific indices i1,i2,i3. Later I want to add for all other index combinations the constraints
model.add(Sizes[k1] + Sizes[k2] + Sizes[k3]>1)
Is there some nice way to do this, e.g. to check if the constraint already exists in the model?
Maybe I can store the handle which is returned by the IloModel::add function (e.g. as an ILOExtracableArray or even IloConstraintArray?) but even then I con't know how to check if the contraint already exists.
Thank you
I don't think that there is really an easy way to get this back from a cplex model. I have previously had to do something similar in several projects, so I give my two suggestions below.
(1) If you know you always have the same number of things in each constraint, then you can create a structure to hold that information, like:
class tuple{
public int index1;
public int index2;
public int index3;
}
and then you can just create one for each constraint you add, and keep them in a list or array or similar.
(2) If you know about the possible values of the indices, then maybe you can create a hash-code or similar from the indices. If done right, this can also solve the issue of symmetry due to permuting the indices - (Sizes[a] + Sizes[b] + Sizes[c]) is the same as (Sizes[b] + Sizes[a] + Sizes[c]).
Then as above, you can keep the hash codes in a list or array for the constraints that you added.