org.xcsp.parser.callbacks.FeatureDisplayer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xcsp3-tools Show documentation
Show all versions of xcsp3-tools Show documentation
Java Tools for parsing XCSP3 instances, compiling JvCSP3 models, and checking solutions. For more information about XCSP3, follow www.xcsp.org
The newest version!
/*
* Copyright (c) 2016 XCSP3 Team ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.xcsp.parser.callbacks;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.xcsp.common.Types.TypeCtr;
import org.xcsp.common.Types.TypeExpr;
import org.xcsp.common.Types.TypeObjective;
import org.xcsp.common.Utilities;
import org.xcsp.parser.entries.XConstraints.XCtr;
import org.xcsp.parser.entries.XObjectives.OObjectiveExpr;
import org.xcsp.parser.entries.XObjectives.XObj;
import org.xcsp.parser.entries.XVariables.XVar;
import org.xcsp.parser.entries.XVariables.XVarInteger;
import org.xcsp.parser.entries.XVariables.XVarSymbolic;
/**
* This class allows us to display some general information about XCSP3 instances, such the number of variables, the
* number of constraints, the distribution of constraints, etc.
*
* @author Christophe Lecoutre
*/
public class FeatureDisplayer implements XCallbacks2 {
// ************************************************************************
// ***** Main (and other static stuff)
// ************************************************************************
private static final String INVALID = "invalid";
public static void main(String[] args) throws Exception {
boolean competitionMode = args.length > 0 && args[0].equals("-cm");
args = competitionMode ? Arrays.copyOfRange(args, 1, args.length) : args;
if (args.length != 1) {
System.out.println("Usage: " + FeatureDisplayer.class.getName() + " [-cm] ");
System.out.println("\tcm stands for competition mode");
} else
new FeatureDisplayer(competitionMode, args[0]);
}
// ************************************************************************
// ***** Implementation object (bridge pattern)
// ************************************************************************
private Implem implem = new Implem(this);
@Override
public Implem implem() {
return implem;
}
// ************************************************************************
// ***** Intern class
// ************************************************************************
/**
* This class allows us to count the number of occurrences of various keys.
*
* @param
* The type of keys
*/
private static class Repartitioner> {
private static final int FULL_DISPLAY_LIMIT = Integer.MAX_VALUE;
/** For each key, the number of occurrences is recorded (as value). */
private final Map repartition = new HashMap<>();
/** Sorted keys, when the repartition has been frozen. */
private List sortedKeys;
private String name;
private Repartitioner(String name) {
this.name = name;
}
private void clear() {
repartition.clear();
sortedKeys = null;
}
private void add(T value) {
Integer nb = repartition.get(value);
repartition.put(value, nb == null ? 1 : nb + 1);
}
private void freeze() {
Collections.sort(sortedKeys = new ArrayList(repartition.keySet()));
}
private T first() {
if (sortedKeys == null)
freeze();
return sortedKeys.size() == 0 ? null : sortedKeys.get(0);
}
private T last() {
if (sortedKeys == null)
freeze();
return sortedKeys.size() == 0 ? null : sortedKeys.get(sortedKeys.size() - 1);
}
private String pair(T k) {
return "{\"" + name + "\":" + (k instanceof Integer ? k.toString() : "\"" + k + "\"") + ",\"count\":" + repartition.get(k) + "}";
}
@Override
public String toString() {
if (sortedKeys == null)
freeze();
if (sortedKeys.size() <= FULL_DISPLAY_LIMIT)
return "[" + sortedKeys.stream().map(k -> pair(k)).collect(joining(",")) + "]";
String s1 = IntStream.range(0, FULL_DISPLAY_LIMIT / 2).mapToObj(i -> pair(sortedKeys.get(i))).collect(joining(","));
String s2 = IntStream.range(sortedKeys.size() - FULL_DISPLAY_LIMIT / 2, sortedKeys.size()).mapToObj(i -> pair(sortedKeys.get(i)))
.collect(joining(", "));
return "[" + s1 + ",\"...\"," + s2 + "]";
}
}
// ************************************************************************
// ***** Fields and Constructors
// ************************************************************************
private boolean competitionMode;
private int n, e;
private Repartitioner sizes = new Repartitioner<>("size");
private Repartitioner degrees = new Repartitioner<>("degree");
private Repartitioner arities = new Repartitioner<>("arity");
private Repartitioner constraints = new Repartitioner<>("type");
private XObj obj;
private int cnt;
private List ignoredFiles = new ArrayList<>();
private void reset() {
n = e = 0;
sizes.clear();
degrees.clear();
arities.clear();
constraints.clear();
obj = null;
}
private String field(String key, Object value) {
return ", " + "\"" + key + "\": "
+ (value instanceof Number || value instanceof Repartitioner || value instanceof Boolean ? value.toString() : "\"" + value.toString() + "\"");
}
@Override
public void loadInstance(String fileName, String... discardedClasses) throws Exception {
try {
cnt++;
if (cnt > 1)
System.out.print(",");
reset();
System.out.print("\n{\"instance\": \"" + fileName + "\"");
XCallbacks2.super.loadInstance(fileName, discardedClasses);
if (competitionMode) {
System.out.print(field("n", n) + field("e", e) + field("nDomainTypes", implem().cache4DomObject.size()));
System.out.print(field("domainSizes", sizes) + field("minDomSize", sizes.first()) + field("maxDomSize", sizes.last()));
System.out.print(field("variableDegrees", degrees) + field("minDegree", degrees.first()) + field("maxDegree", degrees.last()));
System.out.print(field("constraintArities", arities) + field("minConstrArity", arities.first()) + field("maxConstrArity", arities.last()));
int nIntension = constraints.repartition.getOrDefault(TypeCtr.intension, 0);
int nExtension = constraints.repartition.getOrDefault(TypeCtr.extension, 0);
System.out.print(field("globalConstraints", constraints) + field("nIntension", nIntension) + field("nExtension", nExtension));
boolean objVar = obj == null ? false : (obj.type == TypeObjective.EXPRESSION && ((OObjectiveExpr) obj).rootNode.getType() == TypeExpr.VAR);
System.out.print(field("hasObjective", (obj != null))
+ (obj != null ? field("objectiveType", (obj.minimize ? "min" : "max") + ' ' + (objVar ? "VAR" : obj.type)) : ""));
System.out.print("}");
}
} catch (Throwable e) {
if (e.getMessage().equals(INVALID))
System.out.print("\"pb\": \"Instance with some unimplemented method(s)\"");
else
System.out.print("\"pb\": \"Unable to be (totally) parsed\"");
// e.printStackTrace();
}
}
private void recursiveHandling(File file) throws Exception {
if (!file.exists())
Utilities.exit("The file " + file.getName() + " does not exist (or has not been found)");
if (file.isFile()) {
if (file.getName().endsWith(".xml") || file.getName().endsWith(".lzma"))
loadInstance(file.getAbsolutePath());
else
ignoredFiles.add(file.getName());
} else
for (File f : Stream.of(file.listFiles(f -> f.getName().endsWith(".xml") || f.getName().endsWith(".lzma") || file.isDirectory())).sorted()
.collect(toList()))
recursiveHandling(f);
}
/**
* Builds an object {@code InstanceInformation} that directly parses the XCSP3 file(s) from the specified name that
* denotes a file or a directory.
*
* @param competitionMode
* {@code true} if information is displayed to be used by tools of XCSP3 competitions
* @param name
* the name of a file or directory
* @throws Exception
*/
public FeatureDisplayer(boolean competitionMode, String name) throws Exception {
this.competitionMode = competitionMode;
Utilities.control(competitionMode, "For the moment, the competition mode is the only implemented mode");
ignoredFiles.clear();
implem().rawParameters(); // to keep initial formulations (no reformation being processed)
System.out.print("[");
recursiveHandling(new File(name));
System.out.println("\n]");
if (ignoredFiles.size() > 0)
System.err.print("Number of ignore files : " + ignoredFiles.size());
}
// ************************************************************************
// ***** Overridden Callback Functions
// ************************************************************************
@Override
public Object unimplementedCase(Object... objects) {
throw new RuntimeException(INVALID);
}
@Override
public void buildVarInteger(XVarInteger x, int minValue, int maxValue) {
sizes.add(maxValue - minValue + 1);
}
@Override
public void buildVarInteger(XVarInteger x, int[] values) {
sizes.add(values.length);
}
@Override
public void buildVarSymbolic(XVarSymbolic x, String[] values) {
// TODO : manage some specific information about symbolic variables
sizes.add(values.length);
}
@Override
public void loadVar(XVar v) {
n++;
degrees.add(v.degree);
XCallbacks2.super.loadVar(v);
}
@Override
public void loadCtr(XCtr c) {
e++;
arities.add(c.vars().length);
constraints.add(c.getType());
}
@Override
public void loadObj(XObj o) {
obj = o;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy