it.unibo.alchemist.model.sapere.actions.LsaRandomNeighborAction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alchemist-incarnation-sapere Show documentation
Show all versions of alchemist-incarnation-sapere Show documentation
Alchemist incarnation for SAPERE
/*
* Copyright (C) 2010-2023, Danilo Pianini and contributors
* listed, for each module, in the respective subproject's build.gradle.kts file.
*
* This file is part of Alchemist, and is distributed under the terms of the
* GNU General Public License, with a linking exception,
* as described in the file LICENSE in the Alchemist distribution's top directory.
*/
package it.unibo.alchemist.model.sapere.actions;
import it.unibo.alchemist.model.sapere.dsl.ITreeNode;
import it.unibo.alchemist.model.Reaction;
import it.unibo.alchemist.model.sapere.molecules.LsaMolecule;
import org.apache.commons.math3.random.RandomGenerator;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import it.unibo.alchemist.model.Context;
import it.unibo.alchemist.model.Environment;
import it.unibo.alchemist.model.sapere.ILsaMolecule;
import it.unibo.alchemist.model.sapere.ILsaNode;
import it.unibo.alchemist.model.maps.MapEnvironment;
import it.unibo.alchemist.model.Node;
import it.unibo.alchemist.model.Route;
import java.util.List;
/**
*/
public class LsaRandomNeighborAction extends LsaStandardAction {
private static final long serialVersionUID = -7128058274012426458L;
private final Environment, ?> environment;
private final MapEnvironment, ?, ?> menv;
private final boolean initO, initD, initNeigh, initRoute, mapEnv;
@SuppressFBWarnings(
value = "SE_BAD_FIELD",
justification = "All provided RandomGenerator implementations are actually Serializable"
)
private final RandomGenerator randomEngine;
/**
* Builds a new action in a neighborhood. es: +<id,X,n> This class extend
* LsaAbstractAction.
*
* @param environment
* The environment to use
* @param node
* The source node
* @param molecule
* The IlsaMolecule instance you want to add to neighbor lsa
* space.
* @param randomGenerator
* the random engine
*
*/
@SuppressWarnings("unchecked")
public LsaRandomNeighborAction(
final ILsaNode node,
final ILsaMolecule molecule,
final Environment, ?> environment,
final RandomGenerator randomGenerator
) {
super(molecule, node);
final String molString = molecule.toString();
initO = molString.contains(LsaMolecule.SYN_O);
initD = molString.contains(LsaMolecule.SYN_D);
initNeigh = molString.contains(LsaMolecule.SYN_NEIGH);
initRoute = molString.contains(LsaMolecule.SYN_ROUTE);
this.environment = environment;
mapEnv = environment instanceof MapEnvironment;
menv = mapEnv ? (MapEnvironment, ?, ?>) this.environment : null;
randomEngine = randomGenerator;
}
/**
* {@inheritDoc}
*/
@Override
public LsaRandomNeighborAction cloneAction(
final Node> node,
final Reaction> reaction
) {
return new LsaRandomNeighborAction((ILsaNode) node, getMolecule(), getEnvironment(), randomEngine);
}
/**
* {@inheritDoc}
*/
@Override
public void execute() {
final List nodes = getNodes();
if (!nodes.isEmpty()) {
final ITreeNode> nodeId = getMatches().get(LsaMolecule.SYN_SELECTED);
if (nodeId == null) {
/*
* Just choose a random neighbor among those valid
*/
final ILsaNode node = nodes.get(Math.abs(randomEngine.nextInt() % nodes.size()));
setSynthectics(node);
setConcentration(node);
} else {
/*
* There was an operation that fixed a single neighbor
*/
final int id = ((Double) nodeId.getData()).intValue();
for (final ILsaNode node : nodes) {
if (node.getId() == id) {
setSynthectics(node);
setConcentration(node);
return;
}
}
throw new IllegalStateException("there is probably a bug in " + getClass().getName() + "\nMatches: "
+ getMatches() + "\nNodes: " + getNodes());
}
}
}
@Override
public final Context getContext() {
return Context.NEIGHBORHOOD;
}
/**
* @return the current environment
*/
protected Environment, ?> getEnvironment() {
return environment;
}
/**
* @return the current RandomGenerator
*/
protected RandomGenerator getRandomGenerator() {
return randomEngine;
}
/**
* Sets the synthetic variables.
*
* @param node
* the node to use as reference (e.g. for computing the distance)
*/
protected void setSynthectics(final ILsaNode node) {
/*
* #D and #ROUTE
*/
double d = initD || initRoute ? computeDistance(node) : Double.NaN;
if (initD) {
d = computeDistance(node);
setSyntheticD(d);
}
if (initRoute) {
if (mapEnv) {
final Route> route = menv.computeRoute(getNode(), node);
if (route != null) {
final double dist = route.length();
d = Math.max(d, dist);
}
}
setSyntheticRoute(d);
}
/*
* #NEIGH
*/
if (initNeigh) {
setSyntheticNeigh(environment.getNeighborhood(node).getNeighbors());
}
/*
* #O
*/
if (initO) {
setSyntheticO();
}
}
private double computeDistance(final ILsaNode node) {
return environment.getDistanceBetweenNodes(getNode(), node);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "+" + getMolecule().toString();
}
}