How to access ilog decision variable from java? - java

I have a linear problem modelled in IBM ILOG CPLEX Optimization Studio, that returns correct solutions, i.e. objective values.
For simulation purposes I use an ILOG model model file and a data file that I both call from java:
IloOplFactory.setDebugMode(false);
IloOplFactory oplF = new IloOplFactory();
IloOplErrorHandler errHandler = oplF.createOplErrorHandler(System.out);
IloOplModelSource modelSource = oplF.createOplModelSource("CDA_Welfare_Examination_sparse2.mod");
IloCplex cplex = oplF.createCplex();
IloOplSettings settings = oplF.createOplSettings(errHandler);
IloOplModelDefinition def=oplF.createOplModelDefinition(modelSource,settings);
IloOplModel opl=oplF.createOplModel(def,cplex);
String inDataFile = path;
IloOplDataSource dataSource=oplF.createOplDataSource(inDataFile);
opl.addDataSource(dataSource);
opl.generate();
opl.convertAllIntVars(); // converts integer bounds into LP compatible format
if (cplex.solve()){
}
else{
System.out.println("Solution could not be achieved, probably insufficient memory or some other weird problem.");
}
Now, I would like to access the actual decision variable match[Matchable] from java.
In ILOG CPLEX Optimization Studio I use the following nomenclatura:
tuple bidAsk{
int b;
int a;
}
{bidAsk} Matchable = ...;
dvar float match[Matchable];
In Java I access the objective value in the following way (which works fine):
double sol = new Double(opl.getSolutionGetter().getObjValue());
Now, how do I access the decision variable "match"? So far I have started with
IloOplElement dVarMatch = opl.getElement("match");
but I can't seem to get any further. Help is very much appreciated! Thanks a lot!

You're on the right track. You need to get tuples which represent each valid bidAsk in Matchable, then use the tuple as an index into the decision variable object. Here's some sample code in Visual Basic (what I happen to be writing in right now, should be easy to translate to java):
' Get the tuple set named "Matchable"
Dim matchable As ITupleSet = opl.GetElement("Matchable").AsTupleSet
' Get the decision variables named "match"
Dim match As INumVarMap = opl.GetElement("match").AsNumVarMap
' Loop through each bidAsk in Matchable
For Each bidAsk As ITuple In matchable
' This is the current bidAsk's 'b' value
Dim b As Integer = bidAsk.GetIntValue("b")
' This is the current bidAsk's 'a' value
Dim a As Integer = bidAsk.GetIntValue("a")
' this is another way to get bidAsk.b and bidAsk.a
b = bidAsk.GetIntValue(0)
a = bidAsk.GetIntValue(1)
' This is the decision variable object for match[<b,a>]
Dim this_variable As INumVar = match.Get(bidAsk)
' This is the value of that decision variable in the current solution
Dim val As Double = opl.Cplex.GetValue(this_variable)
Next

You can get the variable values through the IloCplex-Object like that:
cplex.getValue([variable reference]);
I never imported a model like that. When you create the model in java, references to the decision variables are easily at hand, but there should be a way to obtain the variables. You could check the documentation:
cplex docu

Related

How to access the final simplex tableau in CPLEX?

I'm solving a LP with CPLEX using the Java API. I build my model with the methods provided (like cplex.numVar(col, lb, ub) and cplex.addLe()) After optimization is done, I'm interested in reading the simplex tableau of the final iteration (to be precise: not only the duals and reduced costs but also the coefficients inside the tableau).
I tried to access the IloLPMatrix object cplex.LPMatrix(), but this only returns an empty matrix. I'm interested in the "filled" matrix associated to the problem I just solved.
So, how can I read the simplex tableau?
The short answer is that you cannot access the simplex tableau with the Concert (Java/.NET/C++) APIs. You can access this advanced feature with the C Callable Library and Python APIs, though. For example, see CPXXbinvarow and examining the simplex tableau in the Python API.
Now, to clear up your possible confusion with what IloLPMatrix does, consider the following (mostly cribbed from this thread on the official IBM developerWorks forum).
If you add constraints to the model with cplex.addLe() then you can use rangeIterator to access them (and possibly conversionIterator, SOS1Iterator, SO2Iterator). Note that when you use rangeIterator you have to figure out the runtime type of an expression before you can get at the coefficients. For example:
for (Iterator it = cplex.rangeIterator(); it.hasNext(); /* nothing */) {
IloRange range = (IloRange)it.next();
IloNumExpr expr = range.getExpr(); // Cannot get the coefficients of expr directly :-(
if (expr instanceof IloLinearNumExpr) {
IloLinearNumExpr linExpr = (IloLinearNumExpr)expr;
for (IloLinearNumExprIterator jt = linExpr.linearIterator(); jt.hasNext(); /* nothing */) {
IloNumVar var = jt.nextNumVar();
double coef = jt.getValue();
...
}
}
else if (expr instance of ...) {
...
}
}
On the other hand, if you build your model with an IloLPMatrix, then you can access it with LPMatrixIterator. When you call cplex.LPMatrix it "Creates and returns an empty LP matrix object." You then have to fill it and add it to the model. Alternately, you can use addLPMatrix to create and add it in one step (you still need to populate it).
For example:
// Create a matrix in which we setup the model.
IloLPMatrix matrix = cplex.LPMatrix();
// Create variables.
IloNumVar x = cplex.numVar();
IloNumVar y = cplex.numVar();
matrix.addCols(new IloNumVar[]{ x, y });
// Create constraint x + y <= 2.
IloLinearNumExpr lhs = cplex.linearNumExpr();
lhs.addTerm(x, 1.0);
lhs.addTerm(y, 1.0);
matrix.addRow(cplex.le(lhs, 2.0));
// When all constraints are setup add the matrix to the model.
cplex.add(matrix);
Note that you can only add linear constraints when using an IloLPMatrix.
Whether you use the first method to build your model and rangeIterator to access it, or the second method and LPMatrixIterator, is a matter of taste and possibly some performance trade-offs; you'd have to experiment with both approaches.
In CPLEX_Studio128\cplex\examples\src\java you could have a look at the example LPex1.java.

Accessing a random number string in different classes

I am having a problem with what should be an extremely easy task. I have a very large program that stretches across 10-15 classes. The entire program centers around a Buffered Reader/Writer with a GUI. The users input determines how a file is read and then converted.
Anyway, currently I set the file location with this line.
bw = new BufferedWriter(new FileWriter(NachaMain.saveFile.getSelectedFile()+"\\NachaOutput.ACH"));
As you can see I used a constant file name. Some of the data analysts have asked me to make the name dynamic, so I am trying to add a random number. This is how I added the random number:
int newNum = 1 + (int)(Math.random() * ((99 - 1) + 1));
String randomNumber = Integer.toString(newNum);
String location = "//"+randomNumber+"NachaOutput.ACH";
bw = new BufferedWriter(new FileWriter(NachaMain.saveFile.getSelectedFile()+location));
So far so good. When I test the "location" string at this stage it works perfectly. The problem lies in that I must call this file again for buffered readers in two different classes. I have a "FileValidation" class that takes the completed buffered writer file and analyzes it for errors. I attempted to call this "location" variable by making it static like this:
public static String location;
I attempt to call it in the validation class like this:
br = new BufferedReader(new FileReader(NachaMain.saveFile.getSelectedFile()+MainWriter.location));
The file location and everything is correct the problem is that in testing the "location" variable comes up null.
I do not understand this. I set the variable as a static in my "NachaMain" class and then changed it using a random number. Why then is the other class coming up null even though it's accessing a static variable that has already been changed?
If anyone has a solution I would appreciate it. Sorry I can't post more code but I can't see an easy way to isolate this code and there is too much to post my entire program.
Duplicate Notes: This question has been flagged as a duplicate. However the duplicate question was simply describing how to initialize a variable and my answer was much simpler, the problem with naming a variable with it's type declaration twice. I did not find a solution in that post however I got my answer here.
First off - your random looks strange:
// Last I checked, 99-1 + 1 was 99 ;-)
int newNum = 1 + (int)(Math.random() * ((99 - 1) + 1));
String randomNumber = Integer.toString(newNum);
Why not simply
String randomNumber = Integer.toString(new Random().nextInt(100)+1);
But then to your main problem:
String location = "//"+randomNumber+"NachaOutput.ACH";
That's an assignment to a local variable not to a static instance variable
Change it to
location = "//"+randomNumber+"NachaOutput.ACH";
this way, it accesses to static member of the same name. And you have to would have to make sure that location does not change "suddenly". Maybe once per program run is enough? Then add a nullcheck:
if(null == location) {
location = "//"+randomNumber+"NachaOutput.ACH";
}
Advice on things not asked
If I told a developer to make the name "dynamic", I'd expect a program, where I could somehow define the name that's stored.
Ways to do that (some, not all)
Use a System.property for the filename with default
if(null == location) {
location = "//"+System.getProperty("nacha.file", "NachaOutput.ACH");
}
Use a setting that can be changed in the UI. Like a menu "Settings". And then persist choice made in a Preferences
You are trying to assign a value to the static field location by declaring its type:
String location = "//"+randomNumber+"NachaOutput.ACH";
This is likely within a method, and likely gives the location variable method-scope.
In turn, your static String location is never assigned, thus it's null (default String value).
Just remove the type String before declaration, to assign your static field instead.
Unrelated, but worth noting...
The idiom:
int newNum = 1 + (int)(Math.random() * ((99 - 1) + 1));
... only generates pseudo-randoms, and doesn't leverage java.util.Random#next....
I would look into the java.util.UUID.randomUUID() idiom, or java.util.Random#next... just in case.

Evaluating trigonometric expressions in Java

How to insert a trigonometric function in the console for further work with it?? For example, sin(x) = 2x + 3log (y) or something like this.I think.. I need to enter an expression as a string, and then it is processed as. But how?
Take a look at exp4j
We have used this library extensively in one of our projects for solving the exact same problem that you are facing.
Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
.variables("x", "y")
.build()
.setVariable("x", 2.3)
.setVariable("y", 3.14);
double result = e.evaluate();
In your particular case, you can ask the user for the following inputs in the console and build your expression using these inputs :
Enter the expression to evaluate. This will become the argument to the ExpressionBuilder constructor.
Enter the Strings that represent the variables in the expression. This will become the input to the variables method. You can add these Strings as keys to a Map which can be used in the next step.
Enter the value of each variable. This will become the input to the setVariable methods. You could collect all the variable values as values in the Map created in the above step. You can iterate over the map and call setVariable(key,value) so that you don't need to know how many variables are present in an expression before hand.
Try exp4j. Example(from the link):
Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
.variables("x", "y")
.build()
.setVariable("x", 2.3)
.setVariable("y", 3.14);
double result = e.evaluate();
Another option is Javaluator. See the link for example.
And there's EvalX. See below example(from the link):
Expression expression = new Expression("1+1/3");
result = expression.eval():
expression.setPrecision(2);
result = expression.eval():
I hope this helps!
Just an addition, I recently found out you can separate exp4j ExpressionBuilder into two parts and add values to the variables in a for loop, you can find may examples at this website https://github.com/fasseg/exp4j/blob/master/src/test/java/net/objecthunter/exp4j/ExpressionBuilderTest.java
ExpressionBuilder e = new ExpressionBuilder("x^2")
.variable("x")
.build();
for(int i = 0; i < 10; i++) {
e.setVariable("x", i);
System.out.println("x^2 = " + e.evaluate());
}

Java to php, Byte, Type, Array

Here is a small Java Code Snippet.
ConfigData[] cd = new ConfigData[1];
cd[0] = new ConfigData();
byte[] tmpbyte ={1,(byte)0x01};
cd[0].settmpdata(tmpbyte);
"ConfigData" is my custom Type (int, Byte Array).
In my last thread i found the tip how to Build / work with a "ByteArray" in php.
But this seems to be a question of the structure of those objects / array.
So..
How can i depict that in PHP.
I hope that this can make some guidelines for you, in the terms of what you can do in PHP, and in a relation to your code snippet (the code is tested):
<?php
// define class
class ConfigData
{
var $intVal;
var $tmpData;
}
$cData = new ConfigData(); // new ConfigData instance
$array[0] = $cData; // put it in a single element array
$array[0]->intVal = 5; // assign an integer to intVal
$array[0]->tmpData = array(1, 1, 2); // assign an array of whatever to tmpData
foreach($array[0]->tmpData as $val) // iterate through assigned array
echo $val." "; // print array item (and append " " )
?>
Now, you might also want to check how byte manipulation in PHP is achieved. I suggest you to do a little Google search, and maybe check the official manual. You question was not specific enough, so I can't say more.

Python to Java translation

i get quite short code of algorithm in python, but i need to translate it to Java. I didnt find any program to do that, so i will really appreciate to help translating it.
I learned python a very little to know the idea how algorithm work.
The biggest problem is because in python all is object and some things are made really very confuzing like
sum(self.flow[(source, vertex)] for vertex, capacity in self.get_edges(source))
and "self.adj" is like hashmap with multiple values which i have no idea how to put all together. Is any better collection for this code in java?
code is:
class FlowNetwork(object):
def __init__(self):
self.adj, self.flow, = {},{}
def add_vertex(self, vertex):
self.adj[vertex] = []
def get_edges(self, v):
return self.adj[v]
def add_edge(self, u,v,w=0):
self.adj[u].append((v,w))
self.adj[v].append((u,0))
self.flow[(u,v)] = self.flow[(v,u)] = 0
def find_path(self, source, sink, path):
if source == sink:
return path
for vertex, capacity in self.get_edges(source):
residual = capacity - self.flow[(source,vertex)]
edge = (source,vertex,residual)
if residual > 0 and not edge in path:
result = self.find_path(vertex, sink, path + [edge])
if result != None:
return result
def max_flow(self, source, sink):
path = self.find_path(source, sink, [])
while path != None:
flow = min(r for u,v,r in path)
for u,v,_ in path:
self.flow[(u,v)] += flow
self.flow[(v,u)] -= flow
path = self.find_path(source, sink, [])
return sum(self.flow[(source, vertex)] for vertex, capacity in self.get_edges(source))
g = FlowNetwork()
map(g.add_vertex, ['s','o','p','q','r','t'])
g.add_edge('s','o',3)
g.add_edge('s','p',3)
g.add_edge('o','p',2)
g.add_edge('o','q',3)
g.add_edge('p','r',2)
g.add_edge('r','t',3)
g.add_edge('q','r',4)
g.add_edge('q','t',2)
print g.max_flow('s','t')
result of this example is "5".
algorithm find max flow in graph(linked list or whatever) from source vertex "s" to destination "t".
Many thanks for any idea
Java doesn't have anything like Python's comprehension syntax. You'll have to replace it with code that loops over the list and aggregates the value of sum as it goes.
Also, self.flow looks like a dictionary indexed by pairs. The only way to match this, AFAIK, is to create a class with two fields that implements hashCode and equals to use as a key for a HashMap.

Categories

Resources