/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.optaplanner.core.impl.heuristic.selector.common.nearby; import java.util.Random; /** * {@code P(x) = 2/m - 2x/m²}. * <p> * Cumulative probability: {@code F(x) = x(2m - x)/m²}. * <p> * Inverse cumulative probability: {@code F(p) = m(1 - (1 - p)^(1/2))}. */ public class LinearDistributionNearbyRandom implements NearbyRandom { protected final int sizeMaximum; public LinearDistributionNearbyRandom(int sizeMaximum) { this.sizeMaximum = sizeMaximum; if (sizeMaximum < 1) { throw new IllegalArgumentException("The maximum (" + sizeMaximum + ") must be at least 1."); } } @Override public int nextInt(Random random, int nearbySize) { int m = sizeMaximum <= nearbySize ? sizeMaximum : nearbySize; double p = random.nextDouble(); double x = m * (1.0 - Math.sqrt(1.0 - p)); int next = (int) x; // Due to a rounding error it might return m if (next >= m) { next = m - 1; } return next; } @Override public int getOverallSizeMaximum() { return sizeMaximum; } }