Input/output in GLPK for Java - java

I find a lot of GLPK for Java examples about how to specify the model (problem/constraints) to the solver and read parameters from a data file, but very little about programmatic parameter input/output.
In my case I need to submit values (array of weights and values) to a knapsack problem programmatically and postprocess the solution as well (perform addtional numeric checks on the solution found) in order to decide whether to proceed or not.
Think of the equivalent of reading a param: line from a data file without calling glp_mpl_read_data or printing details of a solution to a file without calling glp_print_mip/sol/itp.
Can you provide example code or point me to the right resource?

This is only a partial answer. I managed to solve the output part using the
GLPK.get_ipt_obj_val
GLPK.get_mip_obj_val
GLPK.get_ipt_col_val
GLPK.get_mip_col_val
functions as in the following example
static void writeMipSolution(glp_prob lp) {
String name = GLPK.glp_get_obj_name(lp);
double val = GLPK.glp_mip_obj_val(lp);
System.out.println(name + " = " + val);
int n = GLPK.glp_get_num_cols(lp);
for (int i = 1; i <= n; i++) {
name = GLPK.glp_get_col_name(lp, i);
val = GLPK.glp_mip_col_val(lp, i);
System.out.println(name + " = " + val);
}
}
Still investigating the input part, though.

Related

Weka Prediction margin using Java API

Hellow everyone,
I'm using Weka Java API for predictions. I was able to get the expected and actual behavior from the java code. But now what i wanted is to get the 'prediction margin' information from final results. From GUI, i can manage, but i wanted is a Java solution. appreciate if any one can help.What i wanted to get is the below highlighted information using java.
Below code shows the code i'm using as of now to predict actual/predicted.
for (int i = 0; i < testDataSet.numInstances(); i++) {
double actualClass = testDataSet.instance(i).classValue();
String actual = testDataSet.classAttribute().value((int) actualClass);
Instance newInst = testDataSet.instance(i);
double preJ48 = tree.classifyInstance(newInst);
String predictionString = testDataSet.classAttribute().value((int) preJ48);
System.out.println("Actual : " + actual + " Prediction : " + predictionString);
}
############################# Solution i found as below ##########
J48 tree = new J48();
tree.buildClassifier(trainDataSet);
double a = eval.evaluateModelOnceAndRecordPrediction(tree, testDataSet.instance(0));
eval.evaluateModel(tree, testDataSet, plainText);
for (String line : predsBuffer.toString().split("\n")) {
String[] linesplit = line.split("\\s+");
// If there's an error(error flag "+"), the length of linesplit is 6, otherwise 5
System.out.println("linesplit "+linesplit.length);
int id;
String expectedValue, classification;
double probability;
if (line.contains("+")) {
probability = Double.parseDouble(linesplit[5]);
System.out.println("Its Minus "+probability);
} else {
probability = Double.parseDouble(linesplit[4]);
System.out.println("Its Plus "+probability);
}
}
The prediction margin that you are referring to gets generated by the weka.gui.explorer.ClassifierErrorsPlotInstances class. Check the variables probActual and probNext in its process method.
This margin is simply the difference between the probability for the actual class label and the highest probability of the label that isn't the actual class label.
You can use the distributionForInstance method of your classifier to obtain the class distribution array and then determine these two probabilities to calculate the margin for the prediction.

Expand the range of numbers

I was trying a solve a issue which is bothering me for a while. I created a small parser that reads an .ini file and then stores the data in an ArrayList. However, I got stuck with the following snippet:
while (!(sCurrentLine.equals("[End]"))) {
formats.add(sCurrentLine);
for (int i = 0; formats.size() > 0; i++) {
}
sCurrentLine = br.readLine();
}
Now this is the place where I have to add values into formats, which is of type ArrayList.
The values that will be added like this:
0900.013-017=LABEL
0900.018-029=LABEL
Now the range is in between and I also have to make sure that '0900' and '=label' repeats themselves along with the expansion of numbers, for example:
0900.013=LABEL
0900.014=LABEL
0900.015=LABEL
0900.016=LABEL and so on...
and store it back in the ArrayList.
I don't want to depend upon third-party libraries. Please help me out with this.
Use a regular expression to parse the range, then loop over the parsed values. There is some fine tuning to be done but I think this should get you started.
Pattern rangePattern = Pattern.compile("([0-9]+)\\.([0-9]+)-([0-9]+)=(.*)$");
Matcher rangeMatcher = rangePattern.matcher("0900.13-17=First label");
if (rangeMatcher.matches()) {
String prefix = rangeMatcher.group(1);
int start = Integer.parseInt(rangeMatcher.group(2));
int end = Integer.parseInt(rangeMatcher.group(3));
String label = rangeMatcher.group(4);
for (int r = start; r < end; r++) {
System.out.println(prefix + "." + r + "=" + label);
}
}
Create the pattern once and then just get new matchers each time through your loop.
The results:
0900.13=First label
0900.14=First label
0900.15=First label
0900.16=First label

