All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unibo.alchemist.model.sapere.actions.LsaRandomNeighborAction Maven / Gradle / Ivy

There is a newer version: 35.0.1
Show newest version
/*
 * 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();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy