I'm using Transform > Compute Variable to OR two variables (B,C) together. My two vars can have values 1, 2, or 3. I want to calculate a third var that's 1 if either B or C is 1 and zero otherwise. This works
A = (B=1) | (C=1)
But I'm running into trouble if B or C is missing. What I'd like is
if B and C exist and B or C equals 1, A = 1
if B and C exist and neither equals 1, A = 0
if B is missing and C is missing, A = missing
if B or C is 1 and the other value is missing, A = 1
if B or C is not 1 and the other value is missing, A = 0
Can I use Transform > Compute Variable to accomplish this or do I need another approach?
Here's a one liner for this:
compute A=max((B=1), (C=1)).
exe.
You can do this through the transformation menus, but I recommend getting used to (the power of) using syntax.
You can write this in the syntax window. If variable exists is translated as if ~miss(variable)
if ~miss(B) and ~miss(C) and any(1,B,C) A=1.
if ~miss(B) and ~miss(C) and ~any(1,B,C) A=0.
if miss(B) and miss(C) A=$sysmis.
if miss(B) or miss(C) and any(1,B,C) A=1.
if miss(B) or miss(C) and ~any(1,B,C) A=0.
EXECUTE.
Or, if I understand correctly what you are trying to do:
Compute A=0.
if any(1,B,C) A=1.
if miss(A) and miss(B) A=$sysmis.
EXECUTE.
Related
When creating an element in the table, I need to use another element that I created before in the same table. please help me with this.
local table = {
distance = 30.0,
last_distance = table.distance-10.0
}
I want to do the above operation but I can't, I think I need to use self or setmetatable but I don't know how to do it. and please don't give me answers like first create a value outside and then use it in the table, I don't want to do that.
Basic life advice
First of all: Don't call your table table. That will shadow the global table library. Call it t, tab, tabl, Table, table_, or actually give it a useful name, but don't call it table, or there'll be a big surprise when you try to access any table.* methods. Ideally, your linter should warn you about this.
Implementing it using hacks
Table constructors are equivalent to creating a table on the stack - there is no named local variable self or the like. It is likely possible that there is a hidden local variable accessible using debug.getlocal however:
$ lua
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> function getlocals()
>> local i = 1; repeat local k, v = debug.getlocal(2, i); i = i + 1; print(k, v) until not k
>> t = {a = getlocals(), b = ()}
stdin:3: unexpected symbol near ')'
> function getlocals()
local i = 1; repeat local k, v = debug.getlocal(2, i); i = i + 1; print(k, v) until not k end
> t = {a = getlocals(), b = 2}
(temporary) table: 0x55e9181302d0
nil nil
> t
table: 0x55e9181302d0
Indeed, from basic testing it appears that this is even the first local inside the table constructor! However, it isn't quite as easy:
> local a = 1; local b = a; t = {a = getlocals(), b = 2}; print(b)
a 1
b 1
(temporary) table: 0x55e918130160
nil nil
1
Using extensive hacks, you might be able to write something that returns the currently constructed table most of the time (probably relying on the fact that it will usually be the last local). The following works:
function lastlocal()
local i = 0
local last
::next:: -- you could (and perhaps should) use a loop instead
i = i + 1
local k, v = debug.getlocal(2, i)
if v then
last = v
goto next
end
return last
end
from my basic testing, this works fine to obtain the table currently being constructed:
> function lastlocal()
local i = 0
local last
::next:: -- you could (and perhaps should) use a loop instead
i = i + 1
local k, v = debug.getlocal(2, i)
if v then
last = v
goto next
end
return last
end
> t = {a = 1, b = lastlocal().a}
> t.a
1
> t.b
1
Why you should not implement this using hacks
With all of this in mind: Don't ever do this. The purpose of this merely is to lead this ad absurdum. There are multiple reasons why this is horribly unreliable:
The order of execution of table constructor assignments is undefined. An optimizing interpreter like LuaJIT (and the PUC Lua implementation just as well) is free to reorder {a = 1, b = 2} to {b = 2, a = 1}.
Likewise, how table constructors are implemented internally is entirely undefined. There is no guarantee that the local variable actually exists and is the last one.
It is horribly inefficient and relies on the debug library for something other than debugging.
What's a metatable?
Metatables serve an entirely different purpose; you could dynamically generate derived fields like last_distance using them, but you can't use them to reference a table using a table constructor. Here's a basic example:
local t = {distance = 30}
setmetatable(t, {__index = function(self, k)
if k ~= "last_distance" then return nil end
return t.distance - 10 -- calculate `last_distance` & return it
end})
print(t.last_distance) -- 20
t.distance = 10
print(t.last_distance) -- 0
Back to the question
When creating an element in the table, I need to use another element that I created before in the same table.
The proper way to do this is to either (1) create a value outside of the table
local distance = 30
local last_distance = distance - 10
local tab = {distance = distance, last_distance = last_distance}
Perfectly readable, perfectly fine.
Or (2) first create a table with some properties, then add derived properties:
local tab = {distance = 30}
tab.last_distance = tab.distance - 10
as readable, as fine.
Both will be highly efficient; only micro-optimizations would be debatable (could (1) choose a better layout for the hashes by choosing the right insertion order? does it pre-allocate the right size (likely yes)? does (2) incur a penalty since it indexes tab to obtain tab.distance?), but none of this will likely ever matter.
I want to do the above operation but I can't, I think I need to use self or setmetatable but I don't know how to do it.
I have shown you:
How you can do it using egregious hacks and why you shouldn't.
How you can do something similar (derived attributes) using a metamethod.
and please don't give me answers like first create a value outside and then use it in the table, I don't want to do that.
This is the correct, idiomatic way to do this in Lua though. Your restriction seems arbitrary.
Say I have two variables a and b. I would like to define the following relation/constraint between them:
a = 1, b % 12 = 1 or b % 12 = 0
a = 2, b % 12 = 0
Some solutions are
a = 1, b = 1
a = 1, b = 12
a = 2, b = 12
I'm currently modelling this in a straightforward way (and adding an extra condition on top):
rhs = Or(
And(a == 1, Or(b % 12 == 1, b % 12 == 0)),
And(a == 2, Or(b % 12 == 0))
)
lhs = And(b > 10)
solver.add(Implies(lhs, rhs))
However, this becomes very slow as I increase the number of variables and constraints.
Is there a better way to model this? Maybe a function? But I would like to allow search to run "in both directions", i.e. given a value of b, we should be able to identify a value of a, and vice versa.
Based on your comment, it looks like the use of integers is unnecessarily complicating your constraints.
If you need to stick to "numbers" for some other reason, then I'd recommend asserting 0 <= b and b < 12 globally (to represent all 12 notes), which can help the solver reduce the search space. However, division/modulus are always hard for SMT solvers, but perhaps you do not need them at all: In fact, I'd recommend not using numbers to represent notes in the first place. Instead use an enumeration:
Note, (A, B, C) = EnumSort('Note', ('A', 'B', 'C'))
(I've only written the first three above; you can add the remaining 9.)
This very clearly communicates to the solver that you're dealing with a finite collection of distinct items. You should also consider representing octave as some enum-type, or at least restrict it to be in some small range that covers the first 6-7 octaves which I assume you're interested in.
You can read more about enums in z3 here: https://ericpony.github.io/z3py-tutorial/advanced-examples.htm (Scroll down to the part that talks about "enumerations.")
You haven't told us how octaves/notes constrain each other in your system; but it should be easy to capture them using regular functions that take octaves and return possible notes. You should post actual code that people can run so they can see what the bottle-necks can be.
I was reading some Lua and doing a little course to use it with Löve 2D, in an example they give declare a variable this way, which I honestly do not understand:
ballDX = math.random(2) == 1 and 100 or -100
I've tried to google and read a bit but haven't found a place to specifically explain that. Looking at what it says I identify the obvious, BallDX is equal to a random number between 1 and 2, but from there I get quite confused, what does it mean that the random number is equal to 1 and 100 or -100?
This is a kinda interesting Lua concept
The operator and returns its first argument if it is false; otherwise, it returns its second argument.
The operator or returns its first argument if it is not false; otherwise, it returns its second argument
In this case math.random(2) == 1 and 100 or -100 behaves exactly like a ternary operator, it can translate to:
If math.random(2) equals to 1, set ballDX = 100, otherwise set ballDX = -100
For example, assume you had a variable called c, and you want to assign it a value only if a variable is above 10, with a ternary operator you would do this: c = a > 10 ? a : b
In Lua you would use c = a > 10 and a or b
I'm running into a problem that I've never encountered before and I cannot quite figure out what's going on.
I am trying to compute a variable as follows:
COMPUTE A=$SYSMIS.
IF B=$SYSMIS A=$SYSMIS.
IF C > SUM(B, 1) A= 1.
IF C = SUM(B, 1) A= 2.
IF C = B A= 2.
IF C < B A=3.
This runs fine except for the fact that when B=$SYSMIS there are very clear examples of A that are not in fact missing.
I tested it using:
TEMP.
SELECT IF B=$SYSMIS.
FREQ A.
It tells me that "No cases were input to this procedure. Either there are none in the working data file or all of them have been filtered out."
Meaning, the code worked correctly.
But...I found over 1,000 cases that are not fitting this logic.
TEMP.
SELECT IF ID=102.
FREQ A B.
This shows a specific ID that has A=$SYSMIS and B=2.
A, B and C are all numeric.
Thanks in advance for any insight! (:
First, instead of IF B=$SYSMIS you should use if missing(B) - for computing, for analysis and for select.
Another probable reason for your results is in commands like this:
IF C > SUM(B, 1) A=1.
If B is missing, the result of SUM(B, 1) is 1. Therefore if C>1 A gets the value 1, in spite of B being missing.
There are two ways to overcome this.
First, using X+Y instead of sum(X,Y) will result in a missing value when X or Y is missing:
IF C > (B + 1) A=1.
Second option: put the command COMPUTE A=$SYSMIS. at the end of the syntax instead of the beginning, so any values entered in A when B is missing will be replaced with a missing value.
Issue
While trying to learn lua I accidentally found out that if
a = {"a"}
b = a
than this produces (no surprise):
a
{"a"} --[[table: 0x046bde18]]
b
{"a"} --[[table: 0x046bde18]]
but then if:
a[2] = "b"
why is a == b still true?
a
{"a", "b"} --[[table: 0x046bde18]]
b -- this is a surprise
{"a", "b"} --[[table: 0x046bde18]]
This seem to work both ways: if a new value is assigned to b then it will be also assigned to a.
On the other hand if I assign a a value (example: a = 1) and b = a then if a value is changed (a = 2) then b retains the original value (still b = 1).
Questions
Why is this behaviour different depending on wheather a is an array/table or a value? Is it due to built-in metatables (__newindex)?
What is the purpose of such behaviour of arrays/tables?
What if I wanted/needed to somehow seperate a and b (or what to do if I wanted to store the values of a before changing b)?
(I read Lua Assignment and Metatables and Metamethods chapters of the Lua Reference Manual but still have no clue why such behaviour occures.)
In your example, a and b are just references to the same table. In Lua, tables are objects, and you created a table and assigned it to a with the first statement, and then you created a second reference to the same table with the second assignment. So, both a[2] = "b" and b[2] = "b" are acting on the same underlying table (table: 0x046bde18).
A table is not a value, it is an object. a = {"a"} constructs a table and assigns a reference to the table to a. b = a assigns the same reference to b. But, x = 10 assigns the value 10 to x. If y = 10 and you could change the underlying value of 10, I suppose that this change would be reflected in both x and y, but I know of no obvious way to do this. In this code:
x = 10
y = 10
y = y + 1
the resulting values will be x = 10, and y = 11. The underlying value of 10 has not changed, but y was reassigned to the value 11.
If you want to work with two copies of the table that can change independently, you would need to write a function that copies the members of a into b = {}. Here is a question that discusses making copies of tables.