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

com.exigen.ie.constrainer.GoalFloatFastMinimize Maven / Gradle / Ivy

package com.exigen.ie.constrainer;
import com.exigen.ie.constrainer.impl.ConstraintFloatExpLessValue;
import com.exigen.ie.tools.Log;

///////////////////////////////////////////////////////////////////////////////
/*
 * Copyright Exigen Group 1998, 1999, 2000
 * 320 Amboy Ave., Metuchen, NJ, 08840, USA, www.exigengroup.com
 *
 * The copyright to the computer program(s) herein
 * is the property of Exigen Group, USA. All rights reserved.
 * The program(s) may be used and/or copied only with
 * the written permission of Exigen Group
 * or in accordance with the terms and conditions
 * stipulated in the agreement/contract under which
 * the program(s) have been supplied.
 */
///////////////////////////////////////////////////////////////////////////////

/**
 * An implementation of a {@link Goal} that finds a solution which minimizes
 * a constrained integer variable called the "cost".
 * 

* This goal uses the search goal provided by the caller, and expects * that this goal instantiates the cost every time when a solution is found. * * To search for a solution which provides the minimal cost, * GoalFloatFastMinimize finds a solution, posts the constraint that the * cost variable should be less then the found cost and continues the search. *

* In contrast with GoalFloatMinimize, when a solution is found GoalFloatFastMinimize * does not restore all decision variables, but continues the search just with * a more strict constraint to the cost variable. * * When there are no solutions anymore, the latest found solution is the optimal one. *

* By default, GoalFloatFastMinimize calculates the optimal solution twice. * * If the caller's search goal saves every found solution itself, the caller may * specify the mode "goal_saves_solution" to prevent the duplicate calculation * at the end of the search. * * @see GoalFloatMinimize */ public class GoalFloatFastMinimize extends GoalImpl { private FloatExp _cost; private double _best_cost_min; private double _best_cost_max; private Goal _goal_find_solution; private ConstraintFloatExpLessValue _constraint_limit_cost; private int _number_of_solutions; private boolean _trace; private Object _client_tracer; private boolean _goal_saves_solution; private ChoicePointLabel _rootLabel; private double _cost_step; /** * Constructor with a given generation goal, cost expression, trace flag, * and save_solution flag. * * Use "goal" to minimize "cost". * * If ("trace" = true), after each successful iteration, solution# and the * cost value will be printed. * * If ("goal_saves_solution" = true), the optimal solution (if any) * would not be calculated twice: it means the "goal" should save * the value of decision variables and the cost. */ public GoalFloatFastMinimize(Goal goal, FloatExp cost, double costStep) { super(cost.constrainer(),""); _goal_find_solution = goal; _cost = cost; _constraint_limit_cost = new ConstraintFloatExpLessValue(_cost, _cost.max()); _number_of_solutions = 0; _trace = false; _client_tracer = null; _goal_saves_solution = false; _rootLabel = constrainer().createChoicePointLabel(); _cost_step = Math.abs(costStep); } public void traceFlag(boolean flag) { _trace = flag; } public void clientTracer(Object tracer) { _client_tracer = tracer; } public void savesSolutionFlag(boolean flag) { _goal_saves_solution = flag; } /** * The implementation of the search algorithm. *

* It sets labeled choice point from the goals FindAndImprove and AnalyzeAndSet. *
* FindAndImprove is a loop that finds an optimal solution (if any solution exists). * FindAndImprove always fails (the _cost can not be improved infinitely). *
* AnalyzeAndSet do further job: *

    *
  • Checks if any solution was found and fails if not. *
  • If _goal_save_solution is true then it finishes. *
  • Otherwise the constraint _cost==_best_cost is posted and _goal_find_solution * is executed to instantiate the optimal solution. *
*/ public Goal execute() throws Failure { return new GoalOr(new FindAndImprove(constrainer()), new AnalyzeAndSet(constrainer()), _rootLabel ); } /** * Returns a String representation of this goal. */ public String toString() { return "Use "+_goal_find_solution.name()+ " to minimize("+_cost.name()+")"; } /** * Activates _constraint_limit_cost and organizes the optimization loop * using _goal_find_solution and GoalBacktrack. */ class FindAndImprove extends GoalImpl { FindAndImprove(Constrainer C) { super(C,"FindAndImprove"); } public Goal execute() throws Failure { // activate _constraint_limit_cost _constraint_limit_cost.resetValue(_cost.max()); _constraint_limit_cost.post(); return new GoalAnd( _goal_find_solution, new GoalBacktrack(constrainer()) ); } }; /** * This goal is executed after an optimal solution is found or no solution exists. * The constrainer state is as it was before GoalFloatFastMinimize.execute(). */ class AnalyzeAndSet extends GoalImpl { AnalyzeAndSet(Constrainer C) { super(C,"AnalyzeAndSet"); } public Goal execute() throws Failure { // check if the any solution was found if (_number_of_solutions <= 0) constrainer().fail(); //Debug.on();Debug.print("Found solution with the cost = "+_best_cost);Debug.off(); if(_goal_saves_solution) return null; // post the constraint '_cost == _best_cost' double eps = 1e-6; //??? double search_cost_min = _best_cost_min - eps; double search_cost_max = _best_cost_max + eps; _cost.moreOrEqual(search_cost_min).post(); _cost.lessOrEqual(search_cost_max).post(); // find the optimal solution return _goal_find_solution; } } /** * This goal backtracks while _cost GE _best_cost. *
* Then it sets _best_cost as a new value in _constraint_limit_cost. * In this case the search continues with the new limit on the cost. *
* This goal fails if backtrack can not satisfy _cost LT _best_cost. * This means that the is no better solution. * In this case GoalAnalyzeAndSet will be executed as an alternate * goal for the "_rootLabel" choice point. */ class GoalBacktrack extends GoalImpl { public GoalBacktrack(Constrainer c) { super(c,"GoalBacktrack"); } /** * Called when a solution (first or next) is found. * Saves the current value of the cost, increments _number_of_solutions, * and performs tracing. */ void fixFoundSolution() { _best_cost_min = _cost.min(); _best_cost_max = _cost.max(); _number_of_solutions++; if (_trace) { Log.info("Solution "+_number_of_solutions+": cost"+_cost.domainToString()); } if (_client_tracer != null) { Log.info(_client_tracer.toString()); } } /** * violated() for the constraint: _cost <= _best_cost - _cost_step */ boolean violated() { return _cost.min() > _best_cost_min - _cost_step; } public Goal execute() throws Failure { fixFoundSolution(); // backtrack while _cost >= _best_cost ChoicePointLabel lbl = constrainer().currentChoicePointLabel(); while( ((lbl==null )||(!lbl.equals(_rootLabel))) && violated() ) { if(!constrainer().backtrack()) throw new RuntimeException("Internal error in "+this); if (_trace) { Log.info(" Backtrack: cost"+_cost.domainToString()+" best_cost_min="+_best_cost_min); } } // fail if still violated if(violated()) constrainer().fail("GoalBacktrack"); // set _best_cost as a new limit in _constraint_limit_cost _constraint_limit_cost.resetValue(_best_cost_min - _cost_step); return null; } } // GoalBacktrack } // ~GoalFloatFastMinimize




© 2015 - 2024 Weber Informatics LLC | Privacy Policy