}
{composition-setup}
{section}
{column:width=300px}
{pagetree:root=Tutorial}
{column}
{column}
h1. A Road to Trouble
When programming in Java, you generally have [collections|http://docs.oracle.com/javase/tutorial/collections/] of objects, as previously discussed [here|Do you know Java]. Often, you want to create a variable (or constraint) for element of a collection. A *bad* approach is illustrated below:
{code} Column |
---|
A Road to TroubleWhen programming in Java, you generally have collections of objects, as previously discussed here. Often, you want to create a variable (or constraint) for element of a collection. A bad approach is illustrated below: |
Set<String> stringCollection = makeSomeStrings();//assume this is defined elsewhere
IloCplex cplex = new IloCplex();
String[] stringToIndex = new String[stringCollection.size()];
IloIntVar[] variablesToIndex = cplex.boolVarArray(stringCollection.size());
int i = 0;
for(String s: stringCollection){
stringToIndex[i++] = s;
}
|
| {code}
{} |
---|
public IloIntVar getVariableForString(String s, String[] stringToIndex, IloIntVar[] variablesToIndex){
for(int i = 0; i < stringToIndex.length; i++){
if(stringToIndex[i].equals(s)){
return variablesToIndex[i];
}
}
return null;
}
public String getStringForVariable(IloIntVar v, String[] stringToIndex, IloIntVar[] variablesToIndex){
for(int i = 0; i < variablesToIndex.length; i++){
if(variablesToIndex[i] == v){
return stringToIndex[i];
}
}
return null;
}
|
| {code}
* For {mathinline}n{mathinline} {mathinline}O(n){mathinline}.
* We are maintaining two data structures and an index by hand, which leave a lot of room for programmer error
* We cannot add new variables at a later date
We can eliminate any chance of an indexing error and improve our access time to {mathinline}O(1){mathinline} by replacing our two arrays by two [HashMaps|http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html], e.g.
{code}- .
- We are maintaining two data structures and an index by hand, which leave a lot of room for programmer error
- We cannot add new variables at a later date
We can eliminate any chance of an indexing error and improve our access time to by replacing our two arrays by two HashMaps, e.g. Code Block |
---|
Set<String> stringCollection = makeSomeStrings();//assume this is defined elsewhere
IloCplex cplex = new IloCplex();
Map<String,IloIntVar> stringToVariable = new HashMap<String,IloIntVar>();
Map<IloIntVar,String> variableToString = new HashMap<IloIntVar,String>();
for(String s: stringCollection){
IloIntVar v = cplex.boolVar();
stringToVariable.put(s,v);
variableToString.put(v,s);
}
|
| {code}
h1. Good Style
[|http://code.google.com/p/guava-libraries/wiki/GuavaExplained?tm=6] [ImmutableBiMap|http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/.html] __
{} |
---|
public static <T> ImmutableBiMap<T,IloIntVar> makeBinaryVariables(IloCplex cplex, Iterable<T> set) throws IloException{
Builder<T,IloIntVar> ans = ImmutableBiMap.builder();
for(T t: set){
ans.put(t, cplex.boolVar());
}
return ans.build();
}
|
| {code}
{} |
---|
Set<String> stringCollection = makeSomeStrings();//assume this is defined elsewhere
IloCplex cplex = new IloCplex();
ImmutableBiMap<String,IloIntVar> stringVarBiMap = Util.makeBinaryVariables(cplex,stringCollection);
for(String s: stringCollection){
stringVarMap.put(s,cplex.boolVar());
}
public IloIntVar getVariableForString(String s, ImmutableBiMap<String,IloIntVar> stringVarBiMap){
return stringVarBiMap.get(s);
}
public String getStringForVariable(IloIntVar v, ImmutableBiMap<String,IloIntVar> stringVarBiMap){
return stringVarBiMap.inverse().get(v);
}
|
| {code}
[|http://code.google.com/p/guava-libraries/wiki/FunctionalExplained] [|http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Function.html]
|| || ||||Description||
|{anchor:integerSum}integerSum|IloLinearIntExpr|IloCplex cplex, | Description |
---|
integerSum | IloLinearIntExpr | IloCplex cplex, BiMap<T,IloIntVar> |
| | {mathinline} e \in \text{set}{mathinline} finds the variable {mathinline} x_e {mathinline} in variables and returns {mathinline} \sum_{e \in \text{set}} x_e{mathinline}|
|integerSum|IloLinearIntExpr|IloCplex cplex, BiMap<T,IloIntVar> variables, Iterable<T> set,Function<? super T,Integer> coefficients|For each {mathinline} e \in \text{set}{mathinline} finds the variable {mathinline} x_e {mathinline} in variables and {mathinline}c_e{mathinline} by applying coefficients to {mathinline}e{mathinline} and returns {mathinline} \sum_{e \in \text{set}} c_e x_e{mathinline}|
|{anchor:calcSum}calcSum|double|Set<E> terms, Map<E,Double> coefficients|If for every {mathinline}e \in \text{terms}{mathinline}, we let {mathinline}c_e{mathinline} be zero if coefficients does not contain the key {mathinline}e{mathinline} and the value of {mathinline}e{mathinline} coefficientsComputes otherwise, returns {mathinline} \sum_{e \in \text{terms}} c_e{mathinline}.|
While the final function actually has nothing to do with CPLEX, it will often be useful when using CPLEX.
h1. Simple Example Revisited
Recall the IP we modeled with CPLEX in the previous section:
{mathdisplay} finds the variable in variables and returns | integerSum | IloLinearIntExpr | IloCplex cplex, BiMap<T,IloIntVar> variables, Iterable<T> set,Function<? super T,Integer> coefficients | For each finds the variable in variables and by applying coefficients to and returns | calcSum | double | Set<E> terms, Map<E,Double> coefficients | If for every , we let be zero if coefficients does not contain the key and the value of coefficientsComputes otherwise, returns . |
While the final function actually has nothing to do with CPLEX, it will often be useful when using CPLEX. Simple Example RevisitedRecall the IP we modeled with CPLEX in the previous section: Mathdisplay |
---|
\begin{aligned}
&\min & x + 2y + 3z\\
&\text{subject to}& x + y + z &\geq 2\\
&& x,y,z &\in\{0,1\}
\end{aligned}
|
| {mathdisplay}
{{}} __
{} |
---|
public static void exerciseTwo() throws IloException{
List<String> varNames = Arrays.asList("x","y","z");
Map<String,Integer> weightsMap = new HashMap<String,Integer>();
weightsMap.put("x",1);
weightsMap.put("y",2);
weightsMap.put("z",3);
Function<String,Integer> weights = Functions.forMap(weightsMap);
IloCplex cplex = new IloCplex();
//write code here!
}
|
| {code}
{{}} {{}}
{:=} _Solution_
{cloak:id=GoodStyleSolution|visible=false}
{code}
public static void exerciseTwo() throws IloException{
List<String> varNames = Arrays.asList("x","y","z");
Map<String,Integer> weightsMap = new HashMap<String,Integer>();
weightsMap.put("x",1);
weightsMap.put("y",2);
weightsMap.put("z",3);
Function<String,Integer> weights = Functions.forMap(weightsMap);
IloCplex cplex = new IloCplex();
//write code here!
ImmutableBiMap<String,IloIntVar> varMap = Util.makeBinaryVariables(cplex,varNames);
cplex.addGe(Util.integerSum(cplex,varMap,varNames),2);
cplex.addMinimize(Util.integerSum(cplex,varMap,varNames,weights));
cplex.solve();
for(String varName: varNames){
System.out.println(varName +": " + cplex.getValue(varMap.get(varName)));
}
System.out.println("obj: " + cplex.getObjValue());
}
{code}
{cloak}
{column}
{section} Solution Cloak |
---|
visible | false |
---|
id | GoodStyleSolution |
---|
| |
|
|