I want to know for what we need following fields:
node
do
digression
disable
goto
next
transitions
set
exit
node call_reason
{
do
{
digression disable sayHi;
goto next;
}
transitions
{
next: goto how_are_you;
}
}
I suppose, you are asking this question because you are a little bit confused about syntax, I'll try to make it clear.
Nodes and Transitions
DashaScript is the language for describing automated conversations. Basically, any conversation script consists of
nodes - states of your conversation (please, see node doc)
transitions - relations between nodes that are described by conditions of switching from the current node to the another. There are three different kinds of transitions, e.g. instant transition that is used in code of your example (please, see transitions doc).
In some sense, the scripted conversation can be thought of as a graph. In this case, nodes and transitions can be interpreted as vertices and edges of a graph, respectively.
Hence, node and transition define the structure of your conversation script.
Every node has subsection do where you can specify actions and instructions you want to be performed in this particular node.
Also, node may have subsection transitions which is used to specify conditions of switching a current state to another.
Every event-transition (like transition on event and timer transition) specified in this section has the following syntax: <transition_name>: goto <node_name> on <switching_condition>.
Instant transitions (like the one used in your code) have no conditions: <transition_name>: goto <node_name>. To execute such transition, it must be called in section do of current node with goto instruction.
Also, there are special nodes that can be visited from any state. These nodes are called digressions. (see digressions doc). They are used to make fast reactions in your conversation and return to main branch of conversation. To control digression, we have mechanism of enabling/disabling them (see digression-control doc).
So, in your example, the node with name call_reason has section do where you disable degression-node and then instant transition with name next is executed.
All entities of DashaScript language mentioned above are described in program structure docs. I would recommend you to check it out, since there are more important entities that you might need to know about.
Set
set is the instruction that is used for assigning a value for some variable. Example:
node some_node
{
do {
var some_variable: number = 1;
set some_variable = 2; // now some_variable has value of 2
}
}
Exit
exit is the instruction that interrupts the dialog.
Related
I've been looking for the difference of ExitRule and EnterRule in Listener in "the definitive antrl4 reference" book but I still don't understand the difference. What is the difference between these two? And how does Listener travel the tree?
simply said, these are auto generated events created by Antrl
to keep track of the walker, so to speak.
Imagine, you stand in the middle of a long floor with countless doors on either site. Which you have to open and something in the rooms.
To keep track on which doors you've already visited, you mark them with a X and an incrementing number behind.
enterRule == You opens the door of a room.
you get in and search
exitRule == leave the room and paint the X and the next number on the door.
Now you are able to tell exactly which rooms you have already visited, but further more you are able to go to a specific room again for another search, without having to go all the way back and start all over again.
more technically spoken.
Antrl creates an enter and exit method for each Rule that is defined.
These Methods, or also known as callbacks, being used by the walker to walk the given tree.
Using a *ParseTreeListener you provide an entry point which indicates the beginning of the tree. For example enterAssign.
The Walker looks for this event and triggers it.
It then looks for a sub enterRule to trigger this event, and so on...
It keeps walking for as long as it find further enter rules or triggers exitAssign and the walker stops its walk.
Keypoint here is the automated or indipendent walk behavior.
The ParseTreeVisitor on the other hand,
will not generating enter/exit Rules to walk a tree.
It will generate visitRule instead.
The visit methods have to be called explicitly!
That means, if you forget to invoke a visit all its children don't get visited at all.
Antrl-Doc --> Parse Tree Listeners
Antrl-Mega-Tutorial --> many Information, short and precise
Tree Walking
Walking starts from a Root-Node and goes down on it until it have found the very left-most nested item. Then goes back up until it reaches the first node and looks for a sub-tree on the right.
It enters the right tree if one is found.
Or, it gets futher up the chain to find the next node.
...
Until it reaches the Root-Node again.
short Picture:
parent
|
/ \
/ \
Child1 Child2
/
/
Grandchild
chain of Calls:
enter parent
enter Child1
enter Grandchild
exit Grandchild
exit Child1
enter Child2
exit Child2
exit parent
I have a Maya MEL script, which inserts some nodes. The evaluation seems to be deferred until the script finishes. I guess this comes from the pipeline evaluating when the shape is requested by the renderer, so the dirty propagation starts.
Now I want to run commands if the inserted node calculated a certain output like this:
$node = `insertMyNode`;
dgdirty ($node+".outputAttr");
if(`getAttr ($node+".outputAttr")` == 1) {
print("true");
} else {
print("false");
}
This always prints false. When I insert the node and then run getAttr ($node+".outputAttr") in the MEL editor, the node is computed and I get 1.
I tried dgeval as well and it didn't work either. I think in principle neither dgeval nor dgdirty should be needed but getAttr should start the dirty propagation.
But it always returns the default value of the node, not the evaluated one.
dgdirty $node works for me, but I still would rather only dirty the output I am using (and if possible automatically, not with a command which is documented to be for debugging purposeses), so the node does not need to recompute all outputs.
myNode has defined and inputMesh parameter which affects an output bool outputAttr value using attributeAffects in its C++ code. the insertMyNode command connects an input mesh. It is correct that the node is not computed without a connection to an output plug, but when reading the plug it should be computed. When I open the node editor and hover over the output plug, the node is computed correctly. I would expect getAttr to do the same in the example code above.
The dirty propagation usually works if you are dirtying input attributes and request output attributes. To it seems you are dirtying an input attribute and try to get the same input attribute. Usually in a node this is coded with "affects" like: affects(attrA, attrB). and if attrB is requested, the compute() method is called.
So I suppose it could work better if you try to get an output attribute.
I have one parent node ,based on the user input Iam setting a context variable at my application level eligibility:yes or no and passing back.And for my parent node I have two child nodes for conditions $eligibility=="yes" and $eligibility=="no".So once users input from parent node validation is done and context variable is passed back ,then I need to jump and look for condition of eligibility.If yes I need to go one node ,if no then to other.How can I do?
I tried putting true to node and added these two nodes to this and jump to true..But didnt worked..How can we achieve this?
what #data_henrik has mentioned is a good way to set context value and then switch to different flows depending upon the set value. But when you need to perform some logic before setting that value in the context from your application, it won't be a suitable way.
I had a requirement like this, so we used to send a dummy text from our application after we were done with setting the value in context after the parent node execution. Check out the images and explanation after that.
We didn't use Jump because we had to do some validation in the Conversation service after parent node before moving forward. Using jumps would've allowed the Conversation to move to next node before we could set value in context.
Use case flow - once user enters text for the parent node intent, for my case "#send-mail" intent, I show the parent response and do some functional validation in my app after that and add a value to the context. Now we send a dummy text "valid" which satisfies the intent "#Valid" and hence move to the next node in flow. In this node we check for the value in context (which is already set by now) and show appropriate response to user.
You can set within your first two test nodes, $testMe==true and $testMe==false a temp output variable within the output json packet, i.e. output{"temp":"true"} or "false". Then you can jump to a new set of nodes and test for the output.temp value, i.e. output.temp == 'true' then do something, or output.temp == 'false' then do something.
The nice side effect of this action is that the output.temp variable only has a life of that current conversation input. Unlike context variables which need to be removed / deleted.
I'm coding a model where :
Node are represented as bitvectors of 10 length each representing some molecules and edges can take any molecules that was present at source to to a target node.
for example
S_Node : 0b0100000011 // Molecule 0 , 1 , 8 present on node
One_Edge : 0b0000000010 // Molecule 1 is going out on edge
I have to enforce condition that each outgoing Molecule on edge is coming back to the source node on some cycle. Molecule has to come back in a cycle means that during taking path of the cycle it has to be present on evry node and evry edge it takes.
* Parallel edges are allowed.
Molecule 1 takes path S_Node -> Node_1 -> Node_2 ... -> S_Node. So Molecule 1 started from S_Node on an edge and traveled through Node_1 ... and came back to S_Node on a cycle. Hence this molecule satisfies the condition.
Similarly i have to check for each molecule on each edge.
I'm doing in trivial possible way of checking for each nodes what are possible edges going out and then for each edge what are possible bits that are present and enforcing each coming back on some cycle.
for (i = 0; i < N; i++) { // for each Node
for (j = 0; j < E; j++) { // for each Edge going out frm node i
// Lets say we have some way of finding E
if(edgeWeight & (1 << j)) { //All outgoing bits
// Enforcing that each will come back
// On some Cycle
Its easily visible that i have to iterate over all nodes and then all edges going out and then for each bits on those edges, have to write code for enforcing the same. Enforcing itself have to iterate over at least no.Of Nodes #N.
Any better way to efficiently do this ? Any other way to check for same thing in graph theory ? Thanks
You seem to have a directed graph per molecule (per bit) Simply do your trick to check for any non-cycles per molecule.
You can take btillys way of checking for cycles, another option is to look at strongly connected components. You essentially want each subgraph (for a given molecule) to be a graph where each connected component is actually strongly connected. There are some good algorithms to for strongly connected components referred to from the wikipedia article linked to earlier.
The representation of nodes is irrelevant to the problem. You have a directed graph. You wish to verify that for every node and edge, there exists a cycle containing that edge. And you want to be reasonably efficient about it (rather than doing a brute force search for all possible cycles from all edges).
Here is an observation. Suppose that you find a cycle in your graph G. Consider the graph G' which is the same as your original graph EXCEPT that the cycle has been collapsed down to a single node. The answer to your question for G is the same as the answer to your question for G' because any cycle in G leads to a cycle in G' (possibly a self-intersecting one that can be turned into 2 cycles), and any cycle in G' leads to a cycle in G (if you hit the collapsed node, then follow its cycle around until you find the exit point to continue).
So now the question goes from brute force discovery of cycles to collapsing cycles until you have a small graph where the question is easily answered. So for each node, for each edge, you start a path. Your path continues until you have discovered a cycle. Any cycle. (Not necessarily back to the original node!) Collapse that cycle, and keep traveling until you either have to backtrack (in which case your condition is not met) or you manage to loop back to your original node, collapse that cycle, and move on to another edge.
If you implement this, you'll have a polynomial algorithm, but not the best you can do. The problem is that creating new graphs with a cycle collapsed is an expensive operation. But there is a trick that helps. Instead of collapsing the graph every time you find a cycle, try to be lazy about it. Create a new "fake node" for that cycle, and mark each node in that cycle as going to that fake one. Every time you see an edge that goes to a node, do a recursive search through those mappings to the most collapsed node that you've found, and mark everything you saw in that search as directly mapping there.
If you implement the lazy bit well, your overall algorithm should wind up O(E) where E is the number of edges in your graph. You actually can't do better than that given that you have to visit every edge no matter what you do.
I have a game I am working on that uses a linked list for the entities in the game. I have found what I think to be some sort of bug. Note, I'm coding in C. But after this trouble with C pointers I'm thinking about trying C++ techniques.
In my debug testing two projectiles were colliding which blows both of them up. Basically the situation is this:
Starting in Entity's move function:
1) Projectile entity moves
2) Loop through all entities checking collision at this new location
3) If collision, in this case between projectiles, remove both
I pass a double pointer of the entity to the function that does collision. That entity may be removed but I still need to use it for advancing the entity to the next one in the list (in the while loop). If that didn't make sense it is seen as this:
ENTITY *node;
while (node)
{
...
entity_do_collision (&node); // <-- node may be removed in this function
//Debug
if (node == global_node)
{
}
else
node = global_node;
node = node->next; // <-- pass a double pointer above so this works here
}
So, I've ran through the code so many times and don't see any illegal operations. The part that gets me is sometimes the double pointer will work and sometimes it won't. I tested using a global entity pointer (that always works) to compare back in my entity move function to test if the node being removed matches what it was set to in the entity remove function.
This description is a little abstract, so let me know if I need to explain more.
There are zillion solutions which would or would not work for your exact problem.
Here are some ideas to start with:
Do not delete objects from the container on collision, but mark them "dead". Clean up "dead" bodies in separate pass after collision detection finished.
Mark them dead on collision, but not delete at all. Just reuse marked nodes for future entities.
Improvement of (2): sort your container, so "dead" entities went to the tail and mark size of the container as it would contain only "living" ones
Improvement of (1), (2), (3): implement some kind of "garbage collection", so "dead" entities would be cleaned up let's say once a second or once a frame or when memory threshold reached.
etc.
Sidenote: You should never use linked lists in 21th's century (an era of hierarchies of caches, prefetching, out-of-order execution and mutithreading), unless you really, really have no other choice and you understand what you are doing. Use arrays by default, swith to something else only if you find it reasonable.
More info:
What is “cache-friendly” code?
Stop Using Linked-Lists
Bjarne Stroustrup: Why you should avoid Linked Lists (video)
Original code:
ENTITY *node;
while (node)
{
...
entity_do_collision (&node); // <-- node may be removed in this function
node = node->next;
/* the function can have changed node's value
** but on the next iteration ( on the **value** of node->next)
** the original node->next will not be affected!
*/
}
Sample code using pointer tot pointer:
ENTITY **pp;
for (pp = &global_node; *pp; pp = &(*pp)->next)
{
...
entity_do_collision (pp); // <-- *pp (= node) may be removed in this function
...
}