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

org.chocosolver.solver.expression.continuous.arithmetic.UnCArExpression 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) 2023, 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.solver.expression.continuous.arithmetic;

import org.chocosolver.memory.IStateDouble;
import org.chocosolver.solver.ICause;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.exception.ContradictionException;
import org.chocosolver.solver.variables.RealVar;
import org.chocosolver.util.objects.RealInterval;
import org.chocosolver.util.tools.RealUtils;

import java.util.List;
import java.util.TreeSet;

/**
 * Unary arithmetic continuous expression
 * 

* Project: choco-solver. * * @author Charles Prud'homme * @since 28/04/2016. */ public class UnCArExpression implements CArExpression { /** * The model in which the expression is declared */ Model model; /** * Lazy creation of the underlying variable */ RealVar me = null; /** * Operator of the arithmetic expression */ Operator op; /** * The expression this expression relies on */ private final CArExpression e; IStateDouble l; IStateDouble u; /** * Builds a unary expression * * @param op operator * @param exp an continuous arithmetic expression */ public UnCArExpression(Operator op, CArExpression exp) { this.op = op; this.e = exp; this.model = e.getModel(); } @Override public Model getModel() { return model; } @Override public RealVar realVar(double p) { if (me == null) { RealVar v = e.realVar(p); switch (op) { case NEG: me = model.realVar(-v.getUB(), -v.getLB(), p); model.realIbexGenericConstraint("{0}=-{1}", me, v).post(); break; case ABS: me = model.realVar(0.0, Math.max(Math.abs(v.getLB()), Math.abs(v.getUB())) , p); model.realIbexGenericConstraint("{0}=abs({1})", me, v).post(); break; case EXP: me = model.realVar(Math.min(Math.exp(v.getLB()), Math.exp(v.getUB())), Math.max(Math.exp(v.getLB()), Math.exp(v.getUB())), p); model.realIbexGenericConstraint("{0}=exp({1})", me, v).post(); break; case LN: me = model.realVar(Math.min(Math.log(v.getLB()), Math.log(v.getUB())), Math.max(Math.log(v.getLB()), Math.log(v.getUB())), p); model.realIbexGenericConstraint("{0}=ln({1})", me, v).post(); break; case SQR: RealInterval res2 = RealUtils.iPower(v, 2); me = model.realVar(res2.getLB(), res2.getUB(), p); model.realIbexGenericConstraint("{0}={1}^2", me, v).post(); break; case SQRT: RealInterval res2_ = RealUtils.iRoot(v, 2); me = model.realVar(res2_.getLB(), res2_.getUB(), p); model.realIbexGenericConstraint("{0}=sqrt({1})", me, v).post(); break; case CUB: RealInterval res3 = RealUtils.iPower(v, 2); me = model.realVar(res3.getLB(), res3.getUB(), p); model.realIbexGenericConstraint("{0}={1}^3", me, v).post(); break; case CBRT: RealInterval res3_ = RealUtils.iRoot(v, 3); me = model.realVar(res3_.getLB(), res3_.getUB(), p); model.realIbexGenericConstraint("{0}={1}^(1/3)", me, v).post(); break; case COS: me = model.realVar(-1.0, 1.0, p); model.realIbexGenericConstraint("{0}=cos({1})", me, v).post(); break; case SIN: me = model.realVar(-1.0, 1.0, p); model.realIbexGenericConstraint("{0}=sin({1})", me, v).post(); break; case TAN: me = model.realVar(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=tan({1})", me, v).post(); break; case ACOS: me = model.realVar(0.0, Math.PI, p); model.realIbexGenericConstraint("{0}=acos({1})", me, v).post(); break; case ASIN: me = model.realVar(-Math.PI / 2, Math.PI / 2, p); model.realIbexGenericConstraint("{0}=asin({1})", me, v).post(); break; case ATAN: me = model.realVar(-Math.PI / 2, Math.PI / 2, p); model.realIbexGenericConstraint("{0}=atan({1})", me, v).post(); break; case COSH: me = model.realVar(0.0, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=cosh({1})", me, v).post(); break; case SINH: me = model.realVar(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=sinh({1})", me, v).post(); break; case TANH: me = model.realVar(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=tanh({1})", me, v).post(); break; case ACOSH: me = model.realVar(0.0, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=acosh({1})", me, v).post(); break; case ASINH: me = model.realVar(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=asinh({1})", me, v).post(); break; case ATANH: me = model.realVar(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, p); model.realIbexGenericConstraint("{0}=atanh({1})", me, v).post(); break; default: throw new UnsupportedOperationException("Unary arithmetic expressions does not support "+op.name()); } } return me; } @Override public void tighten() { RealInterval res; switch (op) { case COS: res = RealUtils.cos(e); break; case SIN: res = RealUtils.sin(e); break; case NEG: res = new RealIntervalConstant(-e.getUB(), -e.getLB()); break; case SQR: res = RealUtils.iPower(e, 2); break; case SQRT: res = RealUtils.iRoot(e, 2); break; case CUB: res = RealUtils.iPower(e, 3); break; case CBRT: res = RealUtils.iRoot(e, 3); break; case ABS: double linf = e.getLB(); double lsup = e.getUB(); if(lsup < 0.){ res = new RealIntervalConstant(-lsup, -linf); }else if (linf < 0.){ res = new RealIntervalConstant(0., Math.max(-linf, lsup)); }else{ res = new RealIntervalConstant(linf, lsup); } break; case EXP: case LN: case TAN: case ACOS: case ASIN: case ATAN: case COSH: case SINH: case TANH: case ACOSH: case ASINH: case ATANH: default: throw new UnsupportedOperationException("Equation does not support " + op.name()+". Consider using Ibex instead."); } l.set(res.getLB()); u.set(res.getUB()); } @Override public void project(ICause cause) throws ContradictionException { RealInterval res; switch (op) { case COS: res = RealUtils.acos_wrt(this, e); break; case SIN: res = RealUtils.asin_wrt(this, e); break; case NEG: res = new RealIntervalConstant(-this.getUB(), -this.getLB()); break; case SQR: res = RealUtils.iRoot(this, 2, e); break; case SQRT: res = RealUtils.iPower(this, 2); break; case CUB: res = RealUtils.iRoot(this, 3, e); break; case CBRT: res = RealUtils.iPower(this, 3); break; case ABS: res = new RealIntervalConstant(-this.getUB(), this.getUB()); break; case EXP: case LN: case TAN: case ACOS: case ASIN: case ATAN: case COSH: case SINH: case TANH: case ACOSH: case ASINH: case ATANH: default: throw new UnsupportedOperationException("Equation does not support " + op.name()+". Consider using Ibex instead."); } e.intersect(res, cause); } @Override public void collectVariables(TreeSet set) { e.collectVariables(set); } @Override public void subExps(List list) { e.subExps(list); list.add(this); } @Override public boolean isolate(RealVar var, List wx, List wox) { boolean dependsOnX = e.isolate(var, wx, wox); if (dependsOnX){ wx.add(this); } else{ wox.add(this); } return dependsOnX; } @Override public void init() { if(l == null && u == null) { l = model.getEnvironment().makeFloat(Double.NEGATIVE_INFINITY); u = model.getEnvironment().makeFloat(Double.POSITIVE_INFINITY); } e.init(); } @Override public double getLB() { return l.get(); } @Override public double getUB() { return u.get(); } @Override public void intersect(double lb, double ub, ICause cause) throws ContradictionException { if (lb > getLB()) { l.set(lb); } if (ub < getUB()) { u.set(ub); } if (getLB() > getUB()) { model.getSolver().throwsException(cause, null, ""); } } @Override public String toString() { return op.name() + "(" + e.toString() + ")"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy