/** {@inheritDoc} */
  @Override
  public Vector get(Particle particle) {
    Vector localGuide = (Vector) particle.getLocalGuide();
    Vector globalGuide = (Vector) particle.getGlobalGuide();

    PSO pso = (PSO) AbstractAlgorithm.get();
    List<Entity> positions = getRandomParentEntities(pso.getTopology());

    // select three random individuals, all different and different from particle
    ProbabilityDistributionFuction pdf = new UniformDistribution();

    Vector position1 = (Vector) positions.get(0).getCandidateSolution();
    Vector position2 = (Vector) positions.get(1).getCandidateSolution();
    //        Vector position3 = (Vector) positions.get(2).getContents();

    Vector.Builder builder = Vector.newBuilder();
    for (int i = 0; i < particle.getDimension(); ++i) {
      double r = pdf.getRandomNumber(0, 1);
      double attractor = r * localGuide.doubleValueOf(i) + (1 - r) * globalGuide.doubleValueOf(i);
      double stepSize =
          this.rand3.getRandomNumber(0, 1)
              * (position1.doubleValueOf(i) - position2.doubleValueOf(i));

      if (this.rand2.getRandomNumber(0, 1) > this.crossoverProbability.getParameter()) {
        builder.add(attractor + stepSize);
      } else {
        builder.add(((Vector) particle.getPosition()).doubleValueOf(i)); // position3.getReal(i));
      }
    }
    return builder.build();
  }
  @Override
  public Vector get(Particle particle) {
    Vector localGuide = (Vector) particle.getLocalGuide();
    Vector globalGuide = (Vector) particle.getGlobalGuide();

    Vector.Builder builder = Vector.newBuilder();
    for (int i = 0; i < particle.getDimension(); ++i) {
      if (this.uniform.getRandomNumber(0, 1) < 0.5) {
        builder.add(localGuide.doubleValueOf(i));
      } else {
        // double tmp1 = cognitive.getParameter();
        // double tmp2 = social.getParameter();

        double sigma = Math.abs(localGuide.doubleValueOf(i) - globalGuide.doubleValueOf(i));
        // according to Kennedy
        double mean = (localGuide.doubleValueOf(i) + globalGuide.doubleValueOf(i)) / 2;
        // andries proposal: double mean = (tmp1*personalBestPosition.getReal(i) +
        // tmp2*nBestPosition.getReal(i)) / (tmp1+tmp2);

        builder.add(this.randomDistribution.getRandomNumber(mean, sigma));
      }
    }
    return builder.build();
  }