NetLogo - setting variable in calling breed in nested ask of same type of breed - nested

I'm trying to set "parent" variable in a nested ask but without luck.
In code below I use an "outer" ask instruction "ask turtle 0" and below this a nested "ask other turtles".
In the nested ask I'm trying to set a variable of the calling turtle.
turtles-own [
a
b
]
to setup
clear-all
set-default-shape turtles "circle"
setup-turtles
reset-ticks
end
to go
ask turtle 0
[
set a 2
set b 3
show (word "(a, b) = (" a ", " b ")")
ask other turtles
[
show (word "(a, b) = (" a ", " b ")")
set a a + 1
set b b + 1
show (word "(a, b) = (" a ", " b ")")
; Below isn't allowed. Message is:
; This isn't something you can use "set" on.
; set ([b] of myself) 14
]
]
tick
end
The "set ([b] of myself) 14" instruction doesn't work and the message is "This isn't something you can use "set" on.".
Edit: added clarification below:
Let me elaborate a little.
Running the go procedure once gives:
(turtle 0): "(a, b) = (2, 3)"
(turtle 1): "(a, b) = (0, 0)"
(turtle 1): "(a, b) = (1, 1)"
(turtle 2): "(a, b) = (0, 0)"
(turtle 2): "(a, b) = (1, 1)"
(turtle 3): "(a, b) = (0, 0)"
(turtle 3): "(a, b) = (1, 1)"
However, what I would like to happen is that turtle 1, 2 and 3 can write "back" to turtle 0, so that when "go" procedure is run next time I'll set something like:
(turtle 0): "(a, b) = (2, 14)"
(turtle 3): "(a, b) = (1, 1)"
(turtle 3): "(a, b) = (2, 2)"
(turtle 1): "(a, b) = (1, 1)"
(turtle 1): "(a, b) = (2, 2)"
(turtle 2): "(a, b) = (1, 1)"
(turtle 2): "(a, b) = (2, 2)"

A turtle can access the variables of another turtle but it can't change the variables of another turtle. So you will have to go back to the original turtle and ask them to change their own variable using ask myself [...]
ask turtle 0
[
ask other turtles
[
ask myself [set b 14]
]
]

This error is appearing because you are not using the proper way of setting variables in NetLogo. Instead, you should use:
ask other turtles
[
show (word "(a, b) = (" a ", " b ")")
set a a + 1
set b b + 1
show (word "(a, b) = (" a ", " b ")")
set b 14
]
That is because what you wanted to be set ([b] of myself) 14 is inside ask other turtles []. When code inside that is run, it is applied to each individual turtle in the specified set (in your case, all turtles except turtle 0) until all of them has followed the instructions you gave them. So writing that of myself is kind of redundant in there.

Related

Collect coefficients of non-square matrix in sympy

Given three vectors, a(1,4), b(1, 4), c(4,1). I want to do the following
a = MatrixSymbol('a', 1, 4)
b = MatrixSymbol('a', 1, 4)
c = MatrixSymbol('c', 4, 1)
expr = a*c + b*c
c_coeff = .... # How to get the value of (a+b) here
I tried using coeff and collect but it fails because the C matrix is not square.
If it is linear then
>>> from sympy.solvers.solveset import linear_coeffs
>>> linear_coeffs(expr, c)
[a + b, 0]
note that 0 is the constant term; if you added MatrixSymbol('d', 1, 1) to expr the 2nd element would be d; you named 'b' as 'a' in your example; I named it 'b' to get the output shown above.

Why Piecewise() isn't being displayed properly by IPython.display.display()?

from IPython.display import display as mathPrint
from sympy import *
x = symbols("x")
mathPrint(Eq(abs(x), Piecewise((-x, x < 0), (0, x == 0), (x, x > 0)), evaluate=False))
It's printing the expression like this:
It isn't showing the 2nd condition of the function which should be 0 for x = 0.
How can I get the desired output? Should I need to use any other display function?
There are two problems. The first is that you are passing evaluate=False to Eq rather than to Piecewise (check the brackets carefully). The second problem is that you are passing th condition x == 0 which simply evaluates to False. To make a symbolic representation of an equality you should use Eq. In that case evaluate=False is not even needed (in this example):
In [145]: Piecewise((-x, x < 0), (0, Eq(x, 0)), (x, x > 0))
Out[145]:
⎧-x for x < 0
⎪
⎨0 for x = 0
⎪
⎩x for x > 0

How to interface with AutoCAD from Python?

I've the following AutoLISP code
(defun graph ( pts sls tls )
( (lambda ( l )
(foreach x l (text (cdr x) (itoa (car x)) 0.0 1))
(mapcar
'(lambda ( a b / p q r )
(setq p (cdr (assoc a l))
q (cdr (assoc b l))
r (angle p q)
)
(entmake (list '(0 . "LINE") (cons 10 p) (cons 11 q) '(62 . 8)))
(text
(mapcar '(lambda ( x y ) (/ (+ x y) 2.0)) p q)
(rtos (distance p q) 2)
(if (and (< (* pi 0.5) r) (<= r (* pi 1.5))) (+ r pi) r)
2
)
)
sls tls
)
)
(mapcar 'cons (vl-sort (append sls tls) '<) pts)
)
)
(defun text ( p s a c )
(entmake
(list
'(0 . "TEXT")
(cons 10 p)
(cons 11 p)
(cons 50 a)
(cons 01 s)
(cons 62 c)
'(40 . 2)
'(72 . 1)
'(73 . 2)
)
)
)
and the input is
(graph
'((75 25) (115 45) (90 60) (10 5) (45 0) (45 55) (0 25))
'(1 1 1 1 2 2 3 4 4 5 6)
'(2 3 4 5 3 6 6 5 7 7 7)
)
The 2D geometry created from the above is exported as a dxf file from AutoCAD.
The actual input is generated in Python
pts = [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]
sls = [1 1 1 1 2 2 3 4 4 5 6]
tls = [2 3 4 5 3 6 6 5 7 7 7]
I would like to know how to use the python data types as input and directly interface with AutoCAD from Python, save the AutoCAD output as a dxf file.
EDIT:
I've installed pyautocad in Python and did
from pyautocad import Autocad, APoint
Now I am not sure how to evaluate these AutoCAD expressions in Python.
For instance, the inputs are Python tuples
Should I convert each tuple to AutoCAD point using
p = APoint(x, y)
And I am not sure how to proceed from here after generating the input data as autocad points. It's not clear to me how the commands in function
defun graph ( pts sls tls )
Any suggestions will be greatly useful
The interface can be established using the subprocess library of python
"""
Created by Natasha 28/9/2020
-This code passes inputs from python to autocad
ref: https://stackoverflow.com/questions/48794935/batch-run-autolisp-with-python
ref: https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/how-to-interface-with-autocad-from-python/m-p/9768816/highlight/false#M404952
"""
import subprocess
from settings import\
GRAPH_LISP_FILE,\ # file paths
GRAPH_SCR_FILE,\
GRAPH_DWG_FILE,\
GRAPH_DXF_FILE
def write_src(graph):
"""
Commands sent to AutoCAD aew
:param graph:
:return:
"""
with open(GRAPH_SCR_FILE, 'w') as outfile:
outfile.write("open\n" +
f"{GRAPH_DWG_FILE}" + "\n"
"(setq *LOAD_SECURITY_STATE* (getvar 'SECURELOAD))\n" +
'(setvar "SECURELOAD" 0)\n' +
rf'(load "{GRAPH_LISP_FILE}")' + "\n"
f"{graph}\n" +
'(setvar "SECURELOAD" *LOAD_SECURITY_STATE*)\n'
"saveas dxf 16\n" +
rf"{GRAPH_DXF_FILE}" +"\n"+
"quit"
)
pass
def iter_to_lisp_string(list_or_tuple):
"""
Converts python datatypeS list and tuple to AutoCAD datatype
:param list_or_tuple:
:return:
"""
return "(" + " ".join(map(str, list_or_tuple)) + ")"
if __name__ == '__main__':
pts_string = "'" + iter_to_lisp_string(map(iter_to_lisp_string, [(75, 25), (115, 45), (90, 60), (10, 5), (45, 0), (45, 55), (0, 25)]))
sls_string = "'" + iter_to_lisp_string([1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6])
tls_string = "'" + iter_to_lisp_string([2, 3, 4, 5, 3, 6, 6, 5, 7, 7, 7])
graph_command_string = iter_to_lisp_string(["graph", pts_string, sls_string, tls_string])
write_src(graph=graph_command_string)
subprocess.run(["C:\\Program Files\\Autodesk\\AutoCAD 2019\\acad.exe", "/b", GRAPH_SCR_FILE])
print("Process Finished")

Python3: write string into .txt.bz2 file

I want to write the join result by two list into the txt.bz2 file(the file name is named by code, not exist at the beginning). like the following form in txt file.
1 a,b,c
0 d,f,g
.......
But there is error. My code is following, please give me hints how to deal with it. Thanks!
import bz2
x = ['a b c', 'd f g', 'h i k', 'k j l']
y = [1, 0, 0, 1]
with bz2.BZ2File("data/result_small.txt.bz2", "w") as bz_file:
for i in range(len(y)):
m = ','.join(x[i].split(' '))
n = str(y[i])+'\t'+m
bz_file.write(n)
error:
compressed = self._compressor.compress(data)
TypeError: a bytes-like object is required, not 'str'
Open the file in text mode:
import bz2
x = ['a b c', 'd f g', 'h i k', 'k j l']
y = [1, 0, 0, 1]
with bz2.open("data/result_small.txt.bz2", "wt") as bz_file:
for i in range(len(y)):
m = ','.join(x[i].split(' '))
n = str(y[i]) + '\t' + m
bz_file.write(n + '\n')
More succinctly:
import bz2
x = ['a b c', 'd f g', 'h i k', 'k j l']
y = [1, 0, 0, 1]
with bz2.open("data/result_small.txt.bz2", "wt") as bz_file:
for a, b in zip(x, y):
bz_file.write('{}\t{}\n'.format(b, ','.join(a.split())))
You open a bz2-file by using the file bz2.BZ2File(path).
with bz2.BZ2File("data/result_small.txt.bz2", "rt") as bz_file:
#...

