CpxObjective for general expressions: Exception Cplex with solve quadratic model - java

I am trying to minimize the function a quadratic function sum(sum (w*a)-v)^2
being "a" square array and "w" and "v" two vectors. "a" and "v" are known, "w" is unknown. I am using CPLEX in Java
double [][] input = {{1,2},{3,4}};
double[] result = {3,2};
//define new model
IloCplex cplex = new IloCplex();
// variables
IloNumVar[] w = new IloNumVar[input[0].length];
for (int i = 0; i < w.length; i++) {
w[i] = cplex.numVar(0.0, 1.0, IloNumVarType.Float);
}
IloNumExpr value = cplex.numExpr();
IloNumExpr objective = cplex.numExpr();
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result.length; j++) {
value = cplex.sum(value, cplex.prod(input[i][j], w[i]));
}
value = cplex.diff(value, result[i]);
value = cplex.square(value);
objective = cplex.sum(objective, value);
}
but I got this exception which I do not understand:
Exception in thread "main" java.lang.UnsupportedOperationException: CpxObjective for general expressions
at ilog.cplex.CpxObjective.setExpr(CpxObjective.java:102)
at ilog.cplex.CpxObjective.<init>(CpxObjective.java:357)
at ilog.cplex.IloCplexModeler.objective(IloCplexModeler.java:796)
at ilog.cplex.IloCplexModeler.minimize(IloCplexModeler.java:714)
at ilog.cplex.IloCplexModeler.minimize(IloCplexModeler.java:810)
at Tont.main(Tont.java:55)
Thanks for helping.

As far as I can tell, your first iteration of the outer loop creates terms like w[i]^2. The second iteration of the outer loops then takes this expression and squares it. Thus creating terms like w[i]^2. This is not supported. Only exponents of 1 and 2 are supported (linear and quadratic objectives).
From what you wrote, I think you are not creating your objective right. It should look something like this (note the initialization of value moved into the loop):
for (int i = 0; i < result.length; i++) {
IloNumExpr value = cplex.numExpr();
for (int j = 0; j < result.length; j++) {
value = cplex.sum(value, cplex.prod(input[i][j], w[i]));
}
value = cplex.diff(value, result[i]);
value = cplex.square(value);
objective = cplex.sum(objective, value);
}

