All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.chocosolver.util.tools.VariableUtils Maven / Gradle / Ivy

There is a newer version: 4.10.17
Show newest version
/*
 * This file is part of choco-solver, http://choco-solver.org/
 *
 * Copyright (c) 2019, IMT Atlantique. All rights reserved.
 *
 * Licensed under the BSD 4-clause license.
 *
 * See LICENSE file in the project root for full license information.
 */
package org.chocosolver.util.tools;

import static java.util.Arrays.stream;

import java.util.Arrays;
import java.util.stream.IntStream;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.RealVar;
import org.chocosolver.solver.variables.Variable;

/**
 * 

* Project: choco-solver. * * @author Charles Prud'homme * @since 28/04/2016. */ public class VariableUtils { /** * @param vars array of variables * @return computes the bounds for the sum of vars */ public static int[] boundsForAddition(IntVar... vars) { long[] bounds = new long[2]; IntStream.range(0, vars.length).forEach(i -> { bounds[0] += vars[i].getLB(); bounds[1] += vars[i].getUB(); } ); return new int[]{MathUtils.safeCast(bounds[0]), MathUtils.safeCast(bounds[1])}; } /** * @param vars array of variables * @return computes the bounds for the sum of vars */ public static int[] boundsForScalar(IntVar[] vars, int[] coeffs) { long[] bounds = new long[2]; for (int i = 0; i < vars.length; i++) { int c = coeffs[i]; if(c >= 0) { bounds[0] += vars[i].getLB() * coeffs[i]; bounds[1] += vars[i].getUB() * coeffs[i]; }else{ bounds[0] += vars[i].getUB() * coeffs[i]; bounds[1] += vars[i].getLB() * coeffs[i]; } } return new int[]{MathUtils.safeCast(bounds[0]), MathUtils.safeCast(bounds[1])}; } /** * @param vars array of variables * @return computes the bounds for the sum of vars */ public static double[] boundsForAddition(RealVar... vars) { double[] bounds = new double[2]; for (int i = 0; i < vars.length; i++) { bounds[0] += vars[i].getLB(); bounds[1] += vars[i].getUB(); } return bounds; } private static int[] bound(long... values) { return new int[]{ MathUtils.safeCast(stream(values).min().getAsLong()), MathUtils.safeCast(stream(values).max().getAsLong()) }; } private static double[] bound(double... values) { return new double[]{stream(values).min().getAsDouble(), stream(values).max().getAsDouble()}; } /** * @param x a variable * @param y a variable * @return computes the bounds for "x - y" */ public static int[] boundsForSubstraction(IntVar x, IntVar y) { return new int[]{ MathUtils.safeCast(x.getLB() - y.getUB()), MathUtils.safeCast(x.getUB() - y.getLB())}; } /** * @param x a variable * @param y a variable * @return computes the bounds for "x - y" */ public static double[] boundsForSubstraction(RealVar x, RealVar y) { return new double[]{x.getLB() - y.getUB(), x.getUB() - y.getLB()}; } /** * @param x a variable * @param y a variable * @return computes the bounds for "x * y" */ public static int[] boundsForMultiplication(IntVar x, IntVar y) { return bound( x.getLB() * y.getLB(), x.getLB() * y.getUB(), x.getUB() * y.getLB(), x.getUB() * y.getUB() ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "x * y" */ public static double[] boundsForMultiplication(RealVar x, RealVar y) { return bound( x.getLB() * y.getLB(), x.getLB() * y.getUB(), x.getUB() * y.getLB(), x.getUB() * y.getUB() ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "x / y" */ public static int[] boundsForDivision(IntVar x, IntVar y) { int lx = x.getLB(); int ux = x.getUB(); int ly = y.getLB(); int uy = y.getUB(); if (ly == 0) { ly++; } if (uy == 0) { uy--; } if (ly < 0 && 0 < uy) { ly = -1; uy = 1; } return bound( lx / ly, lx / uy, ux / ly, ux / uy ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "x / y" */ public static double[] boundsForDivision(RealVar x, RealVar y) { return bound( x.getLB() / y.getLB(), x.getLB() / y.getUB(), x.getUB() / y.getLB(), x.getUB() / y.getUB() ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "x % y" */ public static int[] boundsForModulo(IntVar x, IntVar y) { long[] vals = new long[4]; if (y.isInstantiatedTo(0)) { vals[0] = Integer.MIN_VALUE; vals[1] = Integer.MAX_VALUE; vals[2] = 0; vals[3] = 0; } else { int yl = y.getLB(); int yu = y.getUB(); vals[0] = 0; vals[1] = 0; vals[2] = 0; if(yl >= 0){ vals[3] = yu-1; }else if(yu <= 0){ vals[3] = yl+1; }else{ vals[0] = Math.abs(yl)-1; vals[1] = Math.abs(yu)-1; vals[2] = -vals[0]; vals[3] = -vals[1]; } } return bound(vals); } /** * @param x a variable * @param y a variable (we consider that lb(y) >= 0 * @return computes the bounds for "x ^ y" */ public static int[] boundsForPow(IntVar x, IntVar y) { return bound(0, 1, MathUtils.pow(x.getLB(), y.getUB()), MathUtils.pow(x.getUB(), y.getUB()), MathUtils.pow(x.getLB() + 1, y.getUB()), MathUtils.pow(x.getUB() - 1, y.getUB()), MathUtils.pow(x.getLB(), Math.max(0, y.getUB() - 1)), MathUtils.pow(x.getUB(), Math.max(0, y.getUB() - 1)), MathUtils.pow(x.getLB() + 1, Math.max(0, y.getUB() - 1)), MathUtils.pow(x.getUB() - 1, Math.max(0, y.getUB() - 1)) ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "x ^ y" */ public static double[] boundsForPow(RealVar x, RealVar y) { return bound( Math.pow(x.getLB(), y.getLB()), Math.pow(x.getLB(), y.getUB()), Math.pow(x.getUB(), y.getLB()), Math.pow(x.getUB(), y.getUB()) ); } /** * @param x a variable * @param y a variable * @return computes the bounds for "atan2(x , y)" */ public static double[] boundsForAtan2(RealVar x, RealVar y) { return bound( Math.atan2(x.getLB(), y.getLB()), Math.atan2(x.getLB(), y.getUB()), Math.atan2(x.getUB(), y.getLB()), Math.atan2(x.getUB(), y.getUB()) ); } /** * @param vars array of variables * @return computes the bounds for the minimum among vars */ public static int[] boundsForMinimum(IntVar... vars) { int[] bounds = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE}; for (int i = 0; i < vars.length; i++) { bounds[0] = Math.min(bounds[0], vars[i].getLB()); bounds[1] = Math.min(bounds[1], vars[i].getUB()); } return bounds; } /** * @param vars array of variables * @return computes the bounds for the minimum among vars */ public static double[] boundsForMinimum(RealVar... vars) { double[] bounds = new double[]{Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}; for (int i = 0; i < vars.length; i++) { bounds[0] = Math.min(bounds[0], vars[i].getLB()); bounds[1] = Math.min(bounds[1], vars[i].getUB()); } return bounds; } /** * @param vars array of variables * @return computes the bounds for the maximum among vars */ public static int[] boundsForMaximum(IntVar... vars) { int[] bounds = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE}; for (int i = 0; i < vars.length; i++) { bounds[0] = Math.max(bounds[0], vars[i].getLB()); bounds[1] = Math.max(bounds[1], vars[i].getUB()); } return bounds; } /** * @param vars array of variables * @return computes the bounds for the maximum among vars */ public static double[] boundsForMaximum(RealVar... vars) { double[] bounds = new double[]{Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY}; for (int i = 0; i < vars.length; i++) { bounds[0] = Math.max(bounds[0], vars[i].getLB()); bounds[1] = Math.max(bounds[1], vars[i].getUB()); } return bounds; } /** * @param vars an array of variables * @return the variables' domain cardinality or {@link Integer#MAX_VALUE} if too large. */ public static long domainCardinality(IntVar... vars) { long card = 1; for (int i = 0; i < vars.length && card < Integer.MAX_VALUE; i++) { card *= vars[i].getDomainSize(); } return Math.min(Integer.MAX_VALUE, card); } /** * Compute the search space size * * @return search space size */ public static double searchSpaceSize(IntVar[] vars) { double size = 1; for (int i = 0; i < vars.length && size > 0; i++) { size *= vars[i].getDomainSize(); } if(size <= 0 || size == Double.POSITIVE_INFINITY) { size = Double.MAX_VALUE; } return size; } /** * @param x an int variable * @param y another int variable * @return true if the two domains intersect */ public static boolean intersect(IntVar x, IntVar y) { if (x.getLB() > y.getUB() || y.getLB() > x.getUB()) { return false; } if (x.hasEnumeratedDomain() && y.hasEnumeratedDomain()) { int ub = x.getUB(); for (int val = x.getLB(); val <= ub; val = x.nextValue(val)) { if (y.contains(val)) { return true; } } return false; } return true; } /** * Transform an array of int to an array of fixed IntVar * @param values array of ints * @param model model to create IntVar * @return */ public static IntVar[] toIntVar(Model model, int... values) { return Arrays.stream(values).mapToObj(model::intVar).toArray(IntVar[]::new); } /** * @param var a variable * @return true if the variable is a constant, based on its type, * false otherwise */ public static boolean isConstant(Variable var) { return (var.getTypeAndKind() & Variable.CSTE) != 0; } /** * @param var a variable * @return true if the variable is a view, based on its type, * false otherwise */ public static boolean isView(Variable var) { return (var.getTypeAndKind() & Variable.VIEW) != 0; } /** * @param var a variable * @return true if the variable is a real variable, based on its kind, * false otherwise */ public static boolean isReal(Variable var) { return (var.getTypeAndKind() & Variable.REAL) !=0; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy