Let's say i have an OptimizationModel abc.lp, which i want to import with the CPlex java-API. I use: importModel function (click) to import it. Now i want to change some decision variable's factors in the constraint or in the objective. For example the imported model abc.lp looks as follows:
Objective: Minimize <factor1>x1 + <factor2>x2
Constraint: <factor1>x1 + <factor2>x2 <= 40
For me factor1 and factor2 are input parameters of a function. So i get:
public void(double factor1, double factor2){
...
cplexModel.import("path/to/abc.lp")
// Change parameters, how to do it?
Is there a handy way to set the factors dynamically from an imported Model with the Cplex-API?
Thanks a lot!
Yes, this is possible. It's not very intuitive, at least to me.
Here's an example snippet that assumes a LP (linear objective and constraints):
// Read model from file with name args[0] into cplex optimizer object
cplex.importModel(args[0]);
// Get the objective and modify it.
IloObjective obj = cplex.getObjective();
IloLinearNumExpr objExpr = (IloLinearNumExpr) obj.getExpr();
IloLinearNumExprIterator iter = objExpr.linearIterator();
// Loop through the linear objective and modify, as necessary.
while (iter.hasNext()) {
IloNumVar var = iter.nextNumVar();
System.out.println("Old coefficient for " + var + ": " + iter.getValue());
// Modify as needed.
if ( var.getName().equals("x1") ) {
iter.setValue(42);
System.out.println("New coefficient for " + var + ": " + iter.getValue());
}
}
// Save the changes.
obj.setExpr(objExpr);
// Assumes that there is an LP Matrix. The fact that we used
// importModel() above guarantees that there will be at least
// one.
IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next();
for (int i = 0; i < lp.getNrows(); i++) {
IloRange range = lp.getRange(i);
System.out.println("Constraint " + range.getName());
IloLinearNumExpr conExpr = (IloLinearNumExpr) range.getExpr();
IloLinearNumExprIterator conIter = conExpr.linearIterator();
// Loop through the linear constraints and modify, as necessary.
while (conIter.hasNext()) {
IloNumVar var = conIter.nextNumVar();
System.out.println("Coefficient for " + var + ": " + conIter.getValue());
// Modify as needed (as above).
if ( var.getName().equals("x1") ) {
conIter.setValue(42);
System.out.println("New coefficient for " + var + ": " + conIter.getValue());
}
}
// Save changes (as above).
range.setExpr(conExpr);
}
cplex.exportModel("modified.lp");
// Solve the model and display the solution if one was found
if ( cplex.solve() ) {
// do something here.
}
Here, we're looking for a variable named "x1". We set it's coefficient to 42 in the objective and in all linear constraints. The println's are for debugging. I did this quickly, so make sure you test it. Otherwise, you should be able to modify that to suit your needs. Hope that helps.
Related
My need is to read the color of a text with PDFlib TET.
As a basis I'm using this PDFlib example: https://www.pdflib.com/tet-cookbook/tet_and_pdflib/search_and_replace_text/
Before both result.add(new rectangle(...)) calls I'm trying to read the color like this:
String csname = tet.pcos_get_string(doc, "colorspaces[" + tet.colorspaceid + "]/name");
if ("Separation".equals(csname)) {
String type = tet.pcos_get_string(doc, "type:colorspaces[" + tet.colorspaceid + "]/colorantname");
System.out.println(type);
if (StringUtils.equalsIgnoreCase("name", type)) {
System.out.println(tet.pcos_get_string(doc, "colorspaces[" + tet.colorspaceid + "]/colorantname"));
}
}
Unfortunately tet.colorspaceid is always 0.
But the correct colorspaceid is 6 (with "correct" = the index of the color the text actually is written with). I know the indexes because I iterated over all colorspaces like this and for i=6 the system prints the name of the intended color:
String type = tet.pcos_get_string(doc, "type:colorspaces[" + i + "]/colorantname");
if (StringUtils.equalsIgnoreCase("name", type)) {
System.out.println(tet.pcos_get_string(doc, "colorspaces[" + i + "]/colorantname"));
}
What do I need to do for tet.colorspaceid being the id of the colorspace of the currently found word fragment?
Or am I completely wrong and TET reads the color somehow else?
Found it - the solution is method print_color_value in this example: https://www.pdflib.com/tet-cookbook/text/glyphinfo/
Just copy method print_color_value, return csname (or colorantname in the if blocks) and rename the method to e.g. getColorValue.
If needed throw away the formatter stuff.
This one should be fairly simple I think, I just can't remember how, when using get methods of an object, how to pull the highest double out of the pack and put it in the println.
So far I just get every object to print with its percentages. But for the life of me I just can't remember and I know I've done this before.
public void displayBookWithBiggestPercentageMarkup(){
Collection<Book> books = getCollectionOfItems();
Iterator<Book> it = books.iterator();
while(it.hasNext()){
Book b = it.next();
double percent = b.getSuggestedRetailPriceDollars() / b.getManufacturingPriceDollars() * 100.0;
System.out.println("Highest markup is " + percent + " " + b.getTitle() + " " + b.getAuthor().getName().getLastName());
}
}
I'm pretty sure I need another local variable but I can't seem to do anything but make it equal the other percent. I have removed the other variable for now as I try to think about it.
I won't go into a lot of detail because it's homework (well done for being up-front about that, by the way) but here's the key idea: keep track of the largest percentage you've seen so far as your loop runs. That's what you want in your other variable.
Good job posting what you've tried so far. You were on the right track. As you loop through your books, keep a variables continuously updated with the highest percent seen so far and another variable for the associated book. Output the variable at the end outside the loop after iteration is done. Also, don't forget to check the edge case of an empty list of books! Something like this should do the trick:
public void displayBookWithBiggestPercentageMarkup(){
Collection<Book> books = getCollectionOfItems();
if (books.size() == 0) {
return;
}
Iterator<Book> it = books.iterator();
double highestPercent = 0;
Book highestPercentBook = null;
while(it.hasNext()){
Book b = it.next();
double percent = b.getSuggestedRetailPriceDollars() / b.getManufacturingPriceDollars() * 100.0;
if (percent > highestPercent) {
highestPercent = percent;
highestPercentBook = b;
}
}
System.out.println("Highest markup is " + highestPercent
+ " " + highestPercentBook.getTitle()
+ " " + highestPercentBook.getAuthor().getName().getLastName());
}
I have an ArrayList called participatingUsers. Person has Person.money and Person.name that are interesting.
What I want to do is check the ArrayList against itself...
So I have this code
for (Person debtHaver : this.participatingUsers) {
// If they're in debt...
if (debtHaver.getMoney() < 0) {
// With someone...
for (Person personToPay : this.participatingUsers) {
// That's not themselves...
if (!debtHaver.getName().equals(personToPay.getName())) {
// See if the personToPay is ranked higher than the
// debtHaver...
if (personToPay.getMoney() > 0) {
// If the debtee can pay the debter in full
if (-debtHaver.getMoney() <= personToPay.getMoney()) {
payment += debtHaver.getName() + " has to pay " + personToPay.getName() + " " + -debtHaver.getMoney() + "\n";
debtHaver.increaseMoney(-debtHaver.getMoney());
personToPay.decreaseMoney(-debtHaver.getMoney());
}
if (-debtHaver.getMoney() > personToPay.getMoney())
{
//But if he can't pay in full... Just pay the small bit you can pay.
payment += debtHaver.getName() + " has to pay " + personToPay.getName() + " " + personToPay.getMoney() + "\n";
debtHaver.increaseMoney(personToPay.getMoney());
personToPay.decreaseMoney(personToPay.getMoney());
}
}
}
}
}
}
return payment;
Basically, I have a double for loop where I check each person against itself. If someone is in debt and has a negative amount of money, seek if there is someone who they can pay, then pay that person. The thing is, personToPay is not being updated in the arrayList debtHaver is in. I'm basically editing two different ArrayLists instead of the same one. What's the best way to deal with this issue?
You are editing the same list. The problem is probably in this code:
debtHaver.increaseMoney(-debtHaver.getMoney());
personToPay.decreaseMoney(-debtHaver.getMoney());
You are putting debtHaver's amount to zero by the first line. And then you try to modify personToPay with zero amount. Just swap two lines of code and it should work:
personToPay.decreaseMoney(-debtHaver.getMoney());
debtHaver.increaseMoney(-debtHaver.getMoney());
I'm new to OO programing and having a bit of trouble with the design of my program to use the concepts. I have done the tutorials but am still having problem.
I have a recursion that takes a value of items(could be anything in this example, stocks) and figures out what number of them are needed to equal a specific value(in this code 100). This part works but I want to know if a stock's weighting exceeds a threshold. Originally I approached this problem with a method that did a for loop and calculated the entire list of values but this is super inefficient because its doing it on every loop of the recursion. I thought this would be a good time to try to learn classes because I could use a class to maintain state information and just increment the value on each loop and it'll let me know when the threshold is hit.
I think I have the code but I don't fully understand how to design this problem with classes. So far it runs the loop each step of the recursion because I'm initially the class there. Is there a better way to design this? My end goal is to be notified when a weighting is exceeded(which I can somewhat already do) but I want to do in way that uses the least bit of resources(avoiding inefficient/unnecessary for loops)
Code(Here's the entire code I have been using to learn but the problem is with the Counter class and its location within the findVariables method):
import java.util.Arrays;
public class LearningClassCounting {
public static int[] stock_price = new int[]{ 20,5,20};
public static int target = 100;
public static void main(String[] args) {
// takes items from the first list
findVariables(stock_price, 100, new int[] {0,0,0}, 0, 0);
}
public static void findVariables(int[] constants, int sum,
int[] variables, int n, int result) {
Counter Checker = new Counter(stock_price, variables);
if (n == constants.length) {
if (result == sum) {
System.out.println(Arrays.toString(variables));
}
} else if (result <= sum){ //keep going
for (int i = 0; i <= 100; i++) {
variables[n] = i;
Checker.check_total_percent(n, i);
findVariables(constants, sum, variables, n+1, result+constants[n]*i);
}
}
}
}
class Counter {
private int[] stock_price;
private int[] variables;
private int value_so_far;
public Counter(int[] stock_price, int[] variables) {
this.stock_price = stock_price;
this.variables = variables;
for (int location = 0; location < variables.length; location++) {
//System.out.println(variables[location] + " * " + stock_price[location] + " = " + (variables[location] * stock_price[location]) );
value_so_far = value_so_far + (variables[location] * stock_price[location]);
}
//System.out.println("Total value so far is " + value_so_far);
//System.out.println("************");
}
public void check_total_percent(int current_location, int percent) {
// Check to see if weight exceeds threshold
//System.out.println("we are at " + current_location + " and " + percent + " and " + Arrays.toString(variables));
//System.out.println("value is " + stock_price[current_location] * percent);
//formula I think I need to use is:
if (percent == 0) {
return;
}
int current_value = (stock_price[current_location] * percent);
int overall_percent = current_value/(value_so_far + current_value);
if (overall_percent > 50 ) {
System.out.println("item " + current_location + " is over 50%" );
}
}
}
What you're describing sounds like a variant of the famous knapsack problem. There are many approaches to these problems, which are inherently difficult to calculate.
Inherently, one may need to check "all the combinations". The so-called optimization comes from backtracking when a certain selection subset is already too large (e.g., if 10 given stocks are over my sum, no need to explore other combinations). In addition, one can cache certain subsets (e.g., if I know that X Y and Z amount to some value V, I can reuse that value). You'll see a lot of discussion of how to approach these sort of problems and how to design solutions.
That being said, my view is that while algorithmic problems of this sort may be important for learning how to program and structure code and data structures, they're generally a very poor choice for learning object-oriented design and modelling.
I'm using libsvm and the documentation leads me to believe that there's a way to output the believed probability of an output classification's accuracy. Is this so? And if so, can anyone provide a clear example of how to do it in code?
Currently, I'm using the Java libraries in the following manner
SvmModel model = Svm.svm_train(problem, parameters);
SvmNode x[] = getAnArrayOfSvmNodesForProblem();
double predictedValue = Svm.svm_predict(model, x);
Given your code-snippet, I'm going to assume you want to use the Java API packaged with libSVM, rather than the more verbose one provided by jlibsvm.
To enable prediction with probability estimates, train a model with the svm_parameter field probability set to 1. Then, just change your code so that it calls the svm method svm_predict_probability rather than svm_predict.
Modifying your snippet, we have:
parameters.probability = 1;
svm_model model = svm.svm_train(problem, parameters);
svm_node x[] = problem.x[0]; // let's try the first data pt in problem
double[] prob_estimates = new double[NUM_LABEL_CLASSES];
svm.svm_predict_probability(model, x, prob_estimates);
It's worth knowing that training with multiclass probability estimates can change the predictions made by the classifier. For more on this, see the question Calculating Nearest Match to Mean/Stddev Pair With LibSVM.
The accepted answer worked like a charm. Make sure to set probability = 1 during training.
If you are trying to drop prediction when the confidence is not met with threshold, here is the code sample:
double confidenceScores[] = new double[model.nr_class];
svm.svm_predict_probability(model, svmVector, confidenceScores);
/*System.out.println("text="+ text);
for (int i = 0; i < model.nr_class; i++) {
System.out.println("i=" + i + ", labelNum:" + model.label[i] + ", name=" + classLoadMap.get(model.label[i]) + ", score="+confidenceScores[i]);
}*/
//finding max confidence;
int maxConfidenceIndex = 0;
double maxConfidence = confidenceScores[maxConfidenceIndex];
for (int i = 1; i < confidenceScores.length; i++) {
if(confidenceScores[i] > maxConfidence){
maxConfidenceIndex = i;
maxConfidence = confidenceScores[i];
}
}
double threshold = 0.3; // set this based data & no. of classes
int labelNum = model.label[maxConfidenceIndex];
// reverse map number to name
String targetClassLabel = classLoadMap.get(labelNum);
LOG.info("classNumber:{}, className:{}; confidence:{}; for text:{}",
labelNum, targetClassLabel, (maxConfidence), text);
if (maxConfidence < threshold ) {
LOG.info("Not enough confidence; threshold={}", threshold);
targetClassLabel = null;
}
return targetClassLabel;