I am working on implementing "Goal-based vector field pathfinding" (demonstrated in the article at this link) It requires that I label every node in my world graph with a path distance from the goal node and recommends using a brushfire (wavefront) algorithm to do this. This is the area I am having issues in. When I get to the 8th iteration of my while loop and the 6th iteration of my nested for, I get a nil reference error on the marked line.
g is my graph, which has an 8-way adjacency list form.
q is an instance of this FIFO lua library.
rtx and rty are the x and y coords of the root node.
d is an iterator added to keep track of the path distance assigned to each node.
The structure of each node in the graph is not the same as the structure of a node being processed.
Node for processing:
n = {}
n[1] = x coord
n[2] = y coord
n[3] = adjacency list (eight entries)
n.vX = x componant of vector for vector field
n.vY = y componant of vector for vector field
Node stored in graph:
n = {}
n[1] = adjacency list
n.vX = x componant of vector for vector field
n.vY = y componant of vector for vector field
Beneath is my implementation so far. The t in the for loop is just a temporary node used to pass information along to the queue. BTW t is where the distance of all the nodes gets set.
local function brushFire( g, rtx, rty )
local q = q.new()
local s = {}
s[1] = rtx
s[2] = rty
s[3] = g[rtx][rty][3]
s.dist = 0
q:pushRight( s )
s = nil
local d = 0
while( table.getn( q.list[q.first] ) ~= 0 ) do
print( d )
local n = q:popLeft()
setDist( g, n )
print( #n[3] )
for i = 1, #n[3] do
print( ":"..i )
if( g[n[3][i][4]][n[3][i][2]].v ~= true ) then
g[n[3][i][5]][n[3][i][2]].v = true
local t = {}
t[1] = n[3][i][1]
t[2] = n[3][i][2]
t[3] = g[n[3][i][7]][n[3][i][2]][1] <------Error here
t.dist = d
q:pushRight( t )
t = nil
end
end
d = d + 1
end
end
Let me know if you need more information in order to answer my question.
I found the answer to my problem. If anyone wants to use the source, I am posting it below:
Queue module:
local q = {}
local q_mt = { __index = q }
function q.new()
local nq = { first = 0, last = -1, list = {} }
return setmetatable( nq, q_mt )
end
function q:pushLeft( value )
local first = self.first - 1
self.first = first
self.list[first] = value
end
function q:pushRight( value )
local last = self.last + 1
self.last = last
self.list[last] = value
end
function q:popLeft()
local first = self.first
if first > self.last then error( "list is empty" ) end
local value = self.list[first]
self.list[first] = nil
self.first = first + 1
return value
end
function q:popRight()
local last = self.last
if self.first > last then error( "list is empty" ) end
local value = self.list[last]
self.list[last] = nil
self.last = last - 1
return value
end
return q
The following module creates a vector field which points towards a goal when pathFind.findPath is called:
local q = require( "Queue" )
local pathFind = {}
local pathFind_mt = { __index = pathFind }
-- Private Functions
local function genDistMap( g, rtx, rty ) -<-<-<- genDistMap is the brushfire part
local q = q.new()
local g = g
g[rtx][rty].v = true
g[rtx][rty].dist = 0
local s = {}
s[1] = rtx
s[2] = rty
s[3] = g[rtx][rty][1]
s.dist = 0
q:pushRight( s )
s = nil
while( q.list[q.first] ~= nil ) do
local n = q:popLeft()
for i = 1, #n[3] do
local x, y = n[3][i][1], n[3][i][2]
if( g[x][y].v ~= true ) then
g[x][y].v = true
local t = {}
t[1] = x
t[2] = y
t[3] = g[x][y][1]
t.dist = n.dist + 1
g[x][y].dist = n.dist + 1
q:pushRight( t )
t = nil
end
end
end
return g
end
local function genVectorField( nodes )
local nodes = nodes
for i = 2, #nodes - 1 do
for j = 2, #nodes[i] - 1 do
local a = nodes[i - 1][j].dist - nodes[i + 1][j].dist
local b = nodes[i][j - 1].dist - nodes[i][j + 1].dist
local c = math.sqrt( a*a + b*b )
nodes[i][j].vX = a/c*5
nodes[i][j].vY = b/c*5
end
end
return nodes
end
-- Public Functions
function pathFind.new()
local newPathFind = {}
return setmetatable ( newPathFind, pathFind_mt )
end
function pathFind.findPath( nodeSet, rootX, rootY )
local nodes = nodeSet
nodes = genDistMap( nodes, rootX, rootY )
nodes = genVectorField( nodes )
return( nodes )
end
return pathFind
Related
I am doing some tests to see where I can improve the performance of my lua code.
I was reading this document: https://www.lua.org/gems/sample.pdf
and I thought using integers as table indices should be considerably faster since it uses the array part of tables and does not require hashing.
So I've written this test program:
print('local x=0 local y=0 local z=0')
local x=0 local y=0 local z=0
t0 = os.clock()
for i=1,1e7 do
x = 1
y = 2
z = 3
end
print(os.clock()-t0 .. "\n")
print("tab = {1,2,3}")
tab = {1,2,3}
t0 = os.clock()
for i=1,1e7 do
tab[1] = 1
tab[2] = 2
tab[3] = 3
end
print(os.clock()-t0 .. "\n")
print("tab = {[1]=1,[2]=2,[3]=3}")
tab = {[1]=1,[2]=2,[3]=3}
t0 = os.clock()
for i=1,1e7 do
tab[1] = 1
tab[2] = 2
tab[3] = 3
end
print(os.clock()-t0 .. "\n")
print("tab = {a=1,b=2,c=3}")
tab = {a=1,b=2,c=3}
t0 = os.clock()
for i=1,1e7 do
tab.a = 1
tab.b = 2
tab.c = 3
end
print(os.clock()-t0 .. "\n")
print('tab = {["bli"]=1,["bla"]=2,["blu"]=3}')
tab = {["bli"]=1,["bla"]=2,["blu"]=3}
t0 = os.clock()
for i=1,1e7 do
tab["bli"] = 1
tab["bla"] = 2
tab["blu"] = 3
end
print(os.clock()-t0 .. "\n")
print("tab = {verylongfieldname=1,anotherevenlongerfieldname=2,superincrediblylongfieldname=3}")
tab = {verylongfieldname=1,anotherevenlongerfieldname=2,superincrediblylongfieldname=3}
t0 = os.clock()
for i=1,1e7 do
tab.verylongfieldname = 1
tab.anotherevenlongerfieldname = 2
tab.superincrediblylongfieldname = 3
end
print(os.clock()-t0 .. "\n")
print('local f = function(p1, p2, p3)')
local f = function(p1, p2, p3)
x = p1
y = p2
z = p3
return x,y,z
end
local a=0
local b=0
local c=0
t0 = os.clock()
for i=1,1e7 do
a,b,c = f(1,2,3)
end
print(os.clock()-t0 .. "\n")
print('local g = function(params)')
local g = function(params)
x = params.p1
y = params.p2
z = params.p3
return {x,y,z}
end
t0 = os.clock()
for i=1,1e7 do
t = g{p1=1, p2=2, p3=3}
end
print(os.clock()-t0 .. "\n")
I've ordered the blocks by what I expected to be increasing time consumption. (I wasn't sure about the function calls, that was just a test.) But here are the surprising results:
local x=0 local y=0 local z=0
0.093613
tab = {1,2,3}
0.678514
tab = {[1]=1,[2]=2,[3]=3}
0.83678
tab = {a=1,b=2,c=3}
0.62888
tab = {["bli"]=1,["bla"]=2,["blu"]=3}
0.733916
tab = {verylongfieldname=1,anotherevenlongerfieldname=2,superincrediblylongfieldname=3}
0.536726
local f = function(p1, p2, p3)
0.475592
local g = function(params)
3.576475
And even the long field names that should cause the longest hashing process are faster than array accessing with integers. Am I doing something wrong?
The 6th page(actual page 20) of the document you linked explains what you are seeing.
If you write something like {[1] = true, [2] = true, [3] = true}, however, Lua is not smart enough to detect that the given expressions (literal numbers, in this case) describe array indices, so it creates a table with four slots in
its hash part, wasting memory and CPU time.
You can only gain a major benefit of the array part when you assign a table using no keys.
table = {1,2,3}
If you are reading/writing to a table or array that already exists you will not see a large deviation in processing time.
The example in the document includes the creation of the table in the for loop
for i = 1, 1000000 do
local a = {true, true, true}
a[1] = 1; a[2] = 2; a[3] = 3
end
Results with all local variables inside the loops. Edit: Lengthened long string to 40 bytes as pointed out by siffiejoe
local x=0 local y=0 local z=0
0.18
tab = {1,2,3}
3.089
tab = {[1]=1,[2]=2,[3]=3}
4.59
tab = {a=1,b=2,c=3}
3.79
tab = {["bli"]=1,["bla"]=2,["blu"]=3}
3.967
tab = {verylongfieldnameverylongfieldnameverylongfieldname=1,anotherevenlongerfieldnameanotherevenlongerfieldname=2,superincrediblylongfieldnamesuperincrediblylongfieldname=3}
4.013
local f = function(p1, p2, p3)
1.238
local g = function(params)
6.325
Additionally lua preforms the hashes differently for different key types.
The source code can be viewed here 5.2.4 ltable.c, this contains the code I will be discussing.
The mainposition function handles that decision making on which hash to preform
/*
** returns the `main' position of an element in a table (that is, the index
** of its hash value)
*/
static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNUMBER:
return hashnum(t, nvalue(key));
case LUA_TLNGSTR: {
TString *s = rawtsvalue(key);
if (s->tsv.extra == 0) { /* no hash? */
s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash);
s->tsv.extra = 1; /* now it has its hash */
}
return hashstr(t, rawtsvalue(key));
}
case LUA_TSHRSTR:
return hashstr(t, rawtsvalue(key));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
return hashpointer(t, pvalue(key));
case LUA_TLCF:
return hashpointer(t, fvalue(key));
default:
return hashpointer(t, gcvalue(key));
}
}
When the key is a Lua_Number we call hashnum
/*
** hash for lua_Numbers
*/
static Node *hashnum (const Table *t, lua_Number n) {
int i;
luai_hashnum(i, n);
if (i < 0) {
if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */
i = 0; /* handle INT_MIN */
i = -i; /* must be a positive value */
}
return hashmod(t, i);
}
Here are the other hash implementations for the other types:
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p) hashpow2(t, p)
/*
** for some types, it is better to avoid modulus by power of 2, as
** they tend to have many 2 factors.
*/
#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
#define hashpointer(t,p) hashmod(t, IntPoint(p))
These hashes resolve down to 2 paths hashpow2 and hashmod. LUA_TNUMBER use hashnum > hashmod and LUA_TSHRSTR use hashstr > hashpow2
I want to divide number without divide operator
def divede_me(val,ded)
i = 1; new_num=0
rem = val % ded
val = val - rem
while (val != new_num)
i += 1
new_num = ded * i
end
return i
end
p divede_me(14,4)
above script return 3 but i want floating point also (for Ex. 3.5) and best way to write above script.
def divide_me(val,ded)
i = 1; new_num=0
rem = val.to_f % ded
val = val - rem
while (val != new_num)
i += 1
new_num = ded * i
end
temp = 0.01
temp += 0.01 until ded * temp >= rem
return i + temp.round(2)
end
p divide_me(14,4)
=>3.5
p divide_me(15,4)
=>3.75
p divide_me(16,7)
=>2.29
Expanding on your existing code, this will get you to reasonably accurate 2 decimal places. Remove the .round(2) to see how inaccurate floats are.
This logic may help you
val = 14
ded = 4
r = val % ded
value = val -r
v_ck = 0
i = 0
while( value != v_ck )
i+=1
v_ck = ded * i
end
ded_ck = 0
j = 0
while(ded_ck != ded)
j += 1
ded_ck = r * j
end
puts i.to_s+"."+j.to_s
A1, B1, C1, A2, B2 and C2 are 6 matrix with the same dimensions 4435X2000.
I have to find the values i, j and k for which A1(k,2000) == A2(i,j) and B1(k,2000) == B2(i,j) and C1(k,2000) == C2(i,j) , with the condition X(k)==1 and Y(i,j)==1
The objective is to find: counter, L, T and D
Is there a way to make this code faster? Can I avoid loops?
counter=0;
L(1)=0;
T(1)=0;
D(1)=0;
for k=1:4435
if X(k)==1 % X is a vector (4435x1)
F(k,:) = [A1(k,2000) B1(k,2000) C1(k,2000)]
for i=1:4435
for j=100:1999
if Y(i,j)==1 % Y is a matrix (4435x1999)
if F(k,:) == [A2(i,j) B2(i,j) C2(i,j)]
counter = counter+1;
L(counter)=k;
T(counter)=i;
D(counter)=j;
end
end
end
end
end
end
I want a solution that will save me at least 80% of the computation time!
and not have the error message: Out of memory
See how this works out for you -
%// Store X-Y data by calling X() and Y() functions
X_data = X(1:4435);
Y_data = Y(1:4435,100:1999);
range1 = 100:1999 %// define range for columns
A2 = A2(:,range1); %// Crop out A2, B2, C2 based on column-range
B2 = B2(:,range1);
C2 = C2(:,range1);
Y_data = Y_data(:,range1)==1;
%// Indices for dim-3
idx_X = find(X_data==1)
%// Map X==1 onto A1, B1, C1
A1Lr = A1(X_data==1,end)
B1Lr = B1(X_data==1,end)
C1Lr = C1(X_data==1,end)
%// Setup output array to store L, T, D as single Nx3 output array
out = zeros(sum(Y_data(:))*numel(A1Lr),3);
%// Try out(sum(Y_data(:)==1)*numel(A1Lr),3)=0; instead for speed!
%// Start collecting output indices
count = 1;
for iter1 = 1:numel(A1Lr)
[R,C] = find(Y_data & A2==A1Lr(iter1) & B2==B1Lr(iter1) & C2==C1Lr(iter1));
nR = numel(R);
out(count:count+nR-1,:) = [R C repmat(iter1,nR,1)];
count = count + nR;
end
out(find(out(:,1)==0,1):end,:)=[];
%// Packup the outputs
T = out(:,1)
D = out(:,2) + range1(1)-1
L = idx_X(out(:,3))
It is very difficult to determine what your code is actually supposed to accomplish, without really working to interpret your code. However, I'll give it a crack:
% Determine where X is true.
XTrue = X == 1;
% Extract values from A1,B1,C1 where X is true.
F ( XTrue , 1 : 3 ) = [ A1(XTrue,2000) B1(XTrue,2000) C1(XTrue,2000) ];
% Determine where Y is true.
YTrueIndex = find ( Y == 1 );
% Determine where the extracted values match
counter = [];
L = [];
T = [];
D = [];
for ( ii = 1 : length(YTrueIndex) )
indexCurrent = YTrueIndex(ii)
FRowsThatMatch = F(:,1)==A2(indexCurrent) & F(:,2)==B2(indexCurrent) & F(:,3)==C2(indexCurrent);
matchCount = length ( find ( FRowsThatMatch ) );
if ( matchCount > 0 )
counter = counter + matchCount;
[ i , j ] = ind2sub ( size ( Y ) , indexCurrent );
L = [ L , find ( FRowsThatMatch ) ];
T = [ T , ones(matchCount,1)*i ];
D = [ D , ones(matchCount,2)*j ];
end
end
I've got a specific type of the planar graph and I found it interesting to search for an algorithm which will color its vertices legally. About this type of graph, it's very easy and cool:
Consider any tree T with n>2 vertices and k leaves. Let's denote G(T) as a graph constructed from T by connecting its leaves into k-cycle in such way that G(T) is planar.
And the problem I came up with is to color G(T) with 3 colors. Clearly, G(T) as a planar graph, is 4-colorable, but I think (don't have a proof) that it is almost always 3-colorable due to its simplicity. Almost always means that only if T is a star and only with odd number of leaves, then G(T) is 4-colorable.
I am looking for some algorithm, or maybe proof of my assumptions which could be easily transformed into an algorithm. I would be very very grateful for any help, hints.
In case I wasn't clear enough I'll give an example:
Let T be a tree with edges E(T) = { {1,2}, {2,3}, {2,4}, {4,5} } and then E(G(T)) = sum of the sets: E(T) and { {1,5}, {5,3}, {3,1} }, since we are connecting leaves 1,5,3 into a cycle.
local Edges_of_Tree = {{1,2}, {2,3}, {2,4}, {4,5}}
local Cycle_of_Leaves = {1,5,3}
local color1 = 'Red'
local color2 = 'Green'
local color3 = 'Blue'
local vert = {}
local vert_arr = {}
local function add_edge(v1, v2)
assert(v1 ~= v2)
if not vert[v1] then
vert[v1] = {deg = 0, adj = {}}
table.insert(vert_arr, v1)
end
vert[v1].deg = vert[v1].deg + 1
assert(not vert[v1].adj[v2], 'multiple edges between '..v1..' and '..v2)
vert[v1].adj[v2] = true
end
for _, edge in ipairs(Edges_of_Tree) do
local v1, v2 = unpack(edge)
add_edge(v1, v2)
add_edge(v2, v1)
end
table.sort(vert_arr)
local leaf_ctr = 0
local root
for v, vv in pairs(vert) do
if vv.deg == 1 then
leaf_ctr = leaf_ctr + 1
else
root = v
end
end
assert(#vert_arr > leaf_ctr + 1, 'tree is a star')
assert(leaf_ctr == #Cycle_of_Leaves, 'invalid Cycle_of_Leaves')
for _, v in ipairs(Cycle_of_Leaves) do
assert(vert[v] and vert[v].deg == 1 and vert[v].color == nil,
'invalid Cycle_of_Leaves')
vert[v].color = false
end
local function recursive_paint_inodes(v, color, prev_v)
assert(vert[v].color == nil, 'a cycle in tree found')
vert[v].color = color
local next_color = (color1..color2):gsub(color, '')
for next_v in pairs(vert[v].adj) do
if next_v ~= prev_v and vert[next_v].deg > 1 then
recursive_paint_inodes(next_v, next_color, v)
end
end
end
recursive_paint_inodes(root, color1)
local front
for i = 1, leaf_ctr do
local vv = vert[Cycle_of_Leaves[i]]
vv.next = Cycle_of_Leaves[i % leaf_ctr + 1]
vv.prev = Cycle_of_Leaves[(i - 2) % leaf_ctr + 1]
local parent = next(vv.adj)
if parent ~= next(vert[vv.prev].adj) then
assert(not vert[parent].conn_to_leaf, 'graph is non-planar')
vert[parent].conn_to_leaf = true
front = Cycle_of_Leaves[i]
end
end
vert[next(vert[vert[front].prev].adj)].color = color3
vert[front].color = color3
local tricolor = color1..color2..color3
local leaf = front
for i = 1, leaf_ctr - 1 do
local prev_color = vert[leaf].color
leaf = vert[leaf].next
local parent_color = vert[next(vert[leaf].adj)].color
local enabled_colors = tricolor:gsub(prev_color, ''):gsub(parent_color, '')
vert[leaf].color = enabled_colors:match(color1)
or enabled_colors:match(color2) or color3
end
for _, v in ipairs(vert_arr) do
print(v..' '..vert[v].color)
end
This code is written in Lua.
You can test it in action there.
Could anyone help me with a way to randomly fill a table with N values, where the values are 1,...,M allowing no duplicates ?
Cheers.
local M, N, tNonFinal, tFinal = 500, 20, {}, {}
math.randomseed( os.time() )
for i = 1, N, 1 do
local iRandom = math.random(1, M)
while tNonFinal[iRandom] do
iRandom = math.random(1, M)
end
table.insert( tNonFinal, iRandom, true )
tFinal[i] = iRandom
end
Your required table will be tFinal. You can also add a condition where if M < N then N = M end
This may help you...
local myArray = {}
local valueArray = {1,2,3,4,5,6,7,8,9,10} -- let it be the array with values 1,2...M
local index = 0
local isFetched = {}
for i=1,#valueArray do
isFetched[i] = 0
end
local randomValue = 0
local function addTomyArray()
randomValue = math.random(#valueArray)
if(isFetched[randomValue]==0)then
index = index + 1
isFetched[randomValue] = 1
myArray[index] = valueArray[randomValue]
if(index==#valueArray)then
for i=1,#myArray do
print(myArray[i]) -- result : shuffled array
end
end
else
addTomyArray()
end
end
timer.performWithDelay(0,addTomyArray,#valueArray) -- #valueArray
Keep coding........ 😃