RasEnumConnections function in JNA is returning incomplete data. What I am doing wrong?

RasEnumConnections function which realized in JNA is returning incomplete data.
What wrong? This is my code:
public static void main(String[] args) {
Connected();
}
private static void Connected () {
boolean state = false;
ArrayList<String> connectedNames = new ArrayList<>();
IntByReference lpcb = new IntByReference(0);
IntByReference lpcConnections = new IntByReference(0);
Rasapi32.INSTANCE.RasEnumConnections(null, lpcb,lpcConnections);
WinRas.RASCONN conn = new WinRas.RASCONN();
conn.dwSize = lpcb.getValue();
WinRas.RASCONN[] connArray;
if(lpcConnections.getValue() > 0)
connArray = (WinRas.RASCONN[])conn.toArray(lpcConnections.getValue());
else
connArray = (WinRas.RASCONN[])conn.toArray(1);
System.out.println("lpcb: " + lpcb.getValue() + " lpcConnections: " + lpcConnections.getValue() + " RASCONN Size: " + conn.dwSize);
int error = Rasapi32.INSTANCE.RasEnumConnections(connArray, lpcb,lpcConnections);
if(error == WinError.ERROR_SUCCESS) {
System.out.println("Entry name: " + Native.toString(connArray[0].szEntryName)
+ " Guid string: " + connArray[0].guidEntry.toGuidString());
System.out.println(connArray[0].guidEntry.Data1);
System.out.println(connArray[0].guidEntry.Data2);
System.out.println(connArray[0].guidEntry.Data3);
}
else System.out.println("Error: " + error);
WinRas.RASENTRY.ByReference entry = getPhoneBookEntry("test1");
if(entry != null) {
System.out.println("test1 guid: "+ entry.guidId.toGuidString());
System.out.println(entry.guidId.Data1);
System.out.println(entry.guidId.Data2);
System.out.println(entry.guidId.Data3);
}
else System.out.println("Error: " + Native.getLastError());
}
}
Char array szEntryName contains only 3 last chars of connection name. (Connection name is "test1")
As I've noted in the comments, the debug output gives you a strong hint at what's happening. The missing "t" and "e" characters appear as 0x74 and 0x65 in the midst of what JNA expects to be a 64-bit pointer. The logical conclusion is that Windows is returning a 32-bit pointer followed by the string, 4 bytes earlier than JNA expected.
RasEnumConnections states a few things regarding the buffer you are passing as connArray:
On input, an application must set the dwSize member of the first
RASCONN structure in the buffer to sizeof(RASCONN) in order to
identify the version of the structure being passed.
In your sample code above you are leaving this value the same as the value from the initial return. This is specifying the "wrong" version of the structure. Instead, you should set the dwSize member to the size you want in your JNA structure:
conn.dwSize = conn.size();
Actually, the constructor for RASCONN sets this for you! So you actually don't have to do this. But in your code sample above, you are overwriting what was pre-set; just delete your conn.dwSize line.
Note that since you are now requesting a (4-bytes per array element) larger buffer by definining the structure size, you also need to pass the increased size in the (second) RasEnumConnections() call. It's set as the number of elements times the (smaller) structure size, but you should reset to the number of elements times the (larger) size like this:
lpcb.setValue(conn.size() * lpcConnections.getValue());
prior to fetching the full array. Otherwise you'll get the error 632 (Incorrect Structure Size).
For reference (or perhaps a suitable replacement for your own code), take a look at the code as implemented in the getRasConnection(String connName) method in JNA's Rasapi32Util.java class.