String concatenation queries

I have a list of characters, say x in number, denoted by b[1], b[2], b[3] ... b[x]. After x,
b[x+1] is the concatenation of b[1],b[2].... b[x] in that order. Similarly,
b[x+2] is the concatenation of b[2],b[3]....b[x],b[x+1].
So, basically, b[n] will be concatenation of last x terms of b[i], taken left from right.
Given parameters as p and q as queries, how can I find out which character among b[1], b[2], b[3]..... b[x] does the qth character of b[p] corresponds to?
Note: x and b[1], b[2], b[3]..... b[x] is fixed for all queries.
I tried brute-forcing but the string length increases exponentially for large x.(x<=100).
Example:
When x=3,
b[] = a, b, c, a b c, b c abc, c abc bcabc, abc bcabc cabcbcabc, //....
//Spaces for clarity, only commas separate array elements
So for a query where p=7, q=5, answer returned would be 3(corresponding to character 'c').
I am just having difficulty figuring out the maths behind it. Language is no issue
I wrote this answer as I figured it out, so please bear with me.
As you mentioned, it is much easier to find out where the character at b[p][q] comes from among the original x characters than to generate b[p] for large p. To do so, we will use a loop to find where the current b[p][q] came from, thereby reducing p until it is between 1 and x, and q until it is 1.
Let's look at an example for x=3 to see if we can get a formula:
p N(p) b[p]
- ---- ----
1 1 a
2 1 b
3 1 c
4 3 a b c
5 5 b c abc
6 9 c abc bcabc
7 17 abc bcabc cabcbcabc
8 31 bcabc cabcbcabc abcbcabccabcbcabc
9 57 cabcbcabc abcbcabccabcbcabc bcabccabcbcabcabcbcabccabcbcabc
The sequence is clear: N(p) = N(p-1) + N(p-2) + N(p-3), where N(p) is the number of characters in the pth element of b. Given p and x, you can just brute-force compute all the N for the range [1, p]. This will allow you to figure out which prior element of b b[p][q] came from.
To illustrate, say x=3, p=9 and q=45.
The chart above gives N(6)=9, N(7)=17 and N(8)=31. Since 45>9+17, you know that b[9][45] comes from b[8][45-(9+17)] = b[8][19].
Continuing iteratively/recursively, 19>9+5, so b[8][19] = b[7][19-(9+5)] = b[7][5].
Now 5>N(4) but 5<N(4)+N(5), so b[7][5] = b[5][5-3] = b[5][2].
b[5][2] = b[3][2-1] = b[3][1]
Since 3 <= x, we have our termination condition, and b[9][45] is c from b[3].
Something like this can very easily be computed either recursively or iteratively given starting p, q, x and b up to x. My method requires p array elements to compute N(p) for the entire sequence. This can be allocated in an array or on the stack if working recursively.
Here is a reference implementation in vanilla Python (no external imports, although numpy would probably help streamline this):
def so38509640(b, p, q):
"""
p, q are integers. b is a char sequence of length x.
list, string, or tuple are all valid choices for b.
"""
x = len(b)
# Trivial case
if p <= x:
if q != 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
return p, b[p - 1]
# Construct list of counts
N = [1] * p
for i in range(x, p):
N[i] = sum(N[i - x:i])
print('N =', N)
# Error check
if q > N[-1]:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
print('b[{}][{}]'.format(p, q), end='')
# Reduce p, q until it is p < x
while p > x:
# Find which previous element character q comes from
offset = 0
for i in range(p - x - 1, p):
if i == p - 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
if offset + N[i] >= q:
q -= offset
p = i + 1
print(' = b[{}][{}]'.format(p, q), end='')
break
offset += N[i]
print()
return p, b[p - 1]
Calling so38509640('abc', 9, 45) produces
N = [1, 1, 1, 3, 5, 9, 17, 31, 57]
b[9][45] = b[8][19] = b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Similarly, for the example in the question, so38509640('abc', 7, 5) produces the expected result:
N = [1, 1, 1, 3, 5, 9, 17]
b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Sorry I couldn't come up with a better function name :) This is simple enough code that it should work equally well in Py2 and 3, despite differences in the range function/class.
I would be very curious to see if there is a non-iterative solution for this problem. Perhaps there is a way of doing this using modular arithmetic or something...

Resources