I am working on a system, when given a bank of different types of elements will create a directed acyclic graph connecting some or all the elements. Each element has some input A and an output B. When building the Graph, the system will need to make sure, the output of the previous node, matches the input of the current one.
The input and output of the nodes are to make sure only certain types of elements are connected
The elements would look like this
ElementName : Input -> Output
Possibly with multiple inputs/output, or with no outputs(See below).
One : X -> Y
Two : Y -> Z,F
Three : Y, Z -> W
Four : Z -> F
Five : F -> NULL
Note:
We are talking about a lot of different elements, 30 or so now, but the plan is to add more as time goes on.
This is part of a project to do a procedural generated narrative. The nodes are individual quests. The inputs are what you need to start the quest. The outputs are how the story state is effected.
Problem:
I have seen several different approaches to generating a random DAG, not one for making a DAG from some preset connection requirements(with rules on connecting them).
I also want some way of limiting complexity of the graph. i.e limit the number of branches they can have.
Idea of what I want:
You have a bunch of different types of legos in a bin, say 30. You have rules on connecting the Legos.
Blue -> Red
Blue -> White
Red -> Yellow
Yellow -> Green/Brown
Brown -> Blue
As you all know, in addition to a color each lego had a shape.So 2 blue legos may not be the same type of lego. So The goal is to build a large structure that fits our rules. Even with our rules, we can still connect the legos in a bunch of different structures.
P.S. I am hoping this is not to general of a question. If it is, please make a note and I will try to make it more specific.
It sounds like an L-system (aka Lindenmayer system) approach would work:
Your collection of Legos is analogous to an alphabet of symbols
Your connection rules correspond to a collection of production rules that expand each symbol into some larger string of symbols
Your starting Lego represents the the initial "axiom" string from which to begin construction
The resulting geometric structures is your DAG
The simplest approach would be something like: given a Lego, randomly select a valid connection rule & add a new Lego to the DAG. From there you could add in more complexity as needed. If you need to skew the random selection to favor certain rules, you're essentially building a stochastic grammar. If the selection of a rule depends on previously generated parts of the DAG it's a type of context sensitive grammar.
Graph rewriting, algorithmically creating a new graph out of base graph, might be a more literal solution, but I personally find that L-systems easier to internalize & that researching them yields results that are not overly academic/theoretical in nature.
L-systems themselves are a category of formal grammars. It might be worth checking into some of those related ideas, but it's pretty easy (for me at least) to get side tracked by theoretical stuff at the expense of core development.
Related
I am currently writing an (exciting!) code in prolog that aims at returning an optimal reforestation plan after defining a certain purpose.
I have now, per grid cell generated a list of possible tree species to plant, and I have designed which grid cells should actually contain trees in a plan and which should be left "blank" (the density of trees also differs per reforestation purpose). I have now come to the point where I am trying to optimize
The amount of different species: If pos(1,2) can house tree_species1, tree_species2, tree_species3, and pos(4,10) can house tree_species2, tree_species3 and tree_species4 I would prefer that different values (e.g. tree_species1, tree_species4 respectively) are assigned to them. However, if this is not possible, I would love for the program to plant two of the same species rather than return "false" (which I think would happen using the "all_different/1" predicate.
Which tree is best for which purpose. For example, I would rather plant an Aspen than a White beam for biodiversity. I was thinking of connecting the different tree types to a score (biodiversity_score(Tree, Score)), but am unsure how I can use the CLP functions then to generate a "maximum" function.
I came across "labeling" but failed to see how I can manipulate this to my purpose.
I've read many blog posts, articles, presentation and videos, even inspected V8's source code, both the bytecode generator, the sea-of-nodes graph generator and the optimization phases, and still couldn't find an answer.
V8's optimizing compiler, TurboFan, uses an IR of type "sea of nodes". All of the academic articles I found about it says that it's basically a CFG combined with a data-flow graph, and as such has two type of edges to connect nodes: data edges and control edges. Basically, if you take only the data edges you form a data-flow graph while if you choose the control edges you get a control flow graph.
However, TurboFan has one more edge type: "effect edges" (and effect phis). I suppose that this is what this slide means when it says that this is not "sea" of nodes but "soup" of nodes, because I couldn't find this term anywhere else. From what I understood, effect edges help the compiler keep the structure of statements/expressions that if reordered will have a visible side-effect. The example everyone uses is o.f = o.f + 1: the load has to come before the store (or we'll read the new value), and the addition has to come before the store, too (or otherwise we'll store the old value and uselessly increment the result).
But I cannot understand: isn't this the goal of control edges? From searching through the code I can see that almost every node has an effect edge and a control edge. Their uses isn't obvious though. From what I understand, in sea of nodes you use control edges to constrain evaluation order. So why do we need both effect and control edges? Probably I'm missing something fundamental, but I can't find it.
TL;DR: What's the use of effect edges and EffectPhi nodes, and how they're different from control edges.
Great thanks.
The idea of a sea-of-nodes compiler is that IR nodes have maximum freedom to move around. That's why in a snippet like o.f = o.f + 1, the sequence load-add-store is not considered "control flow". Only conditions and branches are. So if we slightly extend the example:
if (condition) {
o.f = o.f + 1;
} else {
// something else
}
then, as you describe in the question, effect dependencies ensure that load-add-store are scheduled in this order, and control dependencies ensure that all three operations are only performed if condition is true (technically, if the true-branch of the if-condition is taken). Note that this is important even for the load; for instance, o might be an invalid object if condition is false, and attempting to load its f property might cause a segfault in that case.
I'm having trouble choosing a data structure to use to help identify resources and transitions between resources. After the graph is defined, I'd like to run analysis on the transformation between resources to determine what inputs could yield what outputs.
For example, we could take traditional currency for example:
Dollar -> 3:2 -> Euros
Euros -> 2:3 -> Dollar
Euros -> 1:100 -> Yen
Yen -> 95:1 -> Euro
Yen -> 50:1 -> T-shirt
Dollar -> 2:1 -> Candy Bar
The typical use case would be to take some starting resources, such 5 USD and 100 Japan Yen, and determine what these could be transformed into: how many candy bars? how any tshirts? The graph would be much more complicated through with hundreds of resources each with potentially dozens of transitions to other resources.
Thanks for your ideas!
This sounds like a problem for a standard graph.
Let each resource be a node and connect 2 nodes if there's a transition between them, with the edge weight being the transition ratio.
These edges will probably need to be directed, and, if the transitions are inverses, have 2 edges, one in either direction. Alternatively, if the transitions are inverses, you can have an undirected graph and define the edge weight as the transition ratio from the 'smallest' node to the 'largest' (you'll need to have some possibly arbitrary ordering of node). By "transitions are inverses" I mean, if you go from any resource to any other resource, you can also go back again, and, if you do so, you get back the same amount as you originally started with (although, this doesn't appear to hold from the example).
Then you'll probably have to use breadth-first search (or similar) to determine getting from one resource to another.
In terms of SQL, a possible structure is as follows:
Resource
ID, ...
Transition
ResourceID1, ResourceID2, Cost
I'm working on character recognition (and later fingerprint recognition) using neural networks. I'm getting confused with the sequence of events. I'm training the net with 26 letters. Later I will increase this to include 26 clean letters and 26 noisy letters. If I want to recognize one letter say "A", what is the right way to do this? Here is what I'm doing now.
1) Train network with a 26x100 matrix; each row contains a letter from segmentation of the bmp (10x10).
2) However, for the test targets I use my input matrix for "A". I had 25 rows of zeros after the first row so that my input matrix is the same size as my target matrix.
3) I run perform(net, testTargets,outputs) where outputs are the outputs from the net trained with the 26x100 matrix. testTargets is the matrix for "A".
This doesn't seem right though. Is training supposed by separate from recognizing any character? What I want to happen is as follows.
1) Training the network for an image file that I select (after processing the image into logical arrays).
2) Use this trained network to recognize letter in a different image file.
So train the network to recognize A through Z. Then pick an image, run the network to see what letters are recognized from the picked image.
Okay, so it seems that the question here seems to be more along the lines of "How do I neural networks" I can outline the basic procedure here to try to solidify the idea in your mind, but as far as actually implementing it goes you're on your own. Personally I believe that proprietary languages (MATLAB) are an abomination, but I always appreciate intellectual zeal.
The basic concept of a neural net is that you have a series of nodes in layers with weights that connect them (depending on what you want to do you can either just connect each node to the layer above and beneath, or connect every node, or anywhere in betweeen.). Each node has a "work function" or a probabilistic function that represents the chance that the given node, or neuron will evaluate to "on" or 1.
The general workflow starts from whatever top layer neurons/nodes you've got, initializing them to the values of your data (in your case, you would probably start each of these off as the pixel values in your image, normalized to be binary would be simplest). Each of those nodes would then be multiplied by a weight and fed down towards your second layer, which would be considered a "hidden layer" depending on the sum (either geometric or arithmetic sum, depending on your implementation) which would be used with the work function to determine the state of your hidden layer.
That last point was a little theoretical and hard to follow, so here's an example. Imagine your first row has three nodes ([1,0,1]), and the weights connecting the three of those nodes to the first node in your second layer are something like ([0.5, 2.0, 0.6]). If you're doing an arithmetic sum that means that the weighting on the first node in your "hidden layer" would be
1*0.5 + 0*2.0 + 1*0.6 = 1.1
If you're using a logistic function as your work function (a very common choice, though tanh is also common) this would make the chance of that node evaluating to 1 approximately 75%.
You would probably want your final layer to have 26 nodes, one for each letter, but you could add in more hidden layers to improve your model. You would assume that the letter your model predicted would be the final node with the largest weighting heading in.
After you have that up and running you want to train it though, because you probably just randomly seeded your weights, which makes sense. There are a lot of different methods for this, but I'll generally outline back-propagation which is a very common method of training neural nets. The idea is essentially, since you know which character the image should have been recognized, you compare the result to the one that your model actually predicted. If your model accurately predicted the character you're fine, you can leave the model as is, since it worked. If you predicted an incorrect character you want to go back through your neural net and increment the weights that lead from the pixel nodes you fed in to the ending node that is the character that should have been predicted. You should also decrement the weights that led to the character it incorrectly returned.
Hope that helps, let me know if you have any more questions.
Classic social networks can be represented as a graph/matrix.
With a graph/matrix one can easily compute
shortest path between 2 participants
reachability from A -> B
general statistics (reciprocity, avg connectivity, etc)
etc
Is there an ideal data structure (or a modification to graph/matrix) that enables easy computation of the above while being time aware?
For example,
Input
t = 0...100
A <-> B (while t = 0...10)
B <-> C (while t = 5...100)
C <-> A (while t = 50...100)
Sample Queries
Is A associated with B at any time? (yes)
Is A associated with B while B is associated with C? (yes. #t = 5...10)
Is C ever reachable from A (yes. # t=5 )
What you're looking for is an explicitly persistent data structure. There's a fair body of literature on this, but it's not that well known. Chris Okasaki wrote a pretty substantial book on the topic. Have a look at my answer to this question.
Given a full implementation of something like Driscoll et al.'s node-splitting structure, there are a few different ways to set up your queries. If you want to know about stuff true in a particular time range, you would only examine nodes containing data about that time range. If you wanted to know what time range something was true, you would start searching, and progressively tighten your bounds as you explore each new node. Just remember that your results might not always be contiguous - consider two people start dating, breaking up, and getting back together.
I would guess that there's probably at least one publication worth of unexplored territory in how to do interesting queries over persistent graphs, if not much more.