adding and subtracting for BODMAS system

I have been building a simple formula calculator and have gotten stuck with addition and subtraction. As you should know, when calculating an equation, you follow the arithmetic rules of precedence, i.e. brackets, order: power functions, division, multiplication, addition and subtraction. The problem is that addition and subtraction are given equal priority, so therefore you can read it from left to right. Here is my code so far:
{
ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
while(equation.contains("+")){
addMe(equation);
}
while(equation.contains("-")){
minusMe(equation);
}
}
public static void addMe(ArrayList<String> numberList){
for (int i = 0, n = numberList.size(); i < n; i++) {
String value = (String) numberList.get(i);
if(value.equals("+")){
String wordBefore = (String) numberList.get(i-1);
String wordAfter = (String) numberList.get(i+1);
System.out.println("This is the word before " + wordBefore);
System.out.println("This is the word after " + wordAfter);
double doubleFromBefore = Double.parseDouble(wordBefore);
double doubleFromAfter = Double.parseDouble(wordAfter);
double answer = doubleFromBefore + doubleFromAfter;
System.out.println("This is the answer: " + answer);
String stringAnswer = String.valueOf(answer);
String newNum2 = value.replace(value, stringAnswer);
numberList.set(i,newNum2);
numberList.remove(i-1);
numberList.remove(i);
break;
}
}
}
The minusMe method is exactly the same as the addMe method except with "-" in relevant places. The problem I am having is getting the equation read from left to right one item at a time and either doing the add or subtract method. Ideally I think I need to combine my 2 while loops with an iterator, to solve the problem but my attempts haven't worked. Any idea as to if this will solve my problem? If so please provide amended loop.
Regards
Have a look at this
java.uti.ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
java.util.Iterator<String> equIterator = equation.iterator();
int result = 0;
int multiplier = 1;
while(equIterator.hasNext()){
String operandOrOperator = equIterator.next();
if(operandOrOperator.equals("+")){
multiplier=1;
}else if(operandOrOperator.equals("-")){
multiplier=-1;
}else if(operandOrOperator.equals("*")){
result*=Integer.parseInt(equIterator.next()); // Assuming that next element will be there always after operator.
}else{
result+=(multiplier * Integer.parseInt(operandOrOperator));
}
}
System.out.println("Final result : " + result);
You are doing this all wrong. You need to use at least a recursive-descent expression parser, or Dijkstra's shunting-yard algorithm, maybe even a parser generator if this is going to grow into some kind of a language. You will find all these things via a web search.

how to speed up my ArrayList searching?

