3

I'm quite new to CPLEX+Java. I try to implement a variant of an Orienteering Problem and a Pickup and Delivery problem. I would like to use a LazyConstraintCallback to ensure Subtour Elimination in Integer Solutions.

Due to the orienteering component, I need an additional variable (z[q]) in for the Callback, which is so far not included in the model.

protected void main() throws IloException {
        // first: test if more than one route exists
        int[][] cycles = getCycles(getLongRoute());
        int count = countCycles(cycles);
        IloNumVar[] z = model.boolVarArray(count);

        if (count > 1) {
            // add connectivity constraints
            int b = 1;
            for (int q = 0;q<cycles.length; q++) {
                IloLinearNumExpr expr1 = model.linearNumExpr();
                int[] cycle = cycles[q];
                int m = 0;
                for (int p = 0; p<cycle.length; p++) {
                    int i = ArrayHandler.getIndex(allLocations_k, cycle[p]);
                    for (int l = 0; l<cycle.length; l++) {
                        int j = ArrayHandler.getIndex(allLocations_k, cycle[l]);
                        if (i!=j) {
                            expr1.addTerm(1.0, x[i][j]);
                        }
                    }
                    if (ArrayHandler.contains(deliveryLocation_k, allLocations_k[i])) {
                        expr1.addTerm(ak[i], 1.0);
                    } else {
                        m++;
                        expr1.addTerm(ak[i], -1.0);
                    }
                }

                for (int p = 0; p<loc_k; p++) {
                    int i = allLocations_k[p];
                    if (!ArrayHandler.contains(cycle, i)) {
                        IloLinearNumExpr expr2 = model.linearNumExpr();
                        if (ArrayHandler.contains(deliveryLocation_k, i)) {
                            expr2.addTerm(ak[p], 1.0);
                            expr2.addTerm(z[q],-1.0);
                            this.add(model.le(expr2,0.0));
                            //this.addLe(expr2, z[q]);
                        } else {
                            expr2.addTerm(ak[p], 1.0);
                            expr2.addTerm(z[q], 1.0);
                            this.add(model.ge(expr2,1.0));
                            //model.addLe(1.0,expr2);
                        }
                    }
                }

                expr1.setConstant(m);
                expr1.addTerm(z[q], -1.0);
                this.add(model.le(0.0, expr1));
            }
        }
    }

It throws an "Unknown Object" Error after reading "this.add(model.ge(expr2,z[q]));", which is the first constraint it should add. I guess that this behavior is somehow connected to the unknown variable z[q]. Do I have to add this at another location? I don't know the final dimension of z[q], as I need a z[q] for every subtour found during the execution, this can grow exponentially large (that's why I hoped to be able to create it on the fly). Maybe the error message helps:

ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.CpxNumVar.getVarIndexValue(CpxNumVar.java:295)
at ilog.cplex.CpxLinearExpr.removeDuplicatesSafe(CpxLinearExpr.java:476)
at ilog.cplex.CpxCutCallback.addCut(CpxCutCallback.java:75)
at ilog.cplex.IloCplex$LazyConstraintCallback.add(IloCplex.java:14920)
at PDOP$IntegerCutCallback.main(PDOP.java:334)
at ilog.cplex.CpxCallback.callmain(CpxCallback.java:160)
at ilog.cplex.CpxLazyConstraintCallbackFunction.callIt(CpxLazyConstraintCallbackFunction.java:45)
at ilog.cplex.Cplex.CPXmipopt(Native Method)
at ilog.cplex.CplexI$SolveHandle.start(CplexI.java:2786)
at ilog.cplex.CplexI.solve(CplexI.java:2912)
at ilog.cplex.IloCplex.solve(IloCplex.java:10434)
at PDOP.solveIBR(PDOP.java:193)
at Application.main(Application.java:33)

I hope that this is no "too" stupid question, I've tried to find something on this behavior online, but did not find any examples in which an added variable was required.

Layla
  • 125
  • 10
  • 1
    It sounds like your problem is that the variables don't exist in any constraint or in the objective yet. So, CPLEX doesn't know about them and you get that exception. What happens if you `model.add()` the variables immediately after they are created? – rkersh Jan 30 '18 at 23:39
  • This does no longer result in the "Object not found" exception, but let's Java crash: # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffff59b47fe, pid=5192, tid=13024 # JRE version: Java(TM) SE Runtime Environment (9.0+11) (build 9.0.4+11) # Java VM: Java HotSpot(TM) 64-Bit Server VM (9.0.4+11, mixed mode, tiered, compressed oops, g1 gc, windows-amd64) # Problematic frame: # C [cplex1271remotejni.dll+0x5d47fe] # No core dump will be written. Minidumps are not enabled by default on client versions of Windows – Layla Jan 31 '18 at 06:55

1 Answers1

1

I continued reading into it and it seems as if it is not possible at all to add additional variables in a LazyConstraint (https://www.or-exchange.org/questions/14311/adding-variables-or-modifying-existing-constraints-during-callbacks-with-cplex-c)

I was able to reformulate my problem (it is not as concise and easy to read, but works ...), it is faster than with directly including the subtour elimination constraint in the problem and still results in a feasible solution.

Thanks rkersh for your help :)

Layla
  • 125
  • 10
  • In my haste, I didn't read your question very closely, and I only commented on the symptom (i.e., the `UnknownObjectException`). I'm glad that it led you to a solution, though. – rkersh Jan 31 '18 at 17:51