This is the complete code, but it is infeasible. is it because Cplex cannot solve this kind of problems?
double [][] input = {{1,2},{3,4}};
double[] result = {3,2};
// define new model
IloCplex cplex = new IloCplex();
//cplex.setParam(IloCplex.Param.RootAlgorithm, IloCplex.Algorithm.Auto);
// variables
IloNumVar[] w = cplex.numVarArray(input[0].length, 0, Float.MAX_VALUE);// new IloNumVar[input[0].length];
for (int i = 0; i < w.length; i++) {
w[i] = cplex.numVar(0.0, 1.0, IloNumVarType.Float);
}
//IloNumExpr value = cplex.numExpr();
IloNumExpr objective = cplex.numExpr();
for (int i = 0; i < result.length; i++) {
IloNumExpr value = cplex.numExpr();
for (int j = 0; j < result.length; j++) {
value = cplex.sum(value, cplex.prod(input[i][j], w[i]));
}
value = cplex.diff(value, result[i]);
value = cplex.square(value);
objective = cplex.sum(objective, value);
}
cplex.minimize(objective);
//constraints
IloLinearNumExpr weightsAdded = cplex.linearNumExpr();
for (int j = 0; j < w.length; j++) {
weightsAdded.addTerm(1, w[j]);
}
cplex.addEq(weightsAdded, 1);
for (int i = 0; i < w.length; i++) {
cplex.addGe(0, w[i]);
}
// solve model
if (cplex.solve()) {
System.out.println("obj = "+cplex.getObjValue());
}
else {
System.out.println("problem not solved");
Thank you

Related

CPLEX Java StaticLex is not applicable for (iloNumexpr, iloNumexpr)

I need to blend two objective functions f1 and f2 (see image here) where c is a continuous variable, C_{ug} is a binary variable and a,d and f are parameters. I'm using Cplex Studio IDE 22.1.0 Java in eclipse.
// create the objetive function f1
IloLinearNumExpr firstPart = cplex.linearNumExpr();
int aSum = 0;
for (int k = 0; k < inst.n + inst.m; k++) {
firstPart.addTerm(1, c[k]);
aSum += -inst.a[k];
}
firstPart.setConstant(aSum);
IloLinearNumExpr secondPart = cplex.linearNumExpr();
for (int k = 0; k < inst.n + inst.m; k++) {
// This is the equivalent to z[k] = max(c[k] - d[k], 0)
cplex.addEq(z[k], cplex.max(0, cplex.sum(c[k], -inst.d[k])));
secondPart.addTerm(inst.f[k], z[k]);
}
IloLinearNumExpr objective = cplex.linearNumExpr();
objective.add(firstPart);
objective.add(secondPart);
// create the objetive function f2
IloLinearNumExpr secobj = cplex.linearNumExpr();
for (int tt = 0; tt < inst.T; tt++) {
for (int k = 0; k < inst.q; k++) {
for (int j = 0; j < inst.B; j++) {
secobj.addTerm(1, C[j][k]);
}}}
IloCplex.staticLex(objective, secobj );
I'm getting the following error: the method staticLex(IloNumExpr, String) in the type IloCplex is not applicable for the arguments (IloLinearNumExpr, IloLinearNumExpr).
Does anyone know how I can solve this problem? Many thanks.

(Java) The type of the expression must be an array type but it resolved to Object error

The following code:
// Adds game button container
Object[][] gameButtons = new Object[3][3];
// Adds game buttons to game button container
Arrays.fill(gameButtons, new JButton[3][3]);
for (int i = 0; i < gameButtons.length; i++) {
for (int j = 0; j < gameButtons[i].length; j++) {
for (int k = 0; k < 3; k++) {
for (int l = 0; l < 3; l++) {
gameButtons[i][j][k][l] = new JButton();******
}
}
}
}
is throwing me an error:
The type of the expression must be an array type but it resolved to Object. How do I initialize the JButtons?
EDIT: I forgot to clarify. The error was thrown at the line ******
Note that the ****** was not in my code.
EDIT 2: I tried Logan's fix, but it still didn't work:
for (Object[] row : gameButtons)
Arrays.fill(row, new JButton[3][3]);
for (int i = 0; i < gameButtons.length; i++) {
for (int j = 0; j < gameButtons[i].length; j++) {
for (int k = 0; k < 3; k++) {
for (int l = 0; l < 3; l++) {
gameButtons[i][j][k][l] = new JButton();
}
}
}
}
Same error, same place.
gameButtons[i][j] is of type Object, which cannot be indexed as an array. You must first cast it to a JButton[][] type:
for (int i = 0; i < gameButtons.length; i++) {
for (int j = 0; j < gameButtons[i].length; j++) {
// cast it to an array type before accessing
JButton[][] subArray = (JButton[][])(gameButtons[i][j]);
for (int k = 0; k < 3; k++)
for (int l = 0; l < 3; l++)
subArray[k][l] = new JButton();
}
}
I believe you don't need a for loop. If I understand your problem correctly, you can do like this:
//create a sub array
Object[][] subArray = new Object[3][3];
// create game button container
Object[][] gameButtons = new Object[3][3];
// Adds buttons to sub array
Arrays.fill(subArray, new JButton[3][3]);
// Adds sub array to game button container
Arrays.fill(gameButtons, subArray);
The docs helped me a lot with this.
You could also use a GUI maker such as the one in NetBeans IDE it's much simpler than writing the code yourself.

Finding the mode of a 2D array

I'm trying to return the mode of a 2D array using a frequency array. I have an array, score, which is of length 10, and has 3 columns. Each column contains an int that is between 0 and 100.
I'm trying to find a way that will iterate through the array and return the modal value. What I have so far is:
int value = 0;
int[] freq = new int[100];
for (int row = 0; row < score.length; row++) {
for (int col = 0; col < score[row].length; col++) {
score[row][col] = value;
freq[value]++;
}
}
int largest = 0;
int mode = -1;
for (int i = 0; i < 100; i++) {
if (freq[i] > largest)
{
largest = freq[i];
mode = i;
}
}
System.out.println("modal score is: " +mode);
Problem is that this is just returning the modal score as 0, which it isn't.
You have a problem on generating the freq array. If I understand correctly, on the first double-for block you are trying to put the frequencies of the numbers inside the freq array.
But all you do is:
int value = 0;
.....
score[row][col] = value;
freq[value]++;`
firstly you are changing the score array,( which is a problem for you I guess...) and the you go to freq[0] and do ++. Obviously modal is 0, that number appears in all of the array.
SOLUTION: in the first double for block you should do:
value = score[row][col];
freq[value]++;
so I think you mixed up the order of the line, it should be the other way around.
private static void printMode(double[][] doubles) {
HashMap<Double , Double> map = new HashMap();
for (int i = 0; i < doubles.length; i++) {
for (int j = 0; j < doubles[i].length; j++) {
double temp = doubles[i][j];
if(map.get(temp)==null){
map.put(doubles[i][j],1.0);
}else {
double temp2 = (double) map.get(temp);
map.put(doubles[i][j],++temp2);
}
}
}
Object[] objects = map.values().stream().sorted().toArray();
Stream stream = map.entrySet().stream().filter(val-> val.getValue().equals(objects[objects.length-1]));
stream.forEach(System.out::println);
}
I think using Stream for finding mode is the best way.
use int instead of double doesn't cause any problems.
int value = 0;
int [] freq = new int [arr.length];
for (int i = 0; i < arr.length; i++){
for (int j = 0; j < arr[i].length; j++){
value = arr[i][j];
freq[value]++;
}
}
int largest = 0;
int mode = 0;
for (int i = 0; i < freq.length; i++) {
if (freq[i] > largest)
{
largest = freq[i];
mode = i;
}
}
System.out.println("modal score is: " +mode);

Initialize the Columns of an Array in Java

I have three arrays of equal lengths that I combine (as I will sort them on column c later):
double abc[][] = {
Arrays.copyOf(a, a.length),
Arrays.copyOf(b, a.length),
Arrays.copyOf(c, a.length)
};
When I call
System.out.println(Arrays.deepToString(abc));
I receieve:
[[4.0, 2.0, 1.3333333333333333, 5.0, 2.5, 1.6666666666666667 ....
However, I would prefer something like:
[[1.0, 1.0, 4.0], [2.0, 2.0, 5.0], [3.0, 3.0, 7.0]]
This is possible using double singlets
double test[][] = {{1,1,4},{2,2,5},{3,3,7}};
How can I populate/initialize three columns using three double[ ]?
EDIT:
Solution based on vojta's answer:
double abcT[][] = new double[abc[0].length][abc.length];
for (int i = 0; i < abc.length; i++) {
for (int j = 0; j < abc[0].length; j++) {
abcT[j][i] = abc[i][j];
}
}
System.out.println(Arrays.deepToString(abcT));
I think there is no one-line solution of your problem, unfortunately. You will have to use some homemade code:
static <T> T[][] createMatrix(T[]... columns) {
if (columns== null || columns.length == 0)
return new T[0][0];
int wid = columns.length;
int ht = columns[0].length;
T[][] result = new T[ht][wid];
for (int x = 0; x < wid; x++) {
for (int y = 0; y < ht; y++) {
result[y][x] = columns[x][y];
}
}
return result;
}
I hope it was useful.
I finally reached this more elegant solution:
for (int i = 0; i < a.length; i++){
abc[0][i] = a[i];
abc[1][i] = b[i];
abc[2][i] = c[i];
}
Although it is not a general solution for n[], this avoids the need to make intermediate copies of the original arrays. And then I just swap the for-loops for row and column:
for (int j = 0; j < abc[0].length; j++) {
for (int i = 0; i < abc.length; i++) {
System.out.print(abc[i][j] + " ");
}
System.out.print("\n");
}
Note: This solution does not store in the intended R:C format, but retrieves in C:R.

Iteration sum in a linkedlist in java

I have 3 linked lists, in java with this values:
LinkedList<Double> simTarget = new LinkedList<Double>();
LinkedList<Double> simSource = new LinkedList<Double>();
LinkedList<Double> results = new LinkedList<Double>();
simTarget.add(0.5);
simTarget.add(0.1);
simTarget.add(1.0);
simSource.add(0.5);
simSource.add(0.1);
simSource.add(1.0);
I need to perform an iteractive sum in these lists and the results I stored in the "results", for example:
for (int i = 0; i < simTarget.size(); i++)
{
for (int j = 0; j < simSource.size(); j++)
{
results.add((simTarget.get(i) + (simSource.get(j) * 0.5)/3));
}
}
So, this is my problem: with the linkedlist "results" is that I need to perform again a new iteration but with the same values of the simSource, like this:
for (int i = 0; i < results.size(); i++)
{
for (int j = 0; j < simSource.size(); j++)
{
System.out.println(results.get(i) + (simSource.get(j) * 0.5)/3);
}
}
this iteration need performing (itself) in "x" times, for example: 70 times or 80 times or 1000 times. And just the values of the "results" linkedlist shall increase.
How to perform and to develop this iteration by x times?
Thank you very much.
Because Double is both final and immutable, you will have to encapsulate Double in a custom class, 'Value' for example. Then, you will update the Double field in the Value class each time you do a summation. Therefore, only the object of type Value strored in results will be updated.
for(int x = 0;x< 1000;x++){
for (int i = 0; i < results.size(); i++)
{
for (int j = 0; j < simSource.size(); j++)
{
Value buffer = results.get(i);
buffer.doubleField += (simSource.get(j) * 0.5)/3;
//System.out.println(results.get(i) + (simSource.get(j) * 0.5)/3);
}
}
}
BTW, since you are accessing the LinkedList by index, it will be better to use an ArrayList instead.

Categories

Resources