I currently have an ArrayList holding objects of a class I have created, I then parse through the ArrayList in a for loop searching and comparing some data from the ArrayList and some global variables that are loaded else where, however this ArrayList is constantly growing and will eventually have about 115 elements to it towards the end, which then takes a very long time to search through, the function that does this is also called once for every line I read from a text file and the text file will usually be around 400-500 lines long so as you can tell it is very slow process even when testing on small files. Is there a way to speed this up by maybe using another collection instead of an ArrayList, my reasoning for using the ArrayList is I have to know what index it is on when it finds a match.
Here is the class:
private ArrayList<PanelData> panelArray = new ArrayList<PanelData>(1);
public class PanelData {
String dev = "";
String inst = "";
double tempStart = 0.0;
double tempEnd = 0.0;
}
Function:
public void panelTimeHandler (double timeStart, double timeEnd) throws SQLException {
PanelData temps = new PanelData();
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
boolean flag = false;
if(!flag)
{
panelArray.add(temps);
flag = true;
}
for(int i = 0; i < panelArray.size(); ++i ) {
if(panelArray.get(i).dev.equals(devIDStr) && panelArray.get(i).inst.equals(instanceStr)) {
if(panelArray.get(i).tempStart <= timeStart && panelArray.get(i).tempEnd >= timeEnd ) {
//Do Nothing
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
insert();
panelArray.set(i, temps);
}
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
panelArray.add(temps);
insert();
}
}
}
If there is something more you would like to see just ask, thanks. Beef.
Update: Added insert() function
private void insert() throws SQLException
{
stmt = conn.createStatement();
String sqlStm = "update ARRAY_BAC_SCH_Schedule set SCHEDULE_TIME = {t '" + finalEnd + "'} WHERE SCHEDULE_TIME >= {t '" + finalStart + "'} AND" +
" SCHEDULE_TIME <= {t '" + finalEnd + "'} AND VALUE_ENUM = 0 AND DEV_ID = " + devIDStr + " and INSTANCE = " + instanceStr;
int updateSuccess = stmt.executeUpdate(sqlStm);
if (updateSuccess < 1)
{
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1, " + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalStart + "'}, 1, 'Unsupported')";
stmt.executeUpdate(sqlStm);
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1," + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalEnd + "'}, 0, 'Unsupported')";
stmt.executeUpdate(sqlStm);
}
if(stmt!=null)
stmt.close();
}
Update:
Thank you to Matteo, I realized I was adding to the array even if I didnt find a match till the 10th element it would then added to the array the first 9 times which created many extra elements in the array, which was why it was so slow, I added some breaks and did a little tweaking in the function, and it improved the performance a lot. Thanks for all the input
you can use LinkedHashSet. It seems you add only elements to the end of the list, which is exactly what LinkedHashSet does as well, when inserting an element.
Note however, a LinkedHashSet will not allow duplicates, since it is a set.
Searching if an element exists will be O(1) using contains()
Using the LinkedHashSet will also allow you to keep track of where an element was added, and iterating it will be in order of insertion.
What about using a hashmap?
I would create a small class for the key:
class Key {
String dev, instr;
// todo: implements equals & hashCode
}
and create the map:
Map<Key, PanelData> map = new HashMap...
then you can easily find the element you need by invoking map.get(new Key(...)).
Instead of creating a new class, you could also tweak the PanelData class, implementing methods equals & hashcode so that two classes are equal iff their dev and instr are equal. In this case, your map becomes:
Map<PanelData, PanelData> map ...
// to add:
map.put(temps, temps)
// to search:
PanelData elem = map.get(new PanelData(desiredDev, desiredInstr));
Quite a few optimiztions here.
1) the call: panelArray.get(i) is used repeatedly. Declare a PanelData variable outside the loop, but initialize it only once, at the very begining of the loop:
PanelData pd = null;
for (int i = 0; i < panelArray.size(); ++i) {
pd = panelArray.get(i);
...
}
2) If your dataset allows it, consider using a few maps to help speed look up times:
HashMap<String, PanelData> devToPanelDataMapping = new HashMap<String,PanelData>();
HashMap<String, PanelData> instToPanelDataMapping = new HashMap<String,PanelData>();
3) Consider hashing your strings into ints or longs since String.equals() is slow compared to (int == int)
4) If the ArrayList will be read only, perhaps a multithread solution may help. The thread that reads lines from the text file can hand out individual lines of data to different 'worker' threads.
1) Create PanelArray with the max expected size + 10% when you first create it.
List<PanelData> panelArray = new ArrayList<PanelData>(130) - this will prevent dynamic reallocations of the array which will save processing time.
2) What does insert() do? Odds are that is your resource hog.
This problem might best be solved with a different data structure such as a HashMap or SortedSet.
In order to use a HashMap, you would need to define a class that can produce a hash code for the dev and inst string pairs. One solution is something like:
public class DevAndInstPair
{
private String dev, inst;
#Override
public int hashCode() {
return ((dev.hashCode() * 0x490aac18) ^ inst.hashCode());
}
#Override
public boolean equals(Object o) {
if (o == null || !(o instanceof DevAndInstPair)) {
return false;
}
DevAndInstPair other = (DevAndInstPair) o;
return (dev.equals(other.dev) && inst.equals(other.inst));
}
}
You would then use HashMap<DevAndInstPair, PanelData> as the map type.
Alternatively, if you know that a certain character never appears in dev strings, then you can use that character as a delimiter separating the dev value from the inst value. Supposing that this character is a hyphen ('-'), the key values would be dest + '-' + inst and the key type of the map would be String.
To use SortedSet, you would either have PanelData implement Comparable<PanelData> or write a class implementing Comparator<PanelData>. Remember that the compare operation must be consistent with equals.
A SortedSet is somewhat trickier to use than a HashMap, but I personally think that it is the more elegant solution to this problem.

Categories

Resources