Nodes are equal when their IDs are equal. IDs in one tree are unique. On the schemas, IDs of nodes are visible.
Consider tree1:
root
|
+-- CC
| |
| \-- ZZZ
| |
| \-- UU
|
\-- A
|
\-- HAH
And tree2:
root
|
+-- A
|
+-- ADD
|
\-- HAH
I would like that merge(tree1, tree2) will give this:
root
|
+-- CC
| |
| \-- ZZZ
| |
| \-- UU
|
\-- A
|
+-- HAH
|
\-- ADD
How to do it?
Node has typical methods like getParent(), getChildren().
Order of the children doesn't matter. So, the result could be also:
root
|
+-- A
| |
| +-- ADD
| |
| \-- HAH
|
\-- CC
|
\-- ZZZ
|
\-- UU
My proposition in pseudocode. Comments are more than welcome.
merge(tree1, tree2) {
for (node : tree2.bfs()) { // for every node in breadth-first traversal order
found = tree1.find(node.getParent()); // find parent in tree1
if (found == null) // no parent?
continue; // skip it, it's root
if (!found.getChildren().contains(node)) // no node from tree2 in tree1?
found.add(node); // add it
}
return tree1;
}
The basic algorithm is not hard:
def merge_trees (t1, t2):
make_tree(map(merge_trees,assign(getChildren(t1),getChildren(t2),tree_similarity)))
make_tree(children): create a tree with the given list of children
map(f,list): calls function f on each element of list and return the list of return values
assign(list1,list2,cost_function): implements the Hungarian algorithm, returning the list of matched pairs
The trick is in defining tree_similarity which would have to call assign recursively.
In fact, the efficient implementation would have to cache the return values of the assign calls.
Related
I try to improve our build process and use 2-3 predefined parameters for run on one single build.
Description: we have build configuration with parameters C1, C2, C3 and related build steps B1, B2, B3. They link to each other C1-B1, C2-B2, C3-B3. In this scheme all works fine, I pass parameters like mentioned here - How to pass Arguments between build configuration steps in team city?,
but I'm a bit worried because B1, B2, B3 are full copy each other and this i would like to improve it. Only one problem I couldn't find any mechanism to pass parameters from different configuration.If I use %dep. mechanism i can use parameter from only one configuration.
UPD: Currect scheme
+---+ +---+ +---+
| | | | | |
| C1| | C2| | C3|
| | | | | |
+-+-+ +-+-+ +-+-+
| | |
| | |
+-v-+ +-v-+ +-v-+
| | | | | |
| B1| | B2| | B3|
| | | | | |
+---+ +---+ +---+
the desired scheme:
+---+ +---+ +---+
| | | | | |
| C1| | C2| | C3|
| | | | | |
+-+-+ +-+-+ +-+-+
| | |
| | |
| +-v--+ |
| | | |
| | | |
+-----> B1 <----+
| |
+----+
C1, C2, C3 setup configuration parameters
B1 contains only build steps, like clean, build, dist
Could anyone help me with that? Any ideas?
In your case, you can introduce a TeamCity Metarunner. The idea is that you combine multiple build steps with parameters, and extract them as new entity, available as build runner.
See this documentation section for step by step instructions on creating a metarunner.
You can define a parameter in the template, call it, for example, external.param and give no definition.
Then, in each configuration (C1, C2 and C3) define the value of this parameter as reference to specific dependency.
external.param = %dep.<source_cfg_id>.<source_param_name>%
According to RFC - RFC 6020 - LeafRef I can understand that the leaf can contain a leafref which inturn have the path pointing to the instance which is referenced but question is how many leafrefs are possible for one leaf? Only one or many?
Ex.
leaf mgmt-interface {
type leafref {
path "../interface/name";
}
type leafref {
path "../interface/ip";
}
}
Is the above possible?
A leafref may only target a single leaf or leaf-list node via path. There may only be one type substatement to a leaf (also applies to leaf-list, typedef) and there may only be a single path substatement to type.
7.6.2. The leaf's Substatements
+--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| config | 7.19.1 | 0..1 |
| default | 7.6.4 | 0..1 |
| description | 7.19.3 | 0..1 |
| if-feature | 7.18.2 | 0..n |
| mandatory | 7.6.5 | 0..1 |
| must | 7.5.3 | 0..n |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| type | 7.6.3 | 1 | <--
| units | 7.3.3 | 0..1 |
| when | 7.19.5 | 0..1 |
+--------------+---------+-------------+
12. YANG ABNF Grammar
type-stmt = type-keyword sep identifier-ref-arg-str optsep
(";" /
"{" stmtsep
type-body-stmts
"}")
type-body-stmts = numerical-restrictions /
decimal64-specification /
string-restrictions /
enum-specification /
leafref-specification /
identityref-specification /
instance-identifier-specification /
bits-specification /
union-specification
leafref-specification =
;; these stmts can appear in any order
path-stmt stmtsep
[require-instance-stmt stmtsep]
path-stmt = path-keyword sep path-arg-str stmtend
Note: it is not possible to use union for leafref types in YANG 1.0. This has changed in YANG 1.1 however, where any built-in YANG type may appear inside a union.
9.12. The union Built-In Type
A member type can be of any built-in or derived type, except it MUST
NOT be one of the built-in types "empty" or "leafref".
Is there a way to walk only one level of the tree with SNMP?
Example:
I want to know how many tables my tree has but I don't want to walk each entry. It would be nice to only walk the parent level and return all OIDs for the root node of the table.
Rather than use snmpwalk (which I don't think supports the one level walk mentioned in question), it may be easier to get such info from the MIB file (instead of interrogating the agent).
It may be convenient to use tool like e.g. netsnmp snmptranslate. E.g. to see what tables live in SNMPv2-MIB::system i.e. 1.3.6.1.2.1.1, you could ...
snmptranslate -M +. -m +ALL -Tp -On SNMPv2-MIB::system
+--system(1)
|
+-- -R-- String sysDescr(1)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- ObjID sysObjectID(2)
+-- -R-- TimeTicks sysUpTime(3)
| |
| +--sysUpTimeInstance(0)
|
+-- -RW- String sysContact(4)
| Textual Convention: DisplayString
| Size: 0..255
+-- -RW- String sysName(5)
| Textual Convention: DisplayString
| Size: 0..255
+-- -RW- String sysLocation(6)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- INTEGER sysServices(7)
| Range: 0..127
+-- -R-- TimeTicks sysORLastChange(8)
| Textual Convention: TimeStamp
|
+--sysORTable(9)
|
+--sysOREntry(1)
| Index: sysORIndex
|
+-- ---- INTEGER sysORIndex(1)
| Range: 1..2147483647
+-- -R-- ObjID sysORID(2)
+-- -R-- String sysORDescr(3)
| Textual Convention: DisplayString
| Size: 0..255
+-- -R-- TimeTicks sysORUpTime(4)
Textual Convention: TimeStamp
I have a directed graph (more specifically, a control flow graph), and each of the vertices has a set of properties.
I'd like to find (or write) an algorithm that, given a vertex V with property P, finds the longest path to some vertex E such that all vertices along all possible paths from V to E contain the property P.
Example 1
Say I had the following graph. (Please excuse the bad ascii drawing.)
+----+
+--------+P +--------+
| +----+ |
| V1 |
| |
| |
+--v--+ |
+----+P ++ |
| +-----++ +--v--+
| | +----+P |
| | | +-----+
+--v--+ +--v--+ |
|P +-+ +-+P | |
+-----+ | | +-----+ |
| | |
| | |
+v-v--+ |
V6 |P +---------+ |
+-----+ | |
| |
| |
| |
| |
+-v--v-+
V7 |P |
+---+--+
|
|
+---v--+
V8 |!P |
+------+
Starting at V1, the longest path where P always holds on all possible paths is V1 -> V7. Note that the other paths, say V1 -> V6, are "valid" in that P always holds, but V1 -> V7 is the longest.
Example 2
This example is the same as above, except now the P doesn't hold in V3:
+----+
+--------+P +--------+
| +----+ |
| V1 |
| |
| |
+--v--+ |
+----+P ++ |
| +-----++ +--v--+
| | +----+!P | V3
| | | +-----+
+--v--+ +--v--+ |
|P +-+ +-+P | |
+-----+ | | +-----+ |
| | |
| | |
+v-v--+ |
V6 |P +---------+ |
+-----+ | |
| |
| |
| |
| |
+-v--v-+
V7 |P |
+---+--+
|
|
+---v--+
V8 |!P |
+------+
In this case, starting at V1, the longest path where P always holds in all possible paths is V1 -> V6. The path V1 -> V7 is not valid, because there is a path between V1 and V7 in which P does not hold.
Further notes about my situation
The graph could be cyclic.
The graph will be of a "small to medium" size, with maybe 1000 vertices or less.
The graph does not necessarily always have one root and one leaf, like my examples above.
Question
Is there a standard algorithm for computing such paths?
The problem has no known efficient solution, as it is easily reduceable from Hamiltonian Path Problem, which says - given a graph - is there a path that goes through all vertices exactly once?
The reduction is simple - Given Hamiltonian Path problem, label all nodes with p, and find longest path. Since Hamiltonian path is NP-Complete, so is this problem, and there is no known polynomial solution to it.
An alternative is using a brute-force search (simplest form is generate all permutations and chose the best valid one) - but that will become impossible for large graphs. You might also need to consider using a heuristic approach (that finds a "good" solution, but not the optimal), like Genetic Algorithms.
Another possible solution is to reduce the problem to a Traveling Salesman Problem, and use some existing TSP solver. Note that while this problem is also NP-hard, since it is well-studied, there are some pretty efficient solutions for medium size graphs.
Also, if your graph happens to be somehow 'special' (a DAG for example), you might utilize some smart techniques to achieve significant speed up to polynomial time, like Dynamic Programming.
I need to write a program to draw all possible paths in a given matrix that can be had by moving in only left, right and up direction.
One should not cross the same location more than once. Note also that on a particular path, we may or may not use motion in all possible directions.
Path will start in the bottom-left corner in the matrix and will reach the top-right corner.
Following symbols are used to denote the direction of the motion in the current position:
+---+
| > | right
+---+
+---+
| ^ | up
+---+
+---+
| < | left
+---+
The symbol * is used in the final location to indicate end of path.
Example:
For a 5x8 matrix, using left, right and up directions, 2 different paths are shown below.
Path 1:
+---+---+---+---+---+---+---+---+
| | | | | | | | * |
+---+---+---+---+---+---+---+---+
| | | > | > | > | > | > | ^ |
+---+---+---+---+---+---+---+---+
| | | ^ | < | < | | | |
+---+---+---+---+---+---+---+---+
| | > | > | > | ^ | | | |
+---+---+---+---+---+---+---+---+
| > | ^ | | | | | | |
+---+---+---+---+---+---+---+---+
Path 2
+---+---+---+---+---+---+---+---+
| | | | > | > | > | > | * |
+---+---+---+---+---+---+---+---+
| | | | ^ | < | < | | |
+---+---+---+---+---+---+---+---+
| | | | | | ^ | | |
+---+---+---+---+---+---+---+---+
| | | > | > | > | ^ | | |
+---+---+---+---+---+---+---+---+
| > | > | ^ | | | | | |
+---+---+---+---+---+---+---+---+
Can anyone help me with this?
I tried to solve using lists. It i soon realized that i am making a disaster. Here is the code i tried with.
solution x y = travel (1,1) (x,y)
travelRight (x,y) = zip [1..x] [1,1..] ++ [(x,y)]
travelUp (x,y) = zip [1,1..] [1..y] ++ [(x,y)]
minPaths = [[(1,1),(2,1),(2,2)],[(1,1),(1,2),(2,2)]]
travel startpos (x,y) = rt (x,y) ++ up (x,y)
rt (x,y) | odd y = map (++[(x,y)]) (furtherRight (3,2) (x,2) minPaths)
| otherwise = furtherRight (3,2) (x,2) minPaths
up (x,y) | odd x = map (++[(x,y)]) (furtherUp (2,3) (2,y) minPaths)
| otherwise = furtherUp (2,3) (2,y) minPaths
furtherRight currpos endpos paths | currpos == endpos = (travelRight currpos) : map (++[currpos]) paths
| otherwise = furtherRight (nextRight currpos) endpos ((travelRight currpos) : (map (++[currpos]) paths))
nextRight (x,y) = (x+1,y)
furtherUp currpos endpos paths | currpos == endpos = (travelUp currpos) : map (++[currpos]) paths
| otherwise = furtherUp (nextUp currpos) endpos ((travelUp currpos) : (map(++[currpos]) paths))
nextUp (x,y) = (x,y+1)
identify lst = map (map iden) lst
iden (x,y) = (x,y,1)
arrows lst = map mydir lst
mydir (ele:[]) = "*"
mydir ((x1,y1):(x2,y2):lst) | x1==x2 = '>' : mydir ((x2,y2):lst)
| otherwise = '^' : mydir ((x2,y2):lst)
surroundBox lst = map (map createBox) lst
bar = "+ -+"
mid x = "| "++ [x] ++" |"
createBox chr = bar ++ "\n" ++ mid chr ++ "\n" ++ bar ++ "\n"
This ASCII grids are much more confusing than enlightening. Let me describe a better way to represent each possible path.
Each non-top row will have exactly one cell with UP. I claim that once each of the UP cells has been chosen that the LEFT and RIGHT and EMPTY cells can be determined. I claim that all possible cells in each of the non-top rows can be UP in all combination.
Each path is thus isomorphic to a (rows-1) length list of numbers in the range (1..columns) that determine the UP cells. The number of allowed paths is thus columns^(rows-1) and enumerating the possible paths in this format should be easy.
Then you could make a printer that converts this format to the ASCII art. This may be annoying, depending on skill level.
Looks like a homework so I will try to give enough hints
Try first filling number of paths from a cell to your goal.
So
+---+---+---+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | * |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
The thing to note here is from the cell in the top level there will always be one path to the *.
Number of possible path from cells in the same row will be same. You can realize this as all the paths will ultimately have to move up as there is no down action so in any path the cell above the current row can be reached by any cell in the current row.
You can feel the all possible paths from the current cell has its relation with the possible paths from the cell left,right and above. But as we know we can find all possible paths from only one cell in a row and rest of cells' possible paths will be some movements in the same row followed by a suffix of possible paths from that cell.
Maybe I will give you a example
+---+---+---+
| 1 | 1 | * |
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
You know all possible paths from cells in the first row. You need to find the same in the second row. So a good strategy would be to do it for the right most cell
+---+---+---+
| > | > | * |
+---+---+---+
| ^ | < | < |
+---+---+---+
| | | |
+---+---+---+
+---+---+---+
| | > | * |
+---+---+---+
| | ^ | < |
+---+---+---+
| | | |
+---+---+---+
+---+---+---+
| | | * |
+---+---+---+
| | | ^ |
+---+---+---+
| | | |
+---+---+---+
Now finding this for rest of the cells in the same row is trivial using these as I have told before.
In the end if you have m X n matrix the number of paths from bottom-left corner to top-right corner will be n^(m-1).
Another way
This way is not very optimal but easy to implement. Consider m X n grid
Find the path of longest length. You dont need the exact path just the number of <,>,^.
You can find the direct formula in terms of m and n.
Like
^ = m - 1
< = (n-1) * floor((m-1)/2)
> = (n-1) * (floor((m-1)/2) + 1)
Any valid path will be a prefix of the permutations of this which you can search exhaustively. Use permutations from Data.List to get all possible permutations. Then make a function which given a path strips a valid path from this. map this over the list of permutations and remove duplicates. The thing to note is path will be a prefix of what you get from permutation, so there can be several permutations for the same path.
Can you create that matrix and define the "fields"? Even if you can't (a specific matrix is given), you can map an [(Int, Int)] matrix (which sounds reasonable for this kind of task) to your own representation.
Since you didn't specify what your skill level was, I hope you don't mind that I suggest that you first try to create some kind of a grid in order to have something to work on:
data Status = Free | Left | Right | Up
deriving (Read, Show, Eq)
type Position = (Int, Int)
type Field = (Position, Status)
type Grid = [Field]
grid :: Grid
grid = [((x, y), stat) | x <- [1..10], y <- [1..10], let stat = Free]
Of course there are other ways to achieve this. Afterwards you can define some movement, map Position to Grid index and Statuses to printable characters... Try to fiddle with it and you might get some ideas.