R-style logical vector operation in Nim - vectorization

does anyone know if Nim has a function like 'ifelse' in R that allows to apply conditional calculations on vectors, equivalent to:
a<-c(1,2,3,4)
b<-c(7,2,7,4)
c<-ifelse(a==b,a*b,a+b)
using a loop and 'if, else' statement would be too slow for large vectors.

Ok so. In Nim a Tuple uses the same idea as a vector in R: structural typing. Hopefully I'm on track here. Nim has the ability to do stuff during compile time as opposed to runtime, so the functions that are built in for Tuples, like == have a loop in their source code, but in actuality the loop is unraveling at compile time, and the fields are being referenced directly at runtime. So for speed, Tuple == Tuple will be as fast as it could possibly be, regardless of the number of fields in the Tuple. This can be verified via the source code.
I am certain you can do exactly what you are asking after verifying that this little function I wrote works since * wasn't built in for Tuples:
let
v1 = (1,2,3,4)
v2 = (7,2,7,4)
proc `*`[T:tuple](x, y: T): T =
for a,b in fields(x, result):
b = a
for a,b in fields(y, result):
b = b * a
echo $(v1 * v2) #prints (Field0: 7, Field1: 4, Field2: 21, Field3: 16)
We could write the same function for addition:
let
v1 = (1,2,3,4)
v2 = (7,2,7,4)
proc `+`[T:tuple](x, y: T): T =
for a,b in fields(x, result):
b = a
for a,b in fields(y, result):
b = b + a
echo $(v1 + v2)
Here's a full example which is a combination of the forum convo and the functions above:
proc `+`[T:tuple](x, y: T): T =
for a,b in fields(x, result):
b = a
for a,b in fields(y, result):
b = b + a
proc `*`[T:tuple](x, y: T): T =
for a,b in fields(x, result):
b = a
for a,b in fields(y, result):
b = b * a
let
a = (1,2,3,4)
b = (7,2,7,4)
c = if v1 == v2: v1 * v2 else: v1 + v2
Hope this helps!

Related

lua: piggybacking multiple variables across 1 if statement

I have around 7+ variables: a=1, b=10, c=12...etc
I need to write an if statement for each that does this:
if var>0 then var-=1 end
If I need each of the variables to record their values after each iteration, is there a way for me to avoid writing out one if statement per variable?
I tried defining them all in a table like:
a=1;b=2;c=3
local t = {a,b,c}
for _,v in pairs(t) do
if v>0 then v-=1 end
end
a,b,c=t[1],t[2],t[3]
This code failed though, not sure why. Ultimately I'm looking for more efficient way than simply writing the ifs. You can define efficient in terms of cost or tokens or both. The values used would be random, no pattern. The variable names can potentially be changed, i.e. a_1,a_2, a_3, its not ideal though.
There are a couple of solutions. To shorten your code, you could write a function that processes the value and run it on each variable:
local function toward0(var)
if var > 0 then
return var - 1
end
return var
end
a = toward0(a)
b = toward0(b)
c = toward0(c)
You could also store the data in a table instead of in variables. Then you can process them in a loop:
local valuesThatNeedToBeDecremented = {a = 1, b = 10, c = 12}
for k, v in pairs(valuesThatNeedToBeDecremented) do
if v > 0 then
valuesThatNeedToBeDecremented[k] = v - 1
end
end
You forgot to reasign the new values to the table!
local a, b, c = 1, 2, 3
local t = {a, b, c}
for k, v in ipairs(t) do
if v > 0 then v -= 1 end
t[k] = v
end
a, b, c = t[1], t[2], t[3]
print(a, b, c)

Unpack lua table as object and map them as function arguments

I'm looking for a way to unpack lua table(object, not an array) and map return value as arguments to a function.
Example:
local function f(a, b, c, d)
print(a, b, c, d)
end
--order is messed up on purpose
local object_to_unpack = {
a = 1,
c = 42,
d = 18,
b = 102
}
So Im looking for a way to do something like
f(unpack_and_map(object_to_unpack)) and for function to output 1, 102, 42, 18.
I know about unpack function, but it only works on arrays, not objects, and I don't have any ordering guarantees(as demonstrated in object_to_unpack)
Not sure why you want to unpack that table and not just use it as the functions parameter.
local someTable = {
a = 1,
c = 42,
d = 18,
b = 102,
}
local function f(t)
print(t.a, t.b, t.c, t.d)
end
f(someTable)
If you insist on calling f with a list of expressions you need to create one.
function f(...)
print(...)
end
local args = {}
for _, v in pairs(someTable) do
table.insert(args, v)
end
f(table.unpack(args))
This does not guarantee any order. If you want the list ordered by the keys you need to sort that list prior to calling f.
local keys = {}
for k in pairs(someTable) do
table.insert(keys, k)
end
table.sort(keys)
local args = {}
for _, key in ipairs(keys) do
table.insert(args, someTable[key])
end
f(table.unpack(args))

Element by Element comparison in Lua

I'm trying to find a way to do element-by-element comparison in Lua using the standard < operator. For example, here's what I'd like to do:
a = {5, 7, 10}
b = {6, 4, 15}
c = a < b -- should return {true, false, true}
I already have code working for addition (and subtraction, multiplication, etc). My issue is that Lua forces the result of a comparison to a boolean. I don't want a boolean, I want a table as the result of the comparison.
Here is my code so far, with addition working, but less-than comparison not working:
m = {}
m['__add'] = function (a, b)
-- Add two tables together
-- Works fine
c = {}
for i = 1, #a do
c[i] = a[i] + b[i]
end
return c
end
m['__lt'] = function (a, b)
-- Should do a less-than operator on each element
-- Doesn't work, Lua forces result to boolean
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
end
a = {5, 7, 10}
b = {6, 4, 15}
setmetatable(a, m)
c = a + b -- Expecting {11, 11, 25}
print(c[1], c[2], c[3]) -- Works great!
c = a < b -- Expecting {true, false, true}
print(c[1], c[2], c[3]) -- Error, lua makes c into boolean
The Lua programming manual says that the result of the __lt metamethod call is always converted to a boolean. My question is, how can I work around that? I heard that Lua is good for DSL, and I really need the syntax to work here. I think it should be possible using MetaLua, but I'm not really sure where to start.
A coworker suggested that I just use << instead with the __shl metamethod. I tried it and it works, but I really want to use < for less than, rather than a hack using the wrong symbol.
Thanks!
You only have two choices to make this work with your syntax:
Option 1: Patch the Lua core.
This is probably going to be very difficult, and it'll be a maintenance nightmare in the future. The biggest issue is that Lua assumes on a very low level that the comparison operators <, >, ==, ~= return a bool value.
The byte-code that Lua generates actually does a jump on any comparison. For example, something like c = 4 < 5 gets compiled to byte-code that looks much more like if (4 < 5) then c = true else c = false end.
You can see what the byte-code looks like with luac -l file.lua. If you compare the byte-code of c=4<5 with c=4+5 you'll see what I mean. The addition code is shorter and simpler. Lua assumes you'll do branching with comparisons, not assignment.
Option 2: Parse your code, change it, and run that
This is what I think you should do. It would be very hard, expect most of the work is already done for you (using something like LuaMinify).
First of all, write a function you can use for comparisons of anything. The idea here is to do your special comparison if it's a table, but fall back on using < for everything else.
my_less = function(a, b)
if (type(a) == 'table') then
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
else
return a < b
end
end
Now all we need to do is replace every less than operator a<b with my_less(a,b).
Let's use the parser from LuaMinify. We'll call it with the following code:
local parse = require('ParseLua').ParseLua
local ident = require('FormatIdentity')
local code = "c=a*b<c+d"
local ret, ast = parse(code)
local _, f = ident(ast)
print(f)
All this will do is parse the code into a syntax tree, and then spit it back out again. We'll change FormatIdentity.lua to make it do the substitution. Replace the section near line 138 with the following code:
elseif expr.AstType == 'BinopExpr' then --line 138
if (expr.Op == '<') then
tok_it = tok_it + 1
out:appendStr('my_less(')
formatExpr(expr.Lhs)
out:appendStr(',')
formatExpr(expr.Rhs)
out:appendStr(')')
else
formatExpr(expr.Lhs)
appendStr( expr.Op )
formatExpr(expr.Rhs)
end
That's all there is to it. It will replace something like c=a*b<c+d with my_less(a*b,c+d). Just shove all your code through at runtime.
Comparisons in Lua return a boolean value.
There is nothing you can do about it short of changing the core of Lua.
Can you put up with a bit verbose v()-notation:
v(a < b) instead of a < b ?
local vec_mt = {}
local operations = {
copy = function (a, b) return a end,
lt = function (a, b) return a < b end,
add = function (a, b) return a + b end,
tostring = tostring,
}
local function create_vector_instance(operand1, operation, operand2)
local func, vec = operations[operation], {}
for k, elem1 in ipairs(operand1) do
local elem2 = operand2 and operand2[k]
vec[k] = func(elem1, elem2)
end
return setmetatable(vec, vec_mt)
end
local saved_result
function v(...) -- constructor for class "vector"
local result = ...
local tp = type(result)
if tp == 'boolean' and saved_result then
result, saved_result = saved_result
elseif tp ~= 'table' then
result = create_vector_instance({...}, 'copy')
end
return result
end
function vec_mt.__add(v1, v2)
return create_vector_instance(v1, 'add', v2)
end
function vec_mt.__lt(v1, v2)
saved_result = create_vector_instance(v1, 'lt', v2)
end
function vec_mt.__tostring(vec)
return
'Vector ('
..table.concat(create_vector_instance(vec, 'tostring'), ', ')
..')'
end
Usage:
a = v(5, 7, 10); print(a)
b = v(6, 4, 15); print(b)
c = a + b ; print(c) -- result is v(11, 11, 25)
c = v(a + b); print(c) -- result is v(11, 11, 25)
c = v(a < b); print(c) -- result is v(true, false, true)
As others have already mentioned, there is no straight-forward solution to this. However, with the use of a generic Python-like zip() function, such as the one shown below, you can simplify the problem, like so:
--------------------------------------------------------------------------------
-- Python-like zip() iterator
--------------------------------------------------------------------------------
function zip(...)
local arrays, ans = {...}, {}
local index = 0
return
function()
index = index + 1
for i,t in ipairs(arrays) do
if type(t) == 'function' then ans[i] = t() else ans[i] = t[index] end
if ans[i] == nil then return end
end
return table.unpack(ans)
end
end
--------------------------------------------------------------------------------
a = {5, 7, 10}
b = {6, 4, 15}
c = {}
for a,b in zip(a,b) do
c[#c+1] = a < b -- should return {true, false, true}
end
-- display answer
for _,v in ipairs(c) do print(v) end

Incrementation in Lua

I am playing a little bit with Lua.
I came across the following code snippet that have an unexpected behavior:
a = 3;
b = 5;
c = a-- * b++; // some computation
print(a, b, c);
Lua runs the program without any error but does not print 2 6 15 as expected. Why ?
-- starts a single line comment, like # or // in other languages.
So it's equivalent to:
a = 3;
b = 5;
c = a
LUA doesn't increment and decrement with ++ and --. -- will instead start a comment.
There isn't and -- and ++ in lua.
so you have to use a = a + 1 or a = a -1 or something like that
If you want 2 6 15 as the output, try this code:
a = 3
b = 5
c = a * b
a = a - 1
b = b + 1
print(a, b, c)
This will give
3 5 3
because the 3rd line will be evaluated as c = a.
Why? Because in Lua, comments starts with --. Therefore, c = a-- * b++; // some computation is evaluated as two parts:
expression: c = a
comment: * b++; //// some computation
There are 2 problems in your Lua code:
a = 3;
b = 5;
c = a-- * b++; // some computation
print(a, b, c);
One, Lua does not currently support incrementation. A way to do this is:
c = a - 1 * b + 1
print(a, b, c)
Two, -- in Lua is a comment, so using a-- just translates to a, and the comment is * b++; // some computation.
Three, // does not work in Lua, use -- for comments.
Also it's optional to use ; at the end of every line.
You can do the following:
local default = 0
local max = 100
while default < max do
default = default + 1
print(default)
end
EDIT: Using SharpLua in C# incrementing/decrementing in lua can be done in shorthand like so:
a+=1 --increment by some value
a-=1 --decrement by some value
In addition, multiplication/division can be done like so:
a*=2 --multiply by some value
a/=2 --divide by some value
The same method can be used if adding, subtracting, multiplying or dividing one variable by another, like so:
a+=b
a-=b
a/=b
a*=b
This is much simpler and tidier and I think a lot less complicated, but not everybody will share my view.
Hope this helps!

Understanding the indexing of bound variables in Z3

I am trying to understand how the bound variables are indexed in z3.
Here in a snippet in z3py and the corresponding output. ( http://rise4fun.com/Z3Py/plVw1 )
x, y = Ints('x y')
f1 = ForAll(x, And(x == 0, Exists(y, x == y)))
f2 = ForAll(x, Exists(y, And(x == 0, x == y)))
print f1.body()
print f2.body()
Output:
ν0 = 0 ∧ (∃y : ν1 = y)
y : ν1 = 0 ∧ ν1 = y
In f1, why is the same bound variable x has different index.(0 and 1). If I modify the f1 and bring out the Exists, then x has the same index(0).
Reason I want to understand the indexing mechanism:
I have a FOL formula represented in a DSL in scala that I want to send to z3. Now ScalaZ3 has a mkBound api for creating bound variables that takes index and sort as arguments. I am not sure what value should I pass to the index argument. So, I would like to know the following:
If I have two formulas phi1 and phi2 with maximum bound variable indexes n1 and n2, what would be the index of x in ForAll(x, And(phi1, phi2))
Also, is there a way to show all the variables in an indexed form? f1.body() just shows me x in indexed form and not y. (I think the reason is that y is still bound in f1.body())
Z3 encodes bound variables using de Bruijn indices.
The following wikipedia article describes de Bruijn indices in detail:
http://en.wikipedia.org/wiki/De_Bruijn_index
Remark: in the article above the indices start at 1, in Z3, they start at 0.
Regarding your second question, you can change the Z3 pretty printer.
The Z3 distribution contains the source code of the Python API. The pretty printer is implemented in the file python\z3printer.py.
You just need to replace the method:
def pp_var(self, a, d, xs):
idx = z3.get_var_index(a)
sz = len(xs)
if idx >= sz:
return seq1('Var', (to_format(idx),))
else:
return to_format(xs[sz - idx - 1])
with
def pp_var(self, a, d, xs):
idx = z3.get_var_index(a)
return seq1('Var', (to_format(idx),))
If you want to redefine the HTML pretty printer, you should also replace.
def pp_var(self, a, d, xs):
idx = z3.get_var_index(a)
sz = len(xs)
if idx >= sz:
# 957 is the greek letter nu
return to_format('ν<sub>%s</sub>' % idx, 1)
else:
return to_format(xs[sz - idx - 1])
with
def pp_var(self, a, d, xs):
idx = z3.get_var_index(a)
return to_format('ν<sub>%s</sub>' % idx, 1)

Resources