jp.ac.kobe_u.cs.cream.Serialized Maven / Gradle / Ivy
/*
* @(#)Serialized.java
*/
package jp.ac.kobe_u.cs.cream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
/**
* Serialized constraints constructed from an array of n integer variables (v[0],
* ..., v[n-1]) and an array of n positive integer constants (a[0], ...,
* a[n-1]). This constraint means v[i]+a[i] <= v[j] or v[j]+a[j] <=
* v[i] for each pair of i and j.
*
* @see Sequential
* @see LocalSearch
* @since 1.0
* @version 1.4
* @author Naoyuki Tamura ([email protected])
*/
public class Serialized extends Constraint {
private Variable[] v;
private int[] a;
private int[] order;
/**
* Adds a serialized constraint to the network. The length of two arrays should be the same. All
* elements of a should be positive.
*
* @param net the network
* @param v the array of integer variables
* @param a the array of positive integer constants
*/
public Serialized(Network net, Variable[] v, int[] a) {
super(net);
this.v = v.clone();
this.a = a.clone();
order = null;
}
@Override
public Constraint copy(Network net) {
return new Serialized(net, Constraint.copy(v, net), a);
}
/**
* This class represents a condition on which the order of variables are chosen for this
* serialized constraint in the solution. The condition will be modified by a {@linkplain
* Serialized.Swap swap operation} to find a neighbor solution in the {@link LocalSearch} solver.
*
* @see LocalSearch
* @since 1.0
* @version 1.4
* @author Naoyuki Tamura ([email protected])
*/
public class SerializedCondition extends Condition {
private int[][] code;
/**
* Constructs a condition for the serialized constraint under the current solution by extracting
* the order of variables.
*/
public SerializedCondition() {
index = Serialized.this.getIndex();
code = new int[v.length][3];
for (int i = 0; i < code.length; i++) {
Domain d = v[i].getDomain();
code[i][0] = i;
code[i][1] = ((IntDomain) d).value();
code[i][2] = a[i];
}
Comparator comp =
new Comparator() {
@Override
public int compare(int[] p1, int[] p2) {
int k1 = p1[1];
int k2 = p2[1];
return (k1 < k2) ? -1 : (k1 == k2) ? 0 : 1;
}
};
Arrays.sort(code, comp);
}
@Override
public void setTo(Network network) {
Serialized s = (Serialized) network.getConstraint(index);
if (code == null) {
s.order = null;
} else {
s.order = new int[code.length];
for (int i = 0; i < s.order.length; i++) {
s.order[i] = code[i][0];
}
}
}
@Override
public List operations() {
List operations = new LinkedList();
for (int i = 0; i < code.length - 1; i++) {
if (code[i][1] + code[i][2] == code[i + 1][1]) {
// adjacent
Operation op = new Swap(index, i, i + 1);
operations.add(op);
}
}
return operations;
}
}
/**
* This class represents an operation of swapping an order of two variables.
*
* @see LocalSearch
* @since 1.0
* @version 1.4
* @author Naoyuki Tamura ([email protected])
*/
public class Swap extends Operation {
private int index;
private int i;
private int j;
/**
* Constructs the swap operation exchanging the order of two variables v[i] and
* v[j].
*
* @param index index of the serialized constraint
* @param i index of the first variable (v[i])
* @param j index of the second variable (v[j])
*/
public Swap(int index, int i, int j) {
this.index = index;
this.i = i;
this.j = j;
}
@Override
public void applyTo(Network network) {
Serialized s = (Serialized) network.getConstraint(index);
int t = s.order[i];
s.order[i] = s.order[j];
s.order[j] = t;
}
@Override
public boolean isTaboo(Operation op) {
if (!(op instanceof Swap)) return false;
Swap swap = (Swap) op;
return index == swap.index && i == swap.i && j == swap.j;
}
}
@Override
protected void clearCondition() {
order = null;
}
@Override
protected Condition extractCondition() {
return new SerializedCondition();
}
@Override
public boolean isModified() {
return isModified(v);
}
private boolean satisfySequential(Trail trail) {
if (order == null) return true;
for (int k = 0; k < order.length - 1; k++) {
int i = order[k];
int j = order[k + 1];
IntDomain d0 = (IntDomain) v[i].getDomain();
IntDomain d1 = (IntDomain) v[j].getDomain();
int diffMin = d1.max() - a[i] + 1;
int diffMax = d0.min() + a[i] - 1;
d0 = d0.delete(diffMin, IntDomain.MAX_VALUE);
if (d0.isEmpty()) return false;
d1 = d1.delete(IntDomain.MIN_VALUE, diffMax);
if (d1.isEmpty()) return false;
v[i].updateDomain(d0, trail);
v[j].updateDomain(d1, trail);
}
return true;
}
private boolean satisfySerialized(Trail trail) {
for (int i = 0; i < v.length; i++) {
for (int j = 0; j < v.length; j++) {
if (i == j) continue;
IntDomain d0 = (IntDomain) v[i].getDomain();
IntDomain d1 = (IntDomain) v[j].getDomain();
int diffMin = d1.max() - a[i] + 1;
int diffMax = d1.min() + a[j] - 1;
if (diffMin <= diffMax) {
d0 = d0.delete(diffMin, diffMax);
if (d0.isEmpty()) return false;
v[i].updateDomain(d0, trail);
}
}
}
return true;
}
@Override
public boolean satisfy(Trail trail) {
if (!satisfySequential(trail)) return false;
return satisfySerialized(trail);
}
@Override
public String toString() {
return "Serialized(" + Constraint.toString(v) + "," + Constraint.toString(a) + ")";
}
}