diff --git a/AlgebraicDataflowArchitectureModel/models/Twitter.model b/AlgebraicDataflowArchitectureModel/models/Twitter.model index 491d904..596ad7b 100644 --- a/AlgebraicDataflowArchitectureModel/models/Twitter.model +++ b/AlgebraicDataflowArchitectureModel/models/Twitter.model @@ -6,11 +6,11 @@ out accounts.{id}.tweets(t1:List, tweet(text:Str, time:Long)) = cons(tuple(time, text), t1) } -channel C(myId:Str; m:Json) { +channel C(myId:Str) { in accounts.{myId}.tweets(t1:List, m) = m.myTweets - sub C2(no:Int; flw:Json := m.followees.{no}) { - in accounts.{myId}.followees.{no}(id:Str, flw) = flw.id - in accounts.{flw.id}.tweets(t2:List, flw) = flw.tweets + sub C2(no:Int) { + in accounts.{myId}.followees.{no}(id:Str, m) = m.flw.{no}.id + in accounts.{flw.id}.tweets(t2:List, m) = m.flw.{no}.tweets } - out accounts.{myId}.timeline(l:List, m) = merge(m.myTweets, m.followees) + out accounts.{myId}.timeline(l:List, m) = merge(m.myTweets, m.flw) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java index ce4424e..654eabb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -10,6 +10,12 @@ import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferChannel; +/** + * State of a channel, which represents the map from the values of the depended channel selectors to those of the depending channel selectors + * + * @author Nitta + * + */ public class ChannelState implements Cloneable { private DataTransferChannel channel; private ReferenceStructure referenceStructure; @@ -45,6 +51,13 @@ return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal); } + /** + * Add a value of a depending channel selector + * + * @param channelValues the values of depended channel selectors + * @param dependingVariable a depending channel selector + * @param itsValue its new value + */ public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { if (referenceStructure == null) { referenceStructure = new ReferenceStructure(); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index f263fe9..e9e1db3 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -14,6 +14,7 @@ import models.algebra.Position; import models.algebra.Term; import models.algebra.UnificationFailed; +import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.Selector; @@ -21,6 +22,12 @@ import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +/** + * Event occurred at a channel + * + * @author Nitta + * + */ public class Event { private DataTransferChannel channel; private Expression message; @@ -31,10 +38,18 @@ private List> channelSelectorAndValues = new ArrayList<>(); private Map dependingParameters = new HashMap<>(); private Set outputResources = new HashSet<>(); - private Set succEvents = new HashSet<>(); + private Set childEvents = new HashSet<>(); private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); private Map> channelSelectorToOutputResourcePathParam = new HashMap<>(); + /** + * Constructor for an input event channel + * + * @param channel an input event channel + * @param message an message for the channel + * @param outputResPath an output side resource path of the channel + * @param outputResource an output side resource of the channel + */ public Event(DataTransferChannel channel, Expression message, ResourcePath outputResPath, Resource outputResource) { this.channel = channel; this.message = message; @@ -42,7 +57,7 @@ this.outputResources.add(outputResource); connectChannelSelectorAndPathParameters(); - // Extract channel parameters from the output resource. + // Extract the values of the channel selectors from the output resource. List channelSelectors = channel.getAllSelectors(); for (Selector sel: channelSelectors) { int paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); @@ -59,6 +74,13 @@ } } + /** + * Constructor for a non-event channel + * + * @param channel a non-event channel + * @param inputResPath an input side resource path of the channel + * @param inputResource an input side resource of the channel + */ public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource) { this.channel = channel; this.isInput = false; @@ -66,7 +88,7 @@ this.inputResource = inputResource; connectChannelSelectorAndPathParameters(); - // Extract channel parameters from the input resource. + // Extract the values of the channel selectors from the input resource. List channelSelectors = channel.getAllSelectors(); for (Selector sel: channelSelectors) { if (inputResPath != null) { @@ -87,6 +109,15 @@ } } + /** + * Constructor for a non-event channel + * + * @param channel a non-event channel + * @param inputResPath an input side resource path of the channel + * @param inputResource an input side resource of the channel + * @param channelSelectorValues the values of depended channel selectors + * @param dependingVarToVal the values of depending channel selectors + */ public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource, List channelSelectorValues, Map dependingVarToVal) { this.channel = channel; this.isInput = false; @@ -94,7 +125,7 @@ this.inputResource = inputResource; connectChannelSelectorAndPathParameters(); - // Extract channel parameters from the input resource. + // Extract the values of the channel selectors from channelSelectorValues. List channelSelectors = channel.getAllSelectors(); for (int i = 0; i < channelSelectors.size(); i++) { Selector sel = channelSelectors.get(i); @@ -171,7 +202,13 @@ } - public Term updateDependingParameters(IResourceStateValueProvider resourceStateValueProvider) { + /** + * Update the values of the depending channel selectors + * + * @param resourceStateValueProvider a resourceStateValueProvider to provide current and next resource states + * @return calculated message constraint by this event + */ + public Term constructMessageAndDescendantEvents(IResourceStateValueProvider resourceStateValueProvider, boolean doesUpdateDependingParameters) { IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { @Override public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { @@ -194,59 +231,26 @@ try { Map> substitutedPositionsInMessageFromChannels = new HashMap<>(); - Term unifiedMessage = null; - - // Calculate message constraints from leaf channel members on the channel member dependency graph. - Map> dependency = channel.getMemberDependency(); - if (dependency.size() == 0) { - // No channel member dependency. - Expression messageConstraint = null; - for (ChannelMember channelMember: channel.getInputChannelMembers()) { - // Calculate message constraint from an input state transition - messageConstraint = channel.calcMessageConstraintForInputMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - if (unifiedMessage == null) { - unifiedMessage = (Term) messageConstraint; - } else { - unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); - if (unifiedMessage == null) { - throw new UnificationFailed(); - } - } - } - for (ChannelMember channelMember: channel.getReferenceChannelMembers()) { - // Calculate message constraint from a reference state transition - messageConstraint = channel.calcMessageConstraintForReferenceMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - if (unifiedMessage == null) { - unifiedMessage = (Term) messageConstraint; - } else { - unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); - if (unifiedMessage == null) { - throw new UnificationFailed(); - } - } - } - return unifiedMessage; - } - Set toResolve = new HashSet<>(); - Set resolved = new HashSet<>(); - for (Set depended: dependency.values()) { - toResolve.addAll(depended); - } - for (ChannelMember depending: dependency.keySet()) { - toResolve.remove(depending); - } + return constructMessageAndDesdendantEvents(this.channel, resouceStateAccessor, substitutedPositionsInMessageFromChannels, doesUpdateDependingParameters); + } catch (ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed e) { + e.printStackTrace(); + } + return null; + } + + private Term constructMessageAndDesdendantEvents(DataTransferChannel channel, IResourceStateAccessor resouceStateAccessor, + Map> substitutedPositionsInMessageFromChannels, boolean doesUpdateDependingParameters) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork, UnificationFailed { + Term unifiedMessage = null; + + // Calculate message constraints from leaf channel members on the channel member dependency graph. + Map> dependency = channel.getMemberDependency(); + if (dependency.size() == 0) { + // No channel member dependency. Expression messageConstraint = null; - if ((messageConstraint = getMessage()) instanceof Term) { - unifiedMessage = (Term) messageConstraint; - } - for (ChannelMember leafMember: toResolve) { - if (channel.getInputChannelMembers().contains(leafMember)) { - // Calculate message constraint from an input state transition - messageConstraint = channel.calcMessageConstraintForInputMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - } else if (channel.getReferenceChannelMembers().contains(leafMember)) { - // Calculate message constraint from a reference state transition - messageConstraint = channel.calcMessageConstraintForReferenceMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - } + for (ChannelMember channelMember: channel.getInputChannelMembers()) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); if (unifiedMessage == null) { unifiedMessage = (Term) messageConstraint; } else { @@ -256,20 +260,65 @@ } } } - resolved.addAll(toResolve); - toResolve.clear(); - - for (;;) { - for (Map.Entry> dependEnt: dependency.entrySet()) { - ChannelMember dependingMem = dependEnt.getKey(); - Set dependedMems = dependEnt.getValue(); - if (!resolved.contains(dependingMem) && resolved.containsAll(dependedMems)) { - toResolve.add(dependingMem); + for (ChannelMember channelMember: channel.getReferenceChannelMembers()) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); } } - if (toResolve.size() == 0) break; - for (ChannelMember dependingMem: toResolve) { - // Fill the path parameters of the resource path of a depending channel member. + } + return unifiedMessage; + } + Set toResolve = new HashSet<>(); + Set resolved = new HashSet<>(); + for (Set depended: dependency.values()) { + toResolve.addAll(depended); + } + for (ChannelMember depending: dependency.keySet()) { + toResolve.remove(depending); + } + Expression messageConstraint = null; + if ((messageConstraint = getMessage()) instanceof Term) { + unifiedMessage = (Term) messageConstraint; + } + for (ChannelMember leafMember: toResolve) { + if (channel.getInputChannelMembers().contains(leafMember)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(leafMember)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + resolved.addAll(toResolve); + toResolve.clear(); + + // Calculate message constraints from remaining members on the channel member dependency graph. + for (;;) { + for (Map.Entry> dependEnt: dependency.entrySet()) { + ChannelMember dependingMem = dependEnt.getKey(); + Set dependedMems = dependEnt.getValue(); + if (!resolved.contains(dependingMem) && resolved.containsAll(dependedMems)) { + toResolve.add(dependingMem); + } + } + if (toResolve.size() == 0) break; + for (ChannelMember dependingMem: toResolve) { + // Fill the path parameters of the resource path of a depending channel member. + if (doesUpdateDependingParameters) { Set dependingVarPosInMessage = new HashSet<>(); ResourcePath filledResPath = channel.fillOutsideResourcePath(dependingMem.getResource(), unifiedMessage, dependingMem.getStateTransition().getMessageExpression(), dependingVarPosInMessage); ResourcePath unfilledResPath = dependingMem.getResource(); @@ -293,32 +342,49 @@ updateDependingParameter(var, val); } } - - // Calculate message constraint - if (channel.getInputChannelMembers().contains(dependingMem)) { - // Calculate message constraint from an input state transition - messageConstraint = channel.calcMessageConstraintForInputMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - } else if (channel.getReferenceChannelMembers().contains(dependingMem)) { - // Calculate message constraint from a reference state transition - messageConstraint = channel.calcMessageConstraintForReferenceMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); - } + } + + // Calculate message constraint + if (channel.getInputChannelMembers().contains(dependingMem)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(dependingMem)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); if (unifiedMessage == null) { - unifiedMessage = (Term) messageConstraint; - } else { - unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); - if (unifiedMessage == null) { - throw new UnificationFailed(); - } + throw new UnificationFailed(); } } - resolved.addAll(toResolve); - toResolve.clear(); } - return unifiedMessage; - } catch (ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed e) { - e.printStackTrace(); + resolved.addAll(toResolve); + toResolve.clear(); } - return null; + + // Calculate message constraints from child channels. +// for (Channel childChannel: channel.getChildren()) { +// for (Selector nextSelector: childChannel.getSelectors()) { +// +// } +// Event childEvent = new Event((DataTransferChannel) childChannel, (Expression) messageConstraint.clone(), null, null); +// messageConstraint = constructMessageAndDesdendantEvents((DataTransferChannel) childChannel, resouceStateAccessor, substitutedPositionsInMessageFromChannels); +// if (unifiedMessage == null) { +// unifiedMessage = (Term) messageConstraint; +// } else { +// unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); +// if (unifiedMessage == null) { +// throw new UnificationFailed(); +// } +// } +// childEvents.add(childEvent); +// } + + message = unifiedMessage; + return unifiedMessage; } public void updateDependingParameter(Expression variable, Expression value) { @@ -337,14 +403,6 @@ return outputResources; } - public Set getSuccessors() { - return succEvents; - } - - public void addSuccessor(Event succEvt) { - succEvents.add(succEvt); - } - public ResourceIdentifier getResourceIdentifier(ResourcePath resPath) { ResourceIdentifier resId = ResourceIdentifier.createFrom(resPath); for (Map.Entry chParamEnt: channelSelectorAndValues) { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index ac2c94b..6ddf8d4 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -11,6 +11,11 @@ import models.dataConstraintModel.ResourceHierarchy; import simulator.states.*; +/** + * A runtime instance of a resource + * @author Nitta + * + */ public class Resource { private Resource parent = null; private Map children = null; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index a2df91d..34c6d32 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -30,6 +30,11 @@ import simulator.interfaces.INativeInitializer; import simulator.interfaces.INativeReceiver; +/** + * Simulator to run a model + * @author Nitta + * + */ public class Simulator { private DataTransferModel model; private SystemState curState; @@ -95,7 +100,7 @@ public SystemState transition(Event inputEvent) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { SystemState nextSystemState = new SystemState(curState); - inputEvent.updateDependingParameters(new ResourceStateValueProvider(curState, nextSystemState)); + inputEvent.constructMessageAndDescendantEvents(new ResourceStateValueProvider(curState, nextSystemState), true); nextSystemState.addEvent(inputEvent); fireEvent(inputEvent, curState, nextSystemState); @@ -201,7 +206,7 @@ Expression nextResState = null; outTarget[0] = out; outResVar[0] = new Variable(channel.getChannelName() + "$" + out.getResource().toString() + "$this"); // A special variable to represent the current state of each output resource. - if (!event.isInput() || event.getMessage() instanceof Variable) { + if (event.getMessage() instanceof Variable) { nextResState = channel.deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); } else { nextResState = channel.deriveUpdateExpressionOf(out, (Term) event.getMessage(), resouceStateAccessor); @@ -280,7 +285,7 @@ // If some depending resources are to be updated by the update of an depended input resource. if (doesSatifsyPathConstraints(inResPath, inResId)) { Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); - Expression message = nextEvent.updateDependingParameters(resourceStateValueProvider); + Expression message = nextEvent.constructMessageAndDescendantEvents(resourceStateValueProvider, true); if (message != null) { if (nextChState == null) { nextChState = new ChannelState(channel); @@ -305,9 +310,8 @@ if (!isInputResourceDepended && !isInputResourceDepending) { if (doesSatifsyPathConstraints(inResPath, inResId)) { Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); - Expression message = nextEvent.updateDependingParameters(resourceStateValueProvider); + Expression message = nextEvent.constructMessageAndDescendantEvents(resourceStateValueProvider, true); if (message != null) { - nextEvent.setMessage(message); nextEvents.add(nextEvent); } } @@ -362,7 +366,10 @@ } if (doesMatch) { Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId), channelSelectorValues, dependingVarToVal); - nextEvents.add(nextEvent); + Expression message = nextEvent.constructMessageAndDescendantEvents(resourceStateValueProvider, false); + if (message != null) { + nextEvents.add(nextEvent); + } } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index e078ccb..1b19ac6 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -26,6 +26,11 @@ import simulator.states.PrimitiveResourceState; import simulator.states.ResourceState; +/** + * The whole state of a running model + * @author Nitta + * + */ public class SystemState { private Set rootResources = new HashSet<>(); private Map channelStates = new HashMap<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java index 2dfa5c0..00883d9 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java @@ -2,6 +2,11 @@ import models.algebra.Expression; +/** + * A state of a resource + * @author Nitta + * + */ abstract public class State implements Cloneable { abstract public Expression getValue(); abstract public Object clone();