package com.plectix.simulator.simulator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.plectix.simulator.interfaces.ConnectedComponentInterface;
import com.plectix.simulator.interfaces.ObservableConnectedComponentInterface;
import com.plectix.simulator.interfaces.SolutionInterface;
import com.plectix.simulator.io.xml.RuleCompressionXMLWriter;
import com.plectix.simulator.parser.abstractmodel.perturbations.conditions.ConditionType;
import com.plectix.simulator.simulationclasses.injections.Injection;
import com.plectix.simulator.simulationclasses.injections.InjectionsUtil;
import com.plectix.simulator.simulationclasses.perturbations.AbstractModification;
import com.plectix.simulator.simulationclasses.perturbations.ComplexPerturbation;
import com.plectix.simulator.simulationclasses.perturbations.ConditionInterface;
import com.plectix.simulator.simulationclasses.probability.SkipListSelector;
import com.plectix.simulator.simulationclasses.probability.WeightedItemSelector;
import com.plectix.simulator.simulator.api.SimulatorState;
import com.plectix.simulator.simulator.api.steps.OperationManager;
import com.plectix.simulator.simulator.api.steps.SolutionInitializationOperation;
import com.plectix.simulator.simulator.api.steps.experiments.RulePattern;
import com.plectix.simulator.staticanalysis.Agent;
import com.plectix.simulator.staticanalysis.Rule;
import com.plectix.simulator.staticanalysis.StaticAnalysisException;
import com.plectix.simulator.staticanalysis.contactmap.ContactMap;
import com.plectix.simulator.staticanalysis.influencemap.InfluenceMap;
import com.plectix.simulator.staticanalysis.localviews.LocalViewsMain;
import com.plectix.simulator.staticanalysis.observables.Observables;
import com.plectix.simulator.staticanalysis.rulecompression.CompressionResults;
import com.plectix.simulator.staticanalysis.rulecompression.RuleCompressionType;
import com.plectix.simulator.staticanalysis.rulecompression.RuleCompressor;
import com.plectix.simulator.staticanalysis.speciesenumeration.SpeciesEnumeration;
import com.plectix.simulator.staticanalysis.stories.Stories;
import com.plectix.simulator.staticanalysis.subviews.AllSubViewsOfAllAgentsInterface;
import com.plectix.simulator.staticanalysis.subviews.MainSubViews;
import com.plectix.simulator.util.IdGenerator;
public final class KappaSystem implements KappaSystemInterface {
private WeightedItemSelector<Rule> rules = new SkipListSelector<Rule>();
private List<Rule> orderedRulesList = new ArrayList<Rule>();
private Stories stories = null;
private List<ComplexPerturbation<?, ?>> perturbations = null;
private Observables observables = new Observables();
private SolutionInterface solution;// = new CSolution(); // soup of initial
// components
private final ContactMap contactMap = new ContactMap();
private AllSubViewsOfAllAgentsInterface subViews;
private InfluenceMap influenceMap = null;
private LocalViewsMain localViews = null;
private SpeciesEnumeration enumerationOfSpecies = null;
private RuleCompressionXMLWriter ruleCompressionWriter
= new RuleCompressionXMLWriter(this);
private final Set<RuleCompressionType> performedCompressions =
new HashSet<RuleCompressionType>();
private final IdGenerator agentsIdGenerator = new IdGenerator();
private final IdGenerator ruleIdGenerator = new IdGenerator();
private final SimulationData simulationData;
private SimulatorState state = null;
private boolean initialized = false;
private final OperationManager manager;
public KappaSystem(SimulationData data) {
simulationData = data;
state = new SimulatorState(data);
manager = new OperationManager(this);
}
public SimulationData getSimulationData() {
return simulationData;
}
public final SimulatorState getState() {
return state;
}
public final void resetState() {
state.reset();
// state = new SimulatorState(simulationData);
}
public boolean isInitialized() {
return initialized;
}
public void markAsNotInitialized() {
this.initialized = false;
}
//TODO move this code to the corresponding operation class body
public final void initialize() throws Exception {
manager.perform(new SolutionInitializationOperation(simulationData));
initialized = true;
}
public final List<Rule> compressRules(RuleCompressionType type,
Collection<Rule> rules) throws StaticAnalysisException {
RuleCompressor compressor = new RuleCompressor(type, this
.getLocalViews());
CompressionResults results = compressor.compress(rules);
MainSubViews newSubViews = new MainSubViews();
List<Rule> compressedRules = results.getCompressedRules();
newSubViews.build(solution, compressedRules);
newSubViews.initDeadRules();
//TODO separate output stuff
ruleCompressionWriter.addData(results, newSubViews);
performedCompressions.add(type);
return compressedRules;
}
public final boolean ruleCompressionWasPerformed(RuleCompressionType type) {
return performedCompressions.contains(type);
}
// ---------------------POSITIVE UPDATE-----------------------------
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#doPositiveUpdate
* (com.plectix.simulator.component.Rule, java.util.List)
*/
public final void doPositiveUpdate(Rule rule,
List<Injection> currentInjectionsList) {
if (simulationData.getSimulationArguments().needToBuildActivationMap()) {
rule.positiveUpdate(rule.getActivatedRules(), rule
.getActivatedObservable());
} else {
rule.positiveUpdate(getRules(), observables
.getConnectedComponentList());
}
List<Agent> freeAgents = UpdatesPerformer
.doNegativeUpdateForDeletedAgents(rule, currentInjectionsList);
doPositiveUpdateForDeletedAgents(freeAgents);
}
private final void doPositiveUpdateForDeletedAgents(List<Agent> agents) {
for (Agent agent : agents) {
for (Rule rule : orderedRulesList) {
for (ConnectedComponentInterface cc : rule.getLeftHandSide()) {
Injection inj = cc.createInjection(agent);
if (inj != null) {
if (!agent.hasSimilarInjection(inj))
cc.setInjection(inj);
}
}
}
for (ObservableConnectedComponentInterface obsCC : observables
.getConnectedComponentList()) {
Injection inj = obsCC.createInjection(agent);
if (inj != null) {
if (!agent.hasSimilarInjection(inj))
obsCC.setInjection(inj);
}
}
}
}
// ------------------MISC--------------------------------
public final List<Injection> chooseInjectionsForRuleApplication(Rule rule) {
List<Injection> list = new ArrayList<Injection>();
rule.preparePool(simulationData);
for (ConnectedComponentInterface cc : rule.getLeftHandSide()) {
Injection inj = cc.getRandomInjection();
list.add(inj);
solution.addInjectionToPool(rule.getPool(), inj);
}
if (!InjectionsUtil.isClash(list)) {
return list;
} else {
return null;
}
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#setRules(java.util
* .List)
*/
public final void setRules(List<Rule> rules) {
orderedRulesList = rules;
performedCompressions.clear();
this.rules.updatedItems(rules);
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#checkPerturbation
* (double)
*/
public final void checkPerturbation(double currentTime) {
if (perturbations.size() != 0) {
for (ComplexPerturbation<?, ?> pb : perturbations) {
AbstractModification modification = pb.getModification();
ConditionInterface condition = pb.getCondition();
if (condition.getType() != ConditionType.SPECIES) {
if (modification.wasPerformed()) {
continue;
}
}
if (condition.check(currentTime)) {
modification.perform();
}
}
}
}
// ----------------------GETTERS-------------------------------
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getRules()
*/
public final List<Rule> getRules() {
return orderedRulesList;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#getRuleById(int)
*/
//TODO we have three similar methods here! It is time for refactoring =)
public final Rule getRuleById(int ruleId) {
// TODO: We are scanning a list linearly, can't we use a LinkedHashMap
// here?
for (Rule rule : orderedRulesList) {
if (rule.getRuleId() == ruleId) {
return rule;
}
}
return null;
}
//TODO we have three similar methods here! It is time for refactoring =)
public final Rule getRuleByName(String ruleName) {
for (Rule rule : orderedRulesList) {
if (ruleName.equals(rule.getName())) {
return rule;
}
}
return null;
}
//TODO we have three similar methods here! It is time for refactoring =)
public final Rule getRuleByPattern(RulePattern pattern) {
for (Rule rule : orderedRulesList) {
if (pattern.matches(rule)) {
return rule;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getSolution()
*/
public final SolutionInterface getSolution() {
return solution;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#getObservables()
*/
public final Observables getObservables() {
return observables;
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getStories()
*/
public final Stories getStories() {
return stories;
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getContactMap()
*/
public final ContactMap getContactMap() {
return contactMap;
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getSubViews()
*/
public final AllSubViewsOfAllAgentsInterface getSubViews() {
return subViews;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#generateNextRuleId()
*/
public final long generateNextRuleId() {
return ruleIdGenerator.generateNext();
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#generateNextAgentId
* ()
*/
public final long generateNextAgentId() {
return agentsIdGenerator.generateNext();
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#getPerturbations()
*/
public final List<ComplexPerturbation<?, ?>> getPerturbations() {
return perturbations;
}
// ----------------------SETTERS / ADDERS-------------------------------
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#addRule(com.plectix
* .simulator.component.Rule)
*/
public final void addRule(Rule rule) {
orderedRulesList.add(rule);
rules.updatedItem(rule);
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#setSolution(com.
* plectix.simulator.interfaces.SolutionInterface)
*/
public void setSolution(SolutionInterface solution) {
this.solution = solution;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#setObservables(com
* .plectix.simulator.component.Observables)
*/
public void setObservables(Observables observables) {
this.observables = observables;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#setStories(com.plectix
* .simulator.component.stories.Stories)
*/
public final void setStories(Stories stories) {
this.stories = stories;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#addStories(java.
* lang.String)
*/
public final void addStories(String name) {
byte index = 0;
List<Integer> ruleIDs = new ArrayList<Integer>();
for (Rule rule : orderedRulesList) {
if ((rule.getName() != null)
&& (rule.getName().startsWith(name) && ((name.length() == rule
.getName().length()) || ((rule.getName()
.startsWith(name + "_op")) && ((name.length() + 3) == rule
.getName().length()))))) {
ruleIDs.add(rule.getRuleId());
index++;
}
if (index == 2) {
this.stories.addToStories(ruleIDs);
return;
}
}
this.stories.addToStories(ruleIDs);
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#setPerturbations
* (java.util.List)
*/
public final void setPerturbations(
List<ComplexPerturbation<?, ?>> perturbations) {
this.perturbations = perturbations;
}
// --------------------CLEANUP---------------------
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#resetIdGenerators()
*/
public final void resetIdGenerators() {
agentsIdGenerator.reset();
ruleIdGenerator.reset();
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#clearRules()
*/
public final void clearRules() {
performedCompressions.clear();
rules = new SkipListSelector<Rule>();
orderedRulesList.clear();
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#clearPerturbations()
*/
public final void clearPerturbations() {
if (perturbations != null) {
perturbations.clear();
}
}
// ---------------------MISC------------------------
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getRandomRule()
*/
public final Rule getRandomRule() {
List<Rule> infiniteRules = getInfiniteRatedRules();
if (!infiniteRules.isEmpty() && !this.anyRuleCannotBeApplied(infiniteRules)) {
return infiniteRules.get(ThreadLocalData.getRandom().getInteger(
infiniteRules.size()));
}
return rules.select();
}
/**
* We check whether any rule with infinite rate cannot be applied because of clashes
* @return
*/
private final boolean anyRuleCannotBeApplied(List<Rule> rules) {
for (Rule rule : rules) {
if (!ruleIsBlockedWithClashes(rule)) {
return false;
}
}
return true;
}
/**
* We assume that left hand side of the rule can contain only 2 connected components
* @param rule
* @return
*/
private final boolean ruleIsBlockedWithClashes(Rule rule) {
List<Injection> pair = new ArrayList<Injection>();
if (rule.getLeftHandSide().size() < 2) {
return false;
}
for (Injection injection0 : rule.getLeftHandSide().get(0).getInjectionsList()) {
pair.add(injection0);
for (Injection injection1 : rule.getLeftHandSide().get(1).getInjectionsList()) {
pair.add(injection1);
if (!InjectionsUtil.isClash(pair)) {
return false;
}
pair.remove(injection1);
}
}
return true;
}
private List<Rule> getInfiniteRatedRules() {
List<Rule> infinitRules = new ArrayList<Rule>();
for (Rule rule : orderedRulesList) {
if (rule.hasInfiniteRate() && rule.getActivity() > 0) {
infinitRules.add(rule);
rule.setActivity(0.);
rules.updatedItem(rule);
}
}
return infinitRules;
}
public void updateRuleActivities() {
for (Rule rule : orderedRulesList) {
double oldActivity = rule.getActivity();
rule.calculateActivity();
if (rule.getActivity() != oldActivity) {
rules.updatedItem(rule);
}
}
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getTimeValue()
*/
public final double getTimeValue() {
double randomValue = 0;
while (randomValue == 0.0)
randomValue = ThreadLocalData.getRandom().getDouble();
return -1. / rules.getTotalWeight() * java.lang.Math.log(randomValue);
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#getInfluenceMap()
*/
public final InfluenceMap getInfluenceMap() {
return influenceMap;
}
/*
* (non-Javadoc)
*
* @see com.plectix.simulator.simulator.KappaSystemInterface#getLocalViews()
*/
public final LocalViewsMain getLocalViews() throws StaticAnalysisException {
if (localViews == null) {
MainSubViews sViews = new MainSubViews();
sViews.build(getSolution(), getRules());
localViews = new LocalViewsMain(sViews);
localViews.buildLocalViews();
}
return localViews;
}
/*
* (non-Javadoc)
*
* @see
* com.plectix.simulator.simulator.KappaSystemInterface#getEnumerationOfSpecies
* ()
*/
public final SpeciesEnumeration getEnumerationOfSpecies() {
return enumerationOfSpecies;
}
public final RuleCompressionXMLWriter getRuleCompressionBuilder() {
return ruleCompressionWriter;
}
public OperationManager getOperationManager() {
return manager;
}
public void setEnumerationOfSpecies(SpeciesEnumeration enumerationOfSpecies) {
this.enumerationOfSpecies = enumerationOfSpecies;
}
public void setSubviews(AllSubViewsOfAllAgentsInterface subviews) {
this.subViews = subviews;
}
public void setInfluenceMap(InfluenceMap influenceMap) {
this.influenceMap = influenceMap;
}
public void setLocalViews(LocalViewsMain localViews) {
this.localViews = localViews;
}
}