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

org.chocosolver.solver.search.strategy.strategy.StrategiesSequencer Maven / Gradle / Ivy

/*
 * 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.search.strategy.strategy;

import org.chocosolver.memory.IEnvironment;
import org.chocosolver.memory.IStateInt;
import org.chocosolver.solver.search.strategy.decision.Decision;
import org.chocosolver.solver.variables.Variable;
import org.chocosolver.util.tools.ArrayUtils;

/**
 * A StrategiesSequencer is class for AbstractStrategy composition.
 * this is created with a list of AbstractStrategy, and calling
 * getDecision() retrieves the current active AbstractStrategy and
 * calls the delegate getDecision() method.
 * 
* A AbstractStrategy becomes "inactive" when no more decision can be computed, * ie every decisions have been computed and used. *
* * @author Charles Prud'homme * @author Guillaume Le Louët * @since 5 juil. 2010 */ @SuppressWarnings({"UnusedDeclaration", "ForLoopReplaceableByForEach"}) public class StrategiesSequencer extends AbstractStrategy { private final AbstractStrategy[] strategies; private final IStateInt index; @SuppressWarnings("unchecked") private static V[] make(AbstractStrategy[] strategies) { V[] vars = strategies[0].vars.clone(); for (int i = 1; i < strategies.length; i++) { vars = ArrayUtils.append(vars, strategies[i].vars); } return vars; } public StrategiesSequencer(IEnvironment environment, AbstractStrategy[] strategies) { super(make(strategies)); index = environment.makeInt(0); this.strategies = strategies; } @SafeVarargs public StrategiesSequencer(AbstractStrategy... strategies) { super(make(strategies)); index = null; this.strategies = strategies; } @Override public boolean init() { boolean ok = true; for (int i = 0; i < strategies.length; i++) { ok &= strategies[i].init(); } return ok; } @Override public void remove() { for (int i = 0; i < strategies.length; i++) { strategies[i].remove(); } } @Override public Decision computeDecision(U variable) { if (variable == null || variable.isInstantiated()) { return null; } int idx = (index==null)?0:index.get(); Decision decision = null; while (decision == null && idx < strategies.length) { if (contains(strategies[idx].vars, variable)) { decision = strategies[idx].computeDecision(variable); } idx++; } return decision; } private static boolean contains(Variable[] vars, Variable variable) { for (Variable v : vars) { if (v.equals(variable)) { return true; } } return false; } /** * {@inheritDoc} * Iterates over the declared sub-strategies and gets the overall current decision. */ @Override public Decision getDecision() { int idx = (index==null)?0:index.get(); Decision decision = strategies[idx].getDecision(); while (decision == null && idx < strategies.length - 1) { decision = strategies[++idx].getDecision(); } if(index!=null){ index.set(idx); } return decision; } /** * {@inheritDoc} * This is based on the print() method of every sub-strategies. */ @Override public String toString() { StringBuilder st = new StringBuilder("Sequence of:\n"); for (int i = 0; i < strategies.length; i++) { st.append("\t").append(strategies[i].toString()).append("\n"); } return st.toString(); } }