package org.avmframework;

import org.avmframework.initialization.Initializer;
import org.avmframework.localsearch.LocalSearch;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
import org.avmframework.variable.AtomicVariable;
import org.avmframework.variable.Variable;
import org.avmframework.variable.VectorVariable;

public class AVM {

    protected LocalSearch localSearch;
    protected TerminationPolicy tp;
    protected Initializer initializer, restarter;

    protected Monitor monitor;
    protected ObjectiveFunction objFun;
    protected Vector vector;

    public AVM(LocalSearch localSearch, TerminationPolicy tp, Initializer initializer) {
        this(localSearch, tp, initializer, initializer);
    }

    public AVM(LocalSearch localSearch, TerminationPolicy tp, Initializer initializer, Initializer restarter) {
        this.localSearch = localSearch;
        this.tp = tp;
        this.initializer = initializer;
        this.restarter = restarter;
    }

    public Monitor search(Vector vector, ObjectiveFunction objFun) {
        // set up the monitor
        this.monitor = new Monitor(tp);

        // set up the objective function
        this.objFun = objFun;
        objFun.setMonitor(monitor);

        // initialize the vector
        this.vector = vector;
        initializer.initialize(vector);
        if (vector.size() == 0) {
            throw new EmptyVectorException();
        }

        try {
            // the loop terminates when a TerminationException is thrown
            while (true) {

                // search over the vector's variables
                vectorVariableSearch(vector);

                // restart the search
                monitor.observeRestart();
                restarter.initialize(vector);
            }

        } catch (TerminationException e) {
            // the search has ended
            monitor.observeTermination();
        }

        return monitor;
    }

    protected void variableSearch(Variable var) throws TerminationException {
        if (var instanceof AtomicVariable) {
            atomicVariableSearch((AtomicVariable) var);
        } else if (var instanceof VectorVariable) {
            vectorVariableSearch((VectorVariable) var);
        }
    }

    protected void atomicVariableSearch(AtomicVariable atomicVar) throws TerminationException {
        localSearch.search(atomicVar, vector, objFun);
    }

    protected void vectorVariableSearch(VectorVariable vectorVar) throws TerminationException {
        ObjectiveValue lastImprovement = objFun.evaluate(vector);
        int nonImprovement = 0;

        while (nonImprovement < vectorVar.size()) {

            // alternate through the variables
            int variableIndex = 0;
            while (variableIndex < vectorVar.size() && nonImprovement < vectorVar.size()) {

                // perform a local search on this variable
                Variable var = vectorVar.getVariable(variableIndex);
                variableSearch(var);

                // check if the current objective value has improved on the last
                ObjectiveValue current = objFun.evaluate(vector);
                if (current.betterThan(lastImprovement)) {
                    lastImprovement = current;
                    nonImprovement = 0;
                } else {
                    nonImprovement++;
                }

                variableIndex++;
            }
        }
    }
}

@@ -1642,38 +1642,43 @@
                 
-vector
+alternating
 VariableSearch(v
@@ -2013,476 +2013,19 @@
 oid 
-variableSearch(Variable var) throws TerminationException %7B%0A        if (var instanceof AtomicVariable) %7B%0A            atomicVariableSearch((AtomicVariable) var);%0A        %7D else if (var instanceof VectorVariable) %7B%0A            vectorVariableSearch((VectorVariable) var);%0A        %7D%0A    %7D%0A%0A    protected void atomicVariableSearch(AtomicVariable atomicVar) throws TerminationException %7B%0A        localSearch.search(atomicVar, vector, objFun);%0A    %7D%0A%0A    protected void vector
+alternating
 Vari
@@ -3002,24 +3002,24 @@
           %7D%0A
-
         %7D%0A  
@@ -3021,11 +3021,695 @@
  %7D%0A    %7D
+%0A%0A    protected void variableSearch(Variable var) throws TerminationException %7B%0A        if (var instanceof AtomicVariable) %7B%0A            atomicVariableSearch((AtomicVariable) var);%0A        %7D else if (var instanceof VectorVariable) %7B%0A            vectorVariableSearch((VectorVariable) var);%0A        %7D%0A    %7D%0A%0A    protected void atomicVariableSearch(AtomicVariable atomicVar) throws TerminationException %7B%0A        localSearch.search(atomicVar, vector, objFun);%0A    %7D%0A%0A    protected void vectorVariableSearch(VectorVariable vectorVar) throws TerminationException %7B%0A        // TODO%0A        // try increase and decrease size moves%0A        %0A        alternatingVariableSearch(vectorVar);%0A    %7D
 %0A%7D%0A

Split out avm from rest of vector var search