GUI programs in tcl. how to compile it in ns2? - user-interface

When I tried to compile a program taken from internet
proc demo {} {
canvas .c -bg white
frame .f
button .f.c -text Clear -command {.c delete all}
button .f.co -text Complete -command {showComplete .c}
button .f.tr -text Triangulate -command {showTriangulate .c}
eval pack [winfo children .f] -side left
pack .c .f -fill x -expand 1
bind .c <1> {addVertex %W %x %y}
.c bind vertex <3> {%W delete current}
}
proc showComplete w {
$w delete edge
foreach edge [completeGraph [get vertex $w]] {
showEdge $w $edge
}
}
proc showEdge {w edge {fill gray}} {
regexp {(.+)/(.+),(.+)/(.+)} $edge -> x0 y0 x1 y1
set ::length($edge) [expr {hypot($x1-$x0,$y1-$y0)}]
$w create line $x0 $y0 $x1 $y1 -tags "edge $edge" -fill $fill
}
proc get {tag w} {
set res {}
foreach v [$w find withtag $tag] {
lappend res [lindex [$w gettags $v] 1]
}
set res
}
proc completeGraph vertices {
set graph {}
foreach i $vertices {
foreach j $vertices {
if {$i<$j} {lappend graph $i,$j}
}
}
set graph
}
proc showTriangulate w {
$w delete edge
showComplete $w
wm title . Wait...
set t0 [clock clicks -milliseconds]
foreach edge [triangulate [get edge $w]] {
showEdge $w $edge red
}
wm title . [expr {[clock clicks -milliseconds] - $t0}]
}
proc triangulate graph {
while 1 {
set found 0
foreach i $graph {
foreach j $graph {
if {$i!=$j && [crossing $i $j]} {
lremove graph [longer $i $j]
set found 1
break
}
}
if $found break
}
if {!$found} break
}
set graph
}
proc crossing {edge1 edge2} {
regexp {(.+)/(.+),(.+)/(.+)} $edge1 -> x0 y0 x1 y1
regexp {(.+)/(.+),(.+)/(.+)} $edge2 -> x2 y2 x3 y3
if [adjacent $x0/$y0 $x1/$y1 $x2/$y2 $x3/$y3] {return 0}
set m1 [slope $x0 $y0 $x1 $y1]
set b1 [expr {$y0-$m1*$x0}]
set m2 [slope $x2 $y2 $x3 $y3]
set b2 [expr {$y2-$m2*$x2}]
set x [slope $m2 $b1 $m1 $b2]
expr {[between $x0 $x $x1] && [between $x2 $x $x3]}
}
proc adjacent args {
expr {[llength [lsort -unique $args]]<[llength $args]}
}
proc slope {x0 y0 x1 y1} {
# slightly "bend" a vertical line, to avoid division by zero
if {$x1==$x0} {set x1 [expr {$x1+0.00000001}]}
expr {double($y1-$y0)/($x1-$x0)}
}
proc between {a b c} {
expr {$b==[lindex [lsort -real [list $a $b $c]] 1]}
}
proc longer {edge1 edge2} {
global length
expr {$length($edge1) > $length($edge2)? $edge1: $edge2}
}
proc addVertex {w x y} {
$w create rect [expr $x-2] [expr $y-2] [expr $x+2] [expr $y+2] \
-tags "vertex $x/$y" -fill blue
}
proc lremove {varName element} {
upvar 1 $varName var
set pos [lsearch $var $element]
set var [lreplace $var $pos $pos]
}
demo
bind . <Escape> {exec wish $argv0 &; exit}
bind . <F1> {console show}
invalid command name "canvas"
while executing
"canvas .c -bg white"
(procedure "demo" line 2)
invoked from within
"demo"
In this canvas command is not reading. I am having nam(network animator) and I could compile other programs. I want to know how this can be run. anybody please help.
while compiling in ns2 I get like

wish → → ns-allinone-2.35/bin/wish8.5 ......... Example using : ./wish8.5 canvas.tcl .......... 'ns' is the otcl interpreter. 'ns' is not meant to understand all tcl commands.

Related

AWK recursive tree structure

I'm trying to parse a file that contains lines in a hierarchical structure. For example the file:
a b c
a b d
a B C
A B C
indicates that a contains b and B, that b contains c and d, that B contains C. A contains a different B which contains its own C.
This is much like a list of files.
I want to format this in a hierarchical bracketed way like:
a {
b {
c
d
}
B {
C
}
}
A {
B {
C
}
}
I couldn't come up with a decent way to do this. I thought that AWK would be my best bet, but came up short with how to actually implement it.
Context
My input is actually a list of files. I can of course separate the fields by spaces if needed, or keep them with /. The files are unordered and generated from a code-base during compile-time via inspection. My desired output is going to be a graphviz DOT file containing each file in its own subgraph.
Thus for the input:
a/b/c
a/b/d
a/B/C
A/B/C
the output would be
digraph {
subgraph cluster_a {
label = a
subgraph cluster_b {
label = b
node_1 [label=c]
node_2 [label=d]
}
subgraph cluster_B {
label = B
node_3 [label=C]
}
}
subgraph cluster_A {
label = A
subgraph cluster_B {
label = B
node_4 [label=C]
}
}
}
Does anybody know how I could get this processing done? I'm open to other tools as well, not just AWK.
NOTE: Depth is not fixed, though I could pre-compute the maximum depth if necessary. Not all leaves will be at the same depth either.
I'm open to other tools as well, not just AWK.
I offer this Python solution:
import sys
INDENT = ' '
NODE_COUNT = 1
def build(node, l):
x = l[0]
if x not in node:
node[x] = {}
if len(l) > 1:
build(node[x], l[1:])
def indent(s, depth):
print('%s%s' % (INDENT * depth, s))
def print_node(label, value, depth):
if len(value.keys()) > 0:
indent('subgraph cluster_%s {' % label, depth)
indent(' label = %s' % label, depth)
for child in value:
print_node(child, value[child], depth+1)
indent('}', depth)
else:
global NODE_COUNT
indent('node_%d [label=%s]' % (NODE_COUNT, label), depth)
NODE_COUNT += 1
def main():
d = {}
for line in sys.stdin:
build(d, [x.strip() for x in line.split()])
print('digraph {')
for k in d.keys():
print_node(k, d[k], 1)
print('}')
if __name__ == '__main__':
main()
Result:
$ cat rels.txt
a b c
a b d
a B C
A B C
$ cat rels.txt | python3 make_rels.py
digraph {
subgraph cluster_a {
label = a
subgraph cluster_b {
label = b
node_1 [label=c]
node_2 [label=d]
}
subgraph cluster_B {
label = B
node_3 [label=C]
}
}
subgraph cluster_A {
label = A
subgraph cluster_B {
label = B
node_4 [label=C]
}
}
}
If the depth is fixed at 3 levels
gawk -F/ '
{f[$1][$2][$3] = 1}
END {
n = 0
print "digraph {"
for (a in f) {
print " subgraph cluster_" a " {"
print " label = " a
for (b in f[a]) {
print " subgraph cluster_" b " {"
print " label = " b
for (c in f[a][b]) {
printf " node_%d [label=%s]\n", ++n, c
}
print " }"
}
print " }"
}
print "}"
}
' file
digraph {
subgraph cluster_A {
label = A
subgraph cluster_B {
label = B
node_1 [label=C]
}
}
subgraph cluster_a {
label = a
subgraph cluster_B {
label = B
node_2 [label=C]
}
subgraph cluster_b {
label = b
node_3 [label=c]
node_4 [label=d]
}
}
}
If the depth is arbitrary, things get complicated.

Adjust minimum and maximum size of a table in TCL

I want to create a table in Tcl/Tk gui. The minimum size of every boxes of the table will be (x=10, y=2) and if any words(inserted in any box) exceeds the box's size, then it will be adjusted towards Y-axis.
Please help me.
I have tried with this code :
proc table {w content args} {
frame $w -bg black
set r 0
foreach row $content {
set fields {}
set c 0
foreach col $row {
lappend fields [label $w.$r/$c -text $col]
incr c
}
eval grid $fields -sticky news -padx 1 -pady 1
incr r
}
set w
}
#--- Test:
table .t {
{Row Head1 Head2}
{1 abc 123123}
{2 bcd 12341234}
{3 cde 12345678901234567890}
}
pack .t
The target table will be like this :
I suggest the following. It doesn't cater for the case when a word in a sentence is longer than the maximum column size, but it works otherwise. It will word wrap if the text is a sentence (has a space in it), or character wrap otherwise.
Note that character wrap will still take effect if there is a word with length exceeding the maximum size of a column.
package require Tk
proc wrap {text len} {
if {[string len $text] <= $len} {
# No need for wrapping
} else {
if {[string first " " $text] > -1} {
# Word wrap
set flag "\\M"
} else {
# Character wrap
set flag ""
}
set re "^.{1,$len}$flag"
set result [list]
while {1} {
regexp $re [string trim $text] res
regsub $re [string trim $text] "" text
lappend result $res
if {$text eq ""} {break}
}
set text [join $result \n]
}
return $text
}
proc table {w content args} {
frame $w -bg black
set r 0
foreach row $content {
set fields {}
set c 0
foreach col $row {
set text [wrap $col 10]
lappend fields [label $w.$r/$c -text $text]
incr c
}
eval grid $fields -sticky news -padx 1 -pady 1
incr r
}
set w
}
table .t {
{Row Head1 Head2}
{1 abc 123123}
{2 bcd 12341234}
{3 cde 12345678901234567890}
{4 fgh 123456789098765432101234567890}
{5 ijk "Data Bits per Mask"}
}
pack .t
Output:

not able to sort list in tcl

I have below code in NS2 which calculates distance between two nodes and put it in a list "nbr". I want to sort out that list in ascending order as per value "d" and again store it in a list for further use for that I used lsort command but it is giving me same list that is unsorted.
please help
code:.
proc distance { n1 n2 nd1 nd2} {
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
if {$d<300} {
if {$nd2!=$nd1 && $nd2 == 11} {
set nbr "{$nd1 $nd2 $x1 $y1 $d}"
set m [lsort -increasing -index 4 $nbr]
puts $m
}
}
}
for {set i 1} {$i < $val(nn)} {incr i} {
for {set j 1} {$j < $val(nn)} {incr j} {
$ns at 5.5 "distance $node_($i) $node_($j) $i $j"
}
}
output:
{1 11 305 455 273}
{4 11 308 386 208}
{5 11 378 426 274}
{7 11 403 377 249}
{8 11 244 405 215}
{9 11 256 343 154}
{10 11 342 328 172}
{12 11 319 192 81}
{13 11 395 196 157}
{14 11 469 191 231}
{15 11 443 140 211}
{16 11 363 115 145}
{17 11 290 135 75}
{18 11 234 121 69}
{19 11 263 60 132}
{20 11 347 60 169}
Right now, you're calculating each of the distances separately, but aren't actually collecting them all into a list that can be sorted.
Let's fix this by first rewriting distance to just do the distance calculations themselves:
proc distance {n1 n2 nd1 nd2} {
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
# Why not: set d [expr hypot($x2-$x1,$y2-$y1)]
# I'm keeping *everything* we know at this point
return [list $nd1 $nd2 $n1 $n2 $d $x1 $y1 $x2 $y2]
}
Then, we need another procedure that will process the whole collection (at the time the simulator calls it) and do the sorting. It will call distance to get the individual record, since we've factored that information out.
proc processDistances {count threshold {filter ""}} {
global node_
set distances {}
for {set i 1} {$i < $count} {incr i} {
for {set j 1} {$j < $count} {incr j} {
# Skip self comparisons
if {$i == $j} continue
# Apply target filter
if {$filter ne "" && $j != $filter} continue
# Get the distance information
set thisDistance [distance $node_($i) $node_($j) $i $j]
# Check that the nodes are close enough
if {[lindex $thisDistance 4] < $threshold} {
lappend distances $thisDistance
}
}
}
# Sort the pairs, by distances
set distances [lsort -real -increasing -index 4 $distances]
# Print the sorted list
foreach tuple $distances {
puts "{$tuple}"
}
}
Then we arrange for that whole procedure to be called at the right time:
# We recommend building callbacks using [list], not double quotes
$ns at 5.5 [list processDistances $val(nn) 300 11]

lsort -unique -command for objects

I have a list of rectangles, and, I need to report an error if there are overlapping ones.
So, I've decided to use lsort -command to sort my list and, then, compare new and old lists' lengths. If they're not equal, then, there are overlapping rectangles.
Here is the piece of code that does the work:
package require Itcl
::itcl::class Region {
public method print { name } {
puts "$name: $x1_ $y1_ $x2_ $y2_"
}
public method X1 { } { return $x1_ }
public method Y1 { } { return $y1_ }
public method X2 { } { return $x2_ }
public method Y2 { } { return $y2_ }
# The x1 coordinate of the region
public variable x1_ ""
# The y1 coordinate of the region
public variable y1_ ""
# The x2 coordinate of the region
public variable x2_ ""
# The y2 coordinate of the region
public variable y2_ ""
}
# two regions will be equal <=> when they overlap each other
proc compareRegs { region1 region2 } {
return [ expr {[$region1 X2] <= [$region2 X1] || [$region1 Y2] <= [$region2 Y1] } ]
}
# reg1 and reg2 don't overlap
Region reg1
reg1 configure -x1_ 5.5 -y1_ 5.5014 -x2_ 6.5 -y2_ 5.7014
Region reg2
reg2 configure -x1_ 3.567 -y1_ 5.5014 -x2_ 3.767 -y2_ 5.7014
# reg2 = reg3
Region reg3
reg3 configure -x1_ 3.567 -y1_ 5.5014 -x2_ 3.767 -y2_ 5.7014
# create a usual list
set myList { reg1 reg2 reg3 }
# sort the list
set mySortedList [lsort -unique -command compareRegs $myList]
puts "start mySortedList"
foreach reg $mySortedList {
$reg print "reg"
}
puts "end mySortedList"
# mySortedList = {reg2}
if { [llength $mySortedList] != [llength $myList] } {
puts "ERROR: Regions must not overlap"
}
# let's see what's going on
# reg2 < reg1 is true
puts "result of reg1 < reg2: [compareRegs reg1 reg2]"
puts "result of reg2 < reg1: [compareRegs reg2 reg1]"
# reg2 = reg3 is true
puts "result of reg2 < reg3: [compareRegs reg2 reg3]"
puts "result of reg3 < reg2: [compareRegs reg3 reg2]"
# i.e, in sorted list we should have {reg2 reg1}
Seems lsort -unique -command is not working correctly or I'm doing something wrong.
How can I fix this? Or maybe there are better solutions?
Thanks in advance!
The problem is in your comparison function. Comparison functions need to return three possible values: -1 (or in fact any integer less than zero) if the first value is larger, 0 if the values are equal, and 1 (really an integer greater than zero) if the second value is larger. But the expr operators you are using (<= and ||) give boolean results, i.e., produce just 0 or 1 as values. That's just not going to work.
We need a different approach to the comparisons:
proc compareRegs { region1 region2 } {
# Compare the X values by subtracting them from each other
set cmp [expr {[$region2 X1] - [$region1 X2]}]
if {$cmp != 0.0} {
# Convert to an integer (-1 or 1)
return [expr {$cmp < 0.0 ? -1 : 1}]
}
# Compare the Y values by subtracting them from each other
set cmp [expr {[$region2 Y1] - [$region1 Y2]}]
if {$cmp != 0.0} {
# Convert to an integer (-1 or 1)
return [expr {$cmp < 0.0 ? -1 : 1}]
}
# Both equal; return an integer zero
return 0
}
Yes, this code is a bit long. Should work though.

How should I find nearest neighbors for every element in a list?

I have two sets of integers A and B (size of A less than or equal to B), and I want to answer the question, "How close is A to B?". The way I want to answer this question is by producing a measure of how far you have to go from a given a in A to find a b in B.
The specific measure I want to produce does the following: for each a, find the closest b, the only catch being that once I match a b with an a, I can no longer use that b to match any other a's. (EDIT: the algorithm I'm trying to implement will always prefer a shorter match. So if b is the nearest neighbor to more than one a, pick the a nearest to b. I'm not sure what to do if more than one a has the same distance to b, right now I'm picking the a that precedes b, but that's quite arbitrary and not necessarily optimal.) The measure that I'll for make these sets, the final product, is a histogram showing the number of pairs in the vertical axis and the distance of the pairs in the x-axis.
So if A = {1, 3, 4} and B = {1, 5, 6, 7}, I will get the following a,b pairs: 1,1, 4,5, 3,6. For these data, the histogram should show one pair with distance zero, one pair with distance 1, and one pair with distance 3.
(The actual size of these sets has an upper bound around 100,000 elements, and I read them in from disk already sorted low to high. The integers range from 1 to ~20,000,000. EDIT: also, the elements of A and B are unique, i.e. no repeated elements.)
The solution I've come up with feels a bit clunky. I'm using Perl, but the problem is more or less language agnostic.
First I make a hash, with one key for each number that appears in the union of A and B and values indicating whether each number appears in A, B, or both, e.g. $hash{5} = {a=>1, b=>1} if the number 5 appears in both data-sets. (If it only appeared in A, you'd have $hash{5} = {a=>1}.)
Next, I iterate over A to find all the hash elements that appear in A and B, mark them in the measure, and remove them from the hash.
Then, I sort all the hash keys and make each element of the hash point to its nearest neighbors, like a linked list, where a given hash element now looks like $hash{6} = {b=>1, previous=>4, next=>8}. The linked list doesn't know whether the next and previous elements are in A or B.
Then I loop over pair distances starting at d=1, and find all pairs with distance d, mark them, remove them from the hash, until there are no more elements of A to match.
The loop looks like this:
for ($d=1; #a > 0; $d++) {
#left = ();
foreach $a in #a {
$next = $a;
# find closest b ahead of $a, stop searching if you pass $d
while (exists $hash{$next}{next} && $next - $a < $d) {
$next = $hash{$next}{next};
}
if ($next is in B && $next - $a == $d) {
# found a pair at distance $d
mark_in_measure($a, $next);
remove_from_linked_list($next);
remove_from_linked_list($a);
next;
}
# do same thing looking behind $a
$prev = $a;
...
# you didn't find a match for $a
push #left, $a;
}
#a = #left;
}
This loop obviously prefers pairs that match b's that appear later than a's; I can't tell whether there's a sensible way to decide whether later is better than prior (better in terms of getting closer pairs). The main optimization I'm interested in is processing time.
Sounds like you have a particular case of the Assignment Problem (finding a minimum matching in a weighted bipartite graph).
The algorithm to solve the assignment problem is too slow for you at O(N^3) but I'm pretty sure there you can shave some of this complexity off by exploiting your particular weight function or how you only want a histogram instead of the exact matching.
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use diagnostics;
# http://www.hungarianalgorithm.com/solve.php?c=3-2-6-22--7-2-2-18--13-8-4-12--23-18-14-2&random=1
# https://www.topcoder.com/community/data-science/data-science-tutorials/assignment-problem-and-hungarian-algorithm/
# http://www.cse.ust.hk/~golin/COMP572/Notes/Matching.pdf
my #mat;
my #out_mat;
my $spaces = 6;
my $precision = 0;
my $N = 10;
my $M = 12;
my $r = 100;
my #array1; my #array2;
for my $i (1..$N) {
push #array1, sprintf( "%.${precision}f", rand($r) );
}
for my $i (1..$M) {
push #array2, sprintf( "%.${precision}f", rand($r) );
}
##array1 = ( 1, 3, 4); # $mat[i]->[j] = abs( array1[i] - array2[j] )
##array2 = ( 1, 5, 6, 7);
# 1 5 6 7
# 1 [ 0* 4 5 6 ]
# 3 [ 2 2* 3 4 ]
# 4 [ 3 1 2* 3 ]
my $min_size = $#array1 < $#array2 ? $#array1 : $#array2;
my $max_size = $#array1 > $#array2 ? $#array1 : $#array2;
for (my $i = 0; $i < #array1; $i++){
my #weight_function;
for (my $j = 0; $j < #array2; $j++){
my $dif = sprintf( "%.${precision}f", abs ($array1[$i] - $array2[$j]) );
#my $dif = sprintf( "%.${precision}f", ($array1[$i] - $array2[$j])**2 );
push #weight_function, $dif;
}
push #mat, \#weight_function;
}
# http://cpansearch.perl.org/src/TPEDERSE/Algorithm-Munkres-0.08/lib/Algorithm/Munkres.pm
Algorithm::Munkres::assign(\#mat,\#out_mat);
print "\n\#out_mat index = [";
for my $index (#out_mat) {
printf("%${spaces}d", $index);
}
print " ]\n";
print "\#out_mat values = [";
my %hash;
for my $i (0 .. $max_size){
my $j = $out_mat[$i];
last if ( $i > $min_size and $#array1 < $#array2 );
next if ( $j > $min_size and $#array1 > $#array2 );
my $dif = $mat[$i]->[$j];
printf( "%${spaces}.${precision}f", $dif );
$hash{ $dif } { $i } { 'index_array1' } = $i;
$hash{ $dif } { $i } { 'index_array2' } = $j;
$hash{ $dif } { $i } { 'value_array1' } = $array1[$i];
$hash{ $dif } { $i } { 'value_array2' } = $array2[$j];
}
print " ]\n\n";
my $soma_da_dif = 0;
foreach my $min_diferenca ( sort { $a <=> $b } keys %hash ){
foreach my $k ( sort { $a <=> $b } keys %{$hash{$min_diferenca}} ){
$soma_da_dif += $min_diferenca;
my $index_array1 = $hash{ $min_diferenca } { $k } { 'index_array1' };
my $index_array2 = $hash{ $min_diferenca } { $k } { 'index_array2' };
my $value_array1 = $hash{ $min_diferenca } { $k } { 'value_array1' };
my $value_array2 = $hash{ $min_diferenca } { $k } { 'value_array2' };
printf( " index (%${spaces}.0f,%${spaces}.0f), values (%${spaces}.${precision}f,%${spaces}.${precision}f), dif = %${spaces}.${precision}f\n",
$index_array1, $index_array2, $value_array1, $value_array2, $min_diferenca );
}
}
print "\n\nSum = $soma_da_dif\n";
#-------------------------------------------------#
#------------------ New-Package ------------------#
{ # start scope block
package Algorithm::Munkres;
use 5.006;
use strict;
use warnings;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw( assign );
our $VERSION = '0.08';
...
... <---- copy all the 'package Algorithm::Munkres' here
...
return $minval;
}
1; # don't forget to return a true value from the file
} # end scope block

Resources