I'm using varargs in a method for optional parameters. Any suggestion for how best to document the method?
Here's a wonderfully contrived example:
/**
*
* #param consumption
* liters of liquid consumed after last pee
* #param options
* urgency
* how badly you have to pee on a scale of 1-3,
* 3 being the highest (default 1)
* bribe
* what's a toilet worth to you? (default 0)
* #return waitTime
* minutes until you'll be able to relieve yourself
*/
public integer whenCanIUseTheBathroom(int consumption, int... options){
// Segment handling options, defining defaults/fallbacks
int urgency = 1;
int bribe = 0;
if(options.length > 0) {
urgency = options[0];
}
if(options.length == 2) {
bribe = options[1];
}
// Segment determining one's fate
...
}
Varargs are not usually used to implement optional parameters with different meanings because it does not support different types for the "subparams", offers poor refactoring support (want to insert a new "subparam" or remove an old one?), and is inflexible (you can't omit "urgency" while providing "bribe"). Therefore, there is no standard way to document them with javadoc, either.
Optional parameters are typically implemented using overloading (usually with delegation), or a variant of the builder pattern, which allows you to write:
new BathroomRequest(3).withBribe(2).compute();
For a more thorough discussion of that approach, see Joshua Bloch's Effective Java, item 2.
Related
I have a rather complex MILP, but the main problem is the number of continuous variables, not the number of binaries. I just "hard-coded" the linear relaxation to understand its output, and it takes approx. 10-15 minutes to solve (which is not extremely surprising). If I run the MILP with outputs, I don't see anything happening for the first 10 minutes, because it takes those 10 minutes to construct a first integer-feasible solution. So it would help to be able to enable the same outputs I am seeing when solving the linear relaxation "manually" (so something like Iteration: 1 Dual objective = 52322816.412592) within the B&B output.
Is this possible? I googled at bit, but I only found solutions for steering the solution algorithm, or for deriving linear relaxations using callbacks, while I am interested in a "simple" output of the intermediate steps.
It sounds like you are asking for extra detailed logging during the linear relaxation part of the solve during the B&B. Have a look at the CPLEX parameter settings like IloCplex.Param.MIP.Display (try setting this to 5) and also IloCplex.Param.Simplex.Display (try setting to 1 or 2).
within java you could rely on IloConversion objects that will allow you to locally change the type of one or more variables.
See the sample AdMIPex6.java
/* --------------------------------------------------------------------------
* File: AdMIPex6.java
* Version 20.1.0
* --------------------------------------------------------------------------
* Licensed Materials - Property of IBM
* 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21
* Copyright IBM Corporation 2001, 2021. All Rights Reserved.
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with
* IBM Corp.
* --------------------------------------------------------------------------
*
* AdMIPex6.java -- Solving a model by passing in a solution for the root node
* and using that in a solve callback
*
* To run this example, command line arguments are required:
* java AdMIPex6 filename
* where
* filename Name of the file, with .mps, .lp, or .sav
* extension, and a possible additional .gz
* extension.
* Example:
* java AdMIPex6 mexample.mps.gz
*/
import ilog.concert.*;
import ilog.cplex.*;
public class AdMIPex6 {
static class Solve extends IloCplex.SolveCallback {
boolean _done = false;
IloNumVar[] _vars;
double[] _x;
Solve(IloNumVar[] vars, double[] x) { _vars = vars; _x = x; }
public void main() throws IloException {
if ( !_done ) {
setStart(_x, _vars, null, null);
_done = true;
}
}
}
public static void main(String[] args) {
try (IloCplex cplex = new IloCplex()) {
cplex.importModel(args[0]);
IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next();
IloConversion relax = cplex.conversion(lp.getNumVars(),
IloNumVarType.Float);
cplex.add(relax);
cplex.solve();
System.out.println("Relaxed solution status = " + cplex.getStatus());
System.out.println("Relaxed solution value = " + cplex.getObjValue());
double[] vals = cplex.getValues(lp.getNumVars());
cplex.use(new Solve(lp.getNumVars(), vals));
cplex.delete(relax);
cplex.setParam(IloCplex.Param.MIP.Strategy.Search,
IloCplex.MIPSearch.Traditional);
if ( cplex.solve() ) {
System.out.println("Solution status = " + cplex.getStatus());
System.out.println("Solution value = " + cplex.getObjValue());
}
}
catch (IloException e) {
System.err.println("Concert exception caught: " + e);
}
}
}
if you use OPL then you could have a look at Relax integrity constraints and dual value
int nbKids=300;
float costBus40=500;
float costBus30=400;
dvar int+ nbBus40;
dvar int+ nbBus30;
minimize
costBus40*nbBus40 +nbBus30*costBus30;
subject to
{
ctKids:40*nbBus40+nbBus30*30>=nbKids;
}
main {
var status = 0;
thisOplModel.generate();
if (cplex.solve()) {
writeln("Integer Model");
writeln("OBJECTIVE: ",cplex.getObjValue());
}
// relax integrity constraint
thisOplModel.convertAllIntVars();
if (cplex.solve()) {
writeln("Relaxed Model");
writeln("OBJECTIVE: ",cplex.getObjValue());
writeln("dual of the kids constraint = ",thisOplModel.ctKids.dual);
}
}
I am using JavaBDD to do some computation with BDDs.
I have a very large BDD with many variables and I want to calculate how many ways it can be satisfied with a small subset of those variables.
My current attempt looks like this:
// var 1,2,3 are BDDVarSets with 1 variable.
BDDVarSet union = var1;
union = union.union(var2);
union = union.union(var3);
BDD varSet restOfVars = allVars.minus(union);
BDD result = largeBdd.exist(restOfVars);
double sats = result.satCount(); // Returns a very large number (way too large).
double partSats = result.satCount(union) // Returns an inccorrect number. It is documented that this should not work.
Is the usage of exist() incorrect?
After a bit of playing around I understood what my problem was.
double partSats = result.satCount(union);
Does return the correct answer. What it does is calculate how many possible solutions there are, and divides the solution by 2^(#vars in set).
The reason I thought satCount(union) does not work is due to an incorrect usage of exist() somewhere else in the code.
Here is the implementation of satCound(varSet) for reference:
/**
* <p>Calculates the number of satisfying variable assignments to the variables
* in the given varset. ASSUMES THAT THE BDD DOES NOT HAVE ANY ASSIGNMENTS TO
* VARIABLES THAT ARE NOT IN VARSET. You will need to quantify out the other
* variables first.</p>
*
* <p>Compare to bdd_satcountset.</p>
*
* #return the number of satisfying variable assignments
*/
public double satCount(BDDVarSet varset) {
BDDFactory factory = getFactory();
if (varset.isEmpty() || isZero()) /* empty set */
return 0.;
double unused = factory.varNum();
unused -= varset.size();
unused = satCount() / Math.pow(2.0, unused);
return unused >= 1.0 ? unused : 1.0;
}
Question: How are you handling these use cases?
do you use static helper methods?
do you use the verbose equals followed by isAfter/isBefore?
do you use the negated opposite condition?
do you use 3rd party library helpers?
In daily business, I often need to check if date a <= date b or if date a >= date b.
The internet often suggests to use the negated versions of isBefore/isAfter methods.
In practice I find that I
almost never get these negated comparisons right on the first try (and they should be intuitive and easy).
have a hard time understanding the business logic when reading the code
I guess part of me is still hoping that I just overlooked the corresponding methods in the API (please!).
/**
* #return true if candidate >= reference </br>
* or in other words: <code>candidate.equals(reference) || candidate.isAfter(reference)</code> </br>
* or in other words: <code>!candidate.isBefore(reference) </br>
* or in other words: <code>candidate.compareTo(reference) >= 0
*/
public static boolean isEqualOrAfter(LocalDate candidate, LocalDate reference)
{
return !candidate.isBefore(reference);
}
/**
* #return true if candidate <= reference </br>
* or in other words: <code>candidate.equals(reference) || candidate.isBefore(reference)</code> </br>
* or in other words: <code>!candidate.isAfter(reference) </br>
* or in other words: <code>candidate.compareTo(reference) <= 0
*/
public static boolean isEqualOrBefore(LocalDate candidate, LocalDate reference)
{
return !candidate.isAfter(reference);
}
EDIT: As suggested by Andreas, I added the version with compareTo method, I hope I got them right (without testing).
EDIT 2: Example:
// Manager says: "Show me everything from 3 days ago or later" or "show me everything that's at most 3 days old"
for(Item item : items) {
// negation idiom
if(!item.getDate().isBefore(LocalDate.now().minusDays(3))) {
// show
}
// compareTo idiom
if(item.getDate().compareTo(LocalDate.now().minusDays(3)) >= 0) {
// show
}
// desired
if(item.getDate().isEqualOrAfter(LocalDate.now().minusDays(3))) {
// show
}
}
The methods you seek are unnecesary. That's how you do it:
isEqualOrBefore == !isAfter
isEqualOrAfter == !isBefore
Is compareTo consistent for these types (Well they implement Comparable)?
I remember the inline documentation suggesting the "idiom":
(a.compareTo(b) <operator> 0), so
for isEqualOrBefore: (a.compareTo(b) <= 0)
for isEqualOrAfter: (a.compareTo(b) >= 0)
I am basically being asked to take the Unicode value of a string, multiply it by 10% and add whatever level the object currently has. It's frustrating because as it turns out I have the logic down including the code yet I still get an error that says: expected:<0> but was:<8>. Any suggestions, maybe it's just a slight nuance I have to make in the logic, although I'm fairly certain it's right. Take note of the getLevel method because that's where the error is
public class PouchCreature implements Battleable {
private String name;
private int strength;
private int levelUps;
private int victoriesSinceLevelUp;
/**
* Standard constructor. levelUps and victoriesSinceLevelUp start at 0.
*
* #param nameIn desired name for this PouchCreature
* #param strengthIn starting strength for this PouchCreature
*/
public PouchCreature(String nameIn, int strengthIn) {
this.name = nameIn;
this.strength = strengthIn;
this.levelUps = 0;
this.victoriesSinceLevelUp = 0;
}
/**
* Copy constructor.
*
* #param other reference to the existing object which is the basis of the new one
*/
public PouchCreature(PouchCreature other) {
this.name=other.name;
this.strength=other.strength;
this.levelUps=other.levelUps;
this.victoriesSinceLevelUp=other.victoriesSinceLevelUp;
}
/**
* Getter for skill level of the PouchCreature, which is based on the
* first character of its name and the number of levelUps it has.
* Specifically, the UNICODE value of the first character in its name
* taken %10 plus the levelUps.
*
* #return skill level of the PouchCreature
*/
public int getLevel() {
int value = (int)((int)(getName().charAt(0)) * 0.1);
return value + this.levelUps;
}
You've said you're supposed to increase the value by 10%. What you're actually doing, though, is reducing it 90% by taking just 10% of it (and then truncating that to an int). 67.0 * 0.1 = 6.7, which when truncated to an int is 6.
Change the 0.1 to 1.1 to increase it by 10%:
int value = (int)((int)(getName().charAt(0)) * 1.1);
// --------------------------------------------^
There, if getName() returns "Centaur" (for instance), the C has the Unicode value 67, and value ends up being 73.
We need to see the code you're calling the class with and that is generating your error message. Why is it expecting 0? 8 seems like a valid return value from the information you've given.
Is there a way to add references to one or more of a method's parameters from the method documentation body?
Something like:
/**
* When {#paramref a} is null, we rely on b for the discombobulation.
*
* #param a this is one of the parameters
* #param b another param
*/
void foo(String a, int b)
{...}
As far as I can tell after reading the docs for javadoc there is no such feature.
Don't use <code>foo</code> as recommended in other answers; you can use {#code foo}. This is especially good to know when you refer to a generic type such as {#code Iterator<String>} -- sure looks nicer than <code>Iterator<String></code>, doesn't it!
The correct way of referring to a method parameter is like this:
As you can see in the Java Source of the java.lang.String class:
/**
* Allocates a new <code>String</code> that contains characters from
* a subarray of the character array argument. The <code>offset</code>
* argument is the index of the first character of the subarray and
* the <code>count</code> argument specifies the length of the
* subarray. The contents of the subarray are copied; subsequent
* modification of the character array does not affect the newly
* created string.
*
* #param value array that is the source of characters.
* #param offset the initial offset.
* #param count the length.
* #exception IndexOutOfBoundsException if the <code>offset</code>
* and <code>count</code> arguments index characters outside
* the bounds of the <code>value</code> array.
*/
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = new char[count];
this.count = count;
System.arraycopy(value, offset, this.value, 0, count);
}
Parameter references are surrounded by <code></code> tags, which means that the Javadoc syntax does not provide any way to do such a thing. (I think String.class is a good example of javadoc usage).
I guess you could write your own doclet or taglet to support this behaviour.
Taglet Overview
Doclet Overview
Here is how it is written in Eclipse Temurin JDK 8 sources:
It looks like the only way is or {#code }, but it's not a link - it's just formatting.