Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setting decision variable for custom operators #174

Closed
Onnene opened this issue Apr 26, 2018 · 4 comments
Closed

setting decision variable for custom operators #174

Onnene opened this issue Apr 26, 2018 · 4 comments
Labels

Comments

@Onnene
Copy link

Onnene commented Apr 26, 2018

Hello @dhadka,

Question 1
How can I set a custom decision variable in the evaluate method?

public void evaluate(Solution solution) {

    double[] vars = EncodingUtils.getReal(solution); // Works for real decision variables 

    customDecisionVariable result = new customDecisionVariable(); // will this work for custom variables?

    for (int i = 0; i < getNumberOfVariables(); i++) {
            result = (customDecisionVariable) solution.getVariable(i);
     }
   ...
   ...
   ...
}

Question 2:
How do I can I print out the final set of results? I try the line of code below but I only get a representative string and not the variable itself. System.out.print(result.get(0).getVariable(0).toString());

Question 3:
Is it fine to use a built-in initialization like RandomInitialization for a custom problem? e.g.
Initialization initialization = new RandomInitialization(problem, x);// x = population size

Thank you for your time.

@dhadka
Copy link
Member

dhadka commented Apr 26, 2018

  1. Yes, you just cast it to the type you need:
    CustomDecisionVariable var = (CustomDecisionVariable)solution.getVariable(0);
  1. You would need something that converts the variables to a string representation. For example, here's one that supports real, binary, and permutations.
	private String encode(Variable variable) throws IOException {
		StringBuilder sb = new StringBuilder();
		
		if (variable instanceof RealVariable) {
			RealVariable rv = (RealVariable)variable;
			sb.append(rv.getValue());
		} else if (variable instanceof BinaryVariable) {
			BinaryVariable bv = (BinaryVariable)variable;
			
			for (int i=0; i<bv.getNumberOfBits(); i++) {
				sb.append(bv.get(i) ? "1" : "0");
			}
		} else if (variable instanceof Permutation) {
			Permutation p = (Permutation)variable;

			for (int i=0; i<p.size(); i++) {
				if (i > 0) {
					sb.append(',');
				}
				
				sb.append(p.get(i));
			}
		} else {
			throw new IOException("type not supported");
		}
		
		return sb.toString();
	}

Then call System.out.println(encode(result.get(0).getVariable(0)));. You would need to add in else if conditions for any other types you use.

  1. Yes, RandomInitialization is designed to work with custom problems and custom decision variables. When creating a new decision variable type, you will need to define the randomize() method. This method should assign the value of that variable randomly. Take a look at https://github.com/MOEAFramework/MOEAFramework/tree/master/src/org/moeaframework/core/variable to see how the built-in decision variables are implemented.

@Onnene
Copy link
Author

Onnene commented Apr 27, 2018

@dhadka

Sorry but I have 2 more questions

  1. After declaring the initialization operator for example Initialization initialization = new RandomInitialization(problem, 50);, do I need to add it to the Executor() if yes how can I do that? The other part of this question is if I use a .withProperty(populationSize = 50) in the executor is that an equivalent way of using the initialization?

  2. I am using the NSGA-II on a problem with 1 decision variable and 2 objectives, also I am using an external simulation as the evaluation mechanism inside the evaluate(). For the purpose of a very quick run and observation, I set the .withMaxEvaluations to just 1 (population is set to 1 as well), my understanding is that the decision variable should be evaluated for each objective once, but my observation is that the algorithm calls the simulation many more times because the simulation is running longer than normal when in stand-alone mode. Please throw more light on how the evaluation works with NSGA-II, is there a minimum or default number of evaluations that the algorithm must run, also is there a default populationSize it works with such that if a value below the minimum is given, it uses that default value.

Thanks for the clarification, I am trying to understand the mechanisms of the framework.

@dhadka
Copy link
Member

dhadka commented Apr 27, 2018

  1. The preferred way is to use .withProperty("populationSize", 50). There is currently no way to directly pass an initialization operator through the Executor...if you needed to, you would need to create the algorithm explicitly using its constructor.

  2. The evaluate(Solution solution) method in your problem class will be called once for each solution generated. If you set max evaluations to 1 and the population size to 1, then you should only have one solution evaluated. I suspect if you're seeing more evaluations taking place that it's not setting the population size correctly. See the code below for a simple test.

    There are some cases where we will exceed the max evaluations. The most common reasons are:

    • Max evaluations is not a multiple of the population size. For example, if you set the population size to 100 and max evaluations to 1, you will likely end up evaluating 100 solutions because it executes one iteration which generates 100 solutions.

    • Some algorithms may place additional restrictions on the population size, such as requiring an even sized population.

public class TestEvaluate {
	
	public static int callsToEvaluate = 0;
	
	public static class TestProblem extends AbstractProblem {
		public TestProblem() {
			super(1, 1);
		}

		@Override
		public void evaluate(Solution solution) {
			callsToEvaluate++;
		}

		@Override
		public Solution newSolution() {
			Solution solution = new Solution(1, 1);
			solution.setVariable(0, EncodingUtils.newReal(0.0, 1.0));
			return solution;
		}
	}

	public static void main(String[] args) {
		NondominatedPopulation result = new Executor()
				.withProblemClass(TestProblem.class)
				.withAlgorithm("NSGAII")
				.withMaxEvaluations(1)
				.withProperty("populationSize", 1)
				.run();
		
		System.out.println("Evaluate called " + callsToEvaluate + " times...");
	}

}

@github-actions
Copy link

This is an automated message. This issue is flagged as stale and will be closed in 7 days. If you feel this issue is still relevant, leave a comment to keep the issue open. Please also consider contributing a fix for the issue.

@github-actions github-actions bot added the Stale label Nov 18, 2022
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Nov 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants