Can't multiply a variable with the generator of a vector - sage

This is my code:
sage: Q = QuadraticForm(ZZ,1,[1])
sage: Cl.<x> = CliffordAlgebra(Q)
sage: a = var('a')
sage: a*x
And it errors as follows:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-79-c166ddc995fe> in <module>
----> 1 a*x
/var/tmp/sage-9.4-current/local/lib/python3.9/site-packages/sage/structure/element.pyx in sage.structure.element.Element.__mul__ (build/cythonized/sage/structure/element.c:12205)()
1513 return (<Element>left)._mul_(right)
1514 if BOTH_ARE_ELEMENT(cl):
-> 1515 return coercion_model.bin_op(left, right, mul)
1516
1517 cdef long value
/var/tmp/sage-9.4-current/local/lib/python3.9/site-packages/sage/structure/coerce.pyx in sage.structure.coerce.CoercionModel.bin_op (build/cythonized/sage/structure/coerce.c:11708)()
1246 # We should really include the underlying error.
1247 # This causes so much headache.
-> 1248 raise bin_op_exception(op, x, y)
1249
1250 cpdef canonical_coercion(self, x, y):
TypeError: unsupported operand parent(s) for *: 'Symbolic Ring' and 'The Clifford algebra of the Quadratic form in 1 variables over Integer Ring with coefficients:
[ 1 ]'
How can I multiply x with a variable scalar a?

Related

Recursively sum all digits until number is single digit

For example, sum all the digits of 1253, 1+2+5+3 which is 11. This is two digits, so sum those again to get 2. The final number left is a single digit.
This is what I have so far:
defmodule Kata do
def digital_root(n) do
n |> Integer.digits() |> Enum.reduce(0, &Kernel.+/2)
end
end
n = 1253
You can use a multi clause function for this: in the first one, return n unchanged if it's a single digit. Otherwise, compute the sum of digits (like you've already figured out) and recursively call the function on it again. Also, your reduce can be replaced with Enum.sum/1.
defmodule Kata do
def digital_root(n) when n < 10, do: n
def digital_root(n) do
n |> Integer.digits() |> Enum.sum() |> digital_root()
end
end
Test:
iex(1)> Kata.digital_root(0)
0
iex(2)> Kata.digital_root(1)
1
iex(3)> Kata.digital_root(9)
9
iex(4)> Kata.digital_root(91)
1
iex(5)> Kata.digital_root(912)
3
iex(6)> Kata.digital_root(9123)
6
iex(7)> Kata.digital_root(1253)
2
Just for fun, here's a version that doesn't use Integer.digits/2 or Enum, and instead uses div/2 and rem/2 to calculate the least significant digit for each iteration:
defmodule Kata do
# Function header
def digital_root(to_sum, acc \\ 0)
# Base case. All digits added, acc is a single digit
def digital_root(0, acc) when acc < 10, do: acc
# Finished a round. All digits added, acc is multiple digits. Sum again.
def digital_root(0, acc), do: digital_root(acc, 0)
# Split off the least significant digit, add it, and recurse
def digital_root(to_sum, acc) do
digit = rem(to_sum, 10)
next_to_sum = div(to_sum, 10)
digital_root(next_to_sum, acc + digit)
end
end
Output:
iex> Kata.digital_root(1523)
2
In a benchmark, this version is twice as fast as dogbert's, and three times faster than 7stud's answers.
Name ips average deviation median 99th %
adam 14.26 M 70.13 ns ±1898.51% 66.70 ns 83.30 ns
dogbert 7.08 M 141.28 ns ±14510.93% 125 ns 167 ns
sevenstud 4.83 M 206.98 ns ±15193.15% 167 ns 292 ns
Comparison:
adam 14.26 M
dogbert 7.08 M - 2.01x slower +71.14 ns
sevenstud 4.83 M - 2.95x slower +136.85 ns
Operating System: macOS
CPU Information: Apple M1 Pro
Number of Available Cores: 10
Available memory: 16 GB
Elixir 1.13.4
Erlang 24.3.4
def digit_sum(number) when number < 10, do: number
def digit_sum(number) when is_integer(number) do
digit_sum(
for digit <- Integer.digits(number), reduce: 0 do
acc -> acc + digit
end
)
end
I like Dogbert's better.

numba TypingError: Cannot unify array(float64, 1d, C) and float64 for 'v_new.2'

I'm making value function iteration code for economics study, using python and numba package.
Here's simple description of my problem:
I want to solve maximization problem using brent_max,(similar to scipy.optimization) for kp, given k, v while it converges.
kp is 'next state of k', and it is used for upper bound of maximization problem. so after brent_max calculate the value of kp, I want to save and use it again. That's why I used global option.
Here's my code for the problem and error message.
opt_growth_data = [('α', float64),
('β', float64),
('γ', float64),
('δ', float64),
('grid', float64[:])]
#jitclass(opt_growth_data)
class OptimalGrowth_VI:
def __init__(self, α=0.4, β=0.96, γ=2.0, δ=0.1, grid_max=10, grid_size=500):
self.α, self.β, self.γ, self.δ = α, β, γ, δ
self.grid = np.linspace(0.1, grid_max, grid_size)
def f(self, k):
return k**self.α
def u(self, c):
return c**(1-self.γ) / (1-self.γ)
def objective(self, k, kp, v_array):
f, u, β, δ = self.f, self.u, self.β, self.δ
v = lambda x: interp(self.grid, v_array, x)
return u(f(k) + (1-δ)*k -kp) + β*v(kp)
#njit
def T(v, og_VI):
k0 = og_VI.grid
v_greedy = np.empty_like(v)
v_new = np.empty_like(v)
f, δ = og_VI.f, og_VI.δ
for i in range(len(og_VI.grid)):
if i == 1:
k = k0[i]
else:
k = kp[i]
lower = 1e-10
upper = f(k) + (1-δ)*k
result = brent_max(og_VI.objective, lower, upper, args=(k,v))
v_greedy, v_new = result[0], result[1]
return v_greedy, v_new
def solve_model_VI(og_VI, tol=1e-4, max_iter=1000, print_skip=20):
v = og_VI.grid
i = 0
error = tol + 1
while i < max_iter and error > tol:
v_greedy, v_new = T(v, og_VI)
error = np.max(np.abs(v - v_new))
i += 1
if i % print_skip == 0:
print(f"Error at iteration {i} is {error}.")
global kp
kp = v_greedy
v = v_new
if i == max_iter:
print("Failed to converge!")
if i < max_iter:
print(f"\nConverged in {i} iterations.")
return v_greedy, v_new
og_VI = OptimalGrowth_VI()
k_opt_VI, k_solution = solve_model_VI(og_VI)
TypingError Traceback (most recent call last)
Input In [51], in <module>
1 og_VI = OptimalGrowth_VI()
----> 2 k_opt_VI, k_solution = solve_model_VI(og_VI)
Input In [49], in solve_model_VI(og_VI, tol, max_iter, print_skip)
4 error = tol + 1
6 while i < max_iter and error > tol:
----> 7 v_greedy, v_new = T(v, og_VI)
8 error = np.max(np.abs(v - v_new))
9 i += 1
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Cannot unify array(float64, 1d, C) and float64 for 'v_new.2', defined at /var/folders/yl/t420gknx17d8ppt9jgws8v700000gn/T/ipykernel_19631/2325054440.py (21)
File "../../../../../var/folders/yl/t420gknx17d8ppt9jgws8v700000gn/T/ipykernel_19631/2325054440.py", line 21:
<source missing, REPL/exec in use?>
During: typing of assignment at /var/folders/yl/t420gknx17d8ppt9jgws8v700000gn/T/ipykernel_19631/2325054440.py (21)
File "../../../../../var/folders/yl/t420gknx17d8ppt9jgws8v700000gn/T/ipykernel_19631/2325054440.py", line 21:
<source missing, REPL/exec in use?>
I don't know what is incorrect in my code. Is it related to numba, or do I made completely incorrect code?
It's related to economic problem, so I made a question to economics stack exchange but could not get an answer. I would be very grateful if you could help even if it bothers you.
I refer to
https://python.quantecon.org/optgrowth.html and
https://python.quantecon.org/optgrowth_fast.html
. thank you for your help.

how to change max recursion depth in Julia?

I was curious how quick and accurate, algorithm from Rosseta code ( https://rosettacode.org/wiki/Ackermann_function ) for (4,2) parameters, could be. But got StackOverflowError.
julia> using Memoize
#memoize ack3(m, n) =
m == 0 ? n + 1 :
n == 0 ? ack3(m-1, 1) :
ack3(m-1, ack3(m, n-1))
# WARNING! Next line has to calculate and print number with 19729 digits!
julia> ack3(4,2) # -> StackOverflowError
# has to be -> 2003529930406846464979072351560255750447825475569751419265016973710894059556311
# ...
# 4717124577965048175856395072895337539755822087777506072339445587895905719156733
EDIT:
Oscar Smith is right that trying ack3(4,2) is unrealistic. This is version translated from Rosseta's C++:
module Ackermann
function ackermann(m::UInt, n::UInt)
function ack(m::UInt, n::BigInt)
if m == 0
return n + 1
elseif m == 1
return n + 2
elseif m == 2
return 3 + 2 * n;
elseif m == 3
return 5 + 8 * (BigInt(2) ^ n - 1)
else
if n == 0
return ack(m - 1, BigInt(1))
else
return ack(m - 1, ack(m, n - 1))
end
end
end
return ack(m, BigInt(n))
end
end
julia> import Ackermann;Ackermann.ackermann(UInt(1),UInt(1));#time(a4_2 = Ackermann.ackermann(UInt(4),UInt(2)));t = "$a4_2"; println("len = $(length(t)) first_digits=$(t[1:20]) last digits=$(t[end-20:end])")
0.000041 seconds (57 allocations: 33.344 KiB)
len = 19729 first_digits=20035299304068464649 last digits=445587895905719156733
Julia itself does not have an internal limit to the stack size, but your operating system does. The exact limits here (and how to change them) will be system dependent. On my Mac (and I assume other POSIX-y systems), I can check and change the stack size of programs that get called by my shell with ulimit:
$ ulimit -s
8192
$ julia -q
julia> f(x) = x > 0 ? f(x-1) : 0 # a simpler recursive function
f (generic function with 1 method)
julia> f(523918)
0
julia> f(523919)
ERROR: StackOverflowError:
Stacktrace:
[1] f(::Int64) at ./REPL[1]:1 (repeats 80000 times)
$ ulimit -s 16384
$ julia -q
julia> f(x) = x > 0 ? f(x-1) : 0
f (generic function with 1 method)
julia> f(1048206)
0
julia> f(1048207)
ERROR: StackOverflowError:
Stacktrace:
[1] f(::Int64) at ./REPL[1]:1 (repeats 80000 times)
I believe the exact number of recursive calls that will fit on your stack will depend upon both your system and the complexity of the function itself (that is, how much each recursive call needs to store on the stack). This is the bare minimum. I have no idea how big you'd need to make the stack limit in order to compute that Ackermann function.
Note that I doubled the stack size and it more than doubled the number of recursive calls — this is because of a constant overhead:
julia> log2(523918)
18.998981503278365
julia> 2^19 - 523918
370
julia> log2(1048206)
19.99949084151746
julia> 2^20 - 1048206
370
Just fyi, even if you change the max recursion depth, you won't get the right answer as Julia uses 64 bit integers, so integer overflow with make stuff not work. To get the right answer, you will have to use big ints to have any hope. The next problem is that you probably don't want to memoize, as almost all of the computations are not repeated, and you will be computing the function more than 10^19729 different inputs, which you really do not want to store.

Gathering segments of 2D arrays with MPI in FORTRAN

I have a code which follows particles and outputs the particles at N timeslices. So what I have in the end is an array TEMP(1:M,0:N) where M is the total number of particles. Now the problem is easily made parallel by dividing up the particles. So each processor does work on an array TEMP(MYSTART:MYEND,0:N), while the master does it's work in TEMP(1:M,0:N). Now I need to recombine the array (there are actually multiple arrays like this but focus on one for now). Using a SENDV-RECV loop I coded up:
IF (myid == master) THEN
ALLOCATE(B_lines(1:nlines,0:nsteps),...
ELSE
ALLOCATE(B_lines(mystart:myend,0:nsteps),...
END IF
CALL MPI_BARRIER(MPI_COMM_FIELDLINES,ierr_mpi)
IF (ierr_mpi /=0) CALL andle_err(MPI_BARRIER_ERR,'fieldlines_init',ierr_mpi)
IF (myid == master) THEN
ALLOCATE(buffer_mast(4,0:nsteps))
DO i = myend+1, nlines
CALL MPI_RECV(buffer_mast,4*(nsteps+1),MPI_DOUBLE_PRECISION,&
MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_FIELDLINES,status,ierr_mpi)
IF (ierr_mpi /=0) CALL handle_err(MPI_RECV_ERR,'fieldlines_init_mgrid',ierr_mpi)
sender = status(MPI_SOURCE)
j = status(MPI_TAG)
R_lines(j,:) = buffer_mast(1,:)
Z_lines(j,:) = buffer_mast(2,:)
PHI_lines(j,:) = buffer_mast(3,:)
B_lines(j,:) = buffer_mast(4,:)
END DO
DEALLOCATE(buffer_mast)
ELSE
IF (mystart <= nlines) THEN
ALLOCATE(buffer_slav(4,0:nsteps))
DO j = mystart, myend
buffer_slav(1,:) = R_lines(j,:)
buffer_slav(2,:) = Z_lines(j,:)
buffer_slav(3,:) = PHI_lines(j,:)
buffer_slav(4,:) = B_lines(j,:)
CALL MPI_SEND(buffer_slav,4*(nsteps+1),MPI_DOUBLE_PRECISION,master,j,MPI_COMM_FIELDLINES,ierr_mpi)
IF (ierr_mpi /=0) CALL handle_err(MPI_SEND_ERR,'fieldlines_init_mgrid',ierr_mpi)
END DO
DEALLOCATE(buffer_slav)
END IF
END IF
Now this works just fine but scales poorly. Even with only 64 cores the code spends a great deal of time just sending the data back and forth. Now I'd like to take advantage of GATHERV. So I created a subroutine which I call like:
CALL FIELDLINES_TRANSMIT_2DDBL(mystart,myend,0,nsteps,B_lines(mystart:myend,0:nsteps),&
numprocs,mnum,moffsets,myid,master,MPI_COMM_FIELDLINES,ier)
And looks like:
SUBROUTINE FIELDLINES_TRANSMIT_2DDBL(n1,n2,m1,m2,data_in,nproc,mnum,moffsets,id,root,COMM_local,ier)
USE stel_kinds, ONLY: rprec
IMPLICIT NONE
INCLUDE 'mpif.h' ! MPI
INTEGER, INTENT(in) :: n1,n2,m1,m2,nproc,id,root,COMM_local
INTEGER, INTENT(in) :: mnum(nproc), moffsets(nproc)
REAL(rprec), INTENT(inout) :: data_in(n1:n2,m1:m2)
INTEGER, INTENT(inout) :: ier
INTEGER, PARAMETER :: ndims=2
INTEGER, PARAMETER :: sstart(2) = (/0,0/) ! Starting offsets
INTEGER :: dbl_size, localsize, ARRAY_SEND_TYPE, RESIZED_ARRAY_SEND_TYPE
INTEGER :: asize(ndims), ssize(ndims), mrec(nproc)
INTEGER(KIND=MPI_ADDRESS_KIND):: low_bound,extent
DOUBLE PRECISION, ALLOCATABLE :: buffer_temp(:,:)
IF (ier <0) RETURN
mrec = 1
ssize(1) = n2-n1+1
ssize(2) = m2-m1+1
localsize = mnum(id+1)
ALLOCATE(buffer_temp(ssize(1),ssize(2)))
buffer_temp(1:ssize(1),1:ssize(2)) = data_in(n1:n2,m1:m2)
asize = ssize
CALL MPI_BCAST(asize, 2, MPI_INTEGER, root, COMM_local, ier)
CALL MPI_TYPE_CREATE_SUBARRAY(ndims,asize,ssize,sstart,MPI_ORDER_FORTRAN,&
MPI_DOUBLE_PRECISION,ARRAY_SEND_TYPE,ier)
CALL MPI_TYPE_COMMIT(ARRAY_SEND_TYPE,ier)
CALL MPI_TYPE_SIZE(MPI_DOUBLE_PRECISION, dbl_size,ier)
low_bound = 0
extent = dbl_size
CALL MPI_TYPE_CREATE_RESIZED(ARRAY_SEND_TYPE,low_bound,extent,RESIZED_ARRAY_SEND_TYPE,ier)
CALL MPI_TYPE_COMMIT(RESIZED_ARRAY_SEND_TYPE,ier)
IF (id == root) THEN
localsize = PRODUCT(ssize)
mrec(1) = localsize
CALL MPI_GATHERV(MPI_IN_PLACE,1,MPI_DOUBLE_PRECISION,&
data_in,mrec, moffsets,RESIZED_ARRAY_SEND_TYPE,&
root,COMM_local,ier)
ELSE
CALL MPI_GATHERV(buffer_temp,localsize,MPI_DOUBLE_PRECISION,&
buffer_temp,mrec, moffsets,RESIZED_ARRAY_SEND_TYPE,&
root,COMM_local,ier)
END IF
CALL MPI_TYPE_FREE(ARRAY_SEND_TYPE,ier); IF (ier <0) RETURN
CALL MPI_TYPE_FREE(RESIZED_ARRAY_SEND_TYPE,ier); IF (ier <0) RETURN
DEALLOCATE(buffer_temp)
ier = 0
CALL MPI_BARRIER(COMM_local, ier)
RETURN
END SUBROUTINE FIELDLINES_TRANSMIT_2DDBL
Now I had another code which had opposite indexing (0:nsteps,1:nlines) and it appears to work just fine, but when I try to pass the arrays indexed (1:nlines,0:nsteps) the resulting array appears to all messed up. Any advice would be appreciated.
I'm not exactly clear about all the details of your setup, but here is a simple solution that illustrates how to do it under the restriction that the work divides exactly among processes, i.e. nlines is a multiple of size.
In this case, the pattern at the master is a simple vector (i.e. a 2D subarray). The only trick is to resize the vector appropriately so that the contributions line up correctly at the receiver. You don't need to use Gatherv - each process sends a bunch of doubles and the master receives a single vector from everyone.
The solution for the general case depends on how you split up the data when it does not divide exactly. You could use this solution if all the processes have the same amount of data except for the last one who has less data, but you pad out the data on the last process so that it can send and receive the same amount of data as the rest (including some dummy data).
I initialise the data so that, for example, at step 3 the values of the lines distributed across processes are 301, 302, 303, ... 300+nlines. If I run on 4 processes with 12 lines and 4 steps then the output looks correct:
laptop:~$ mpiexec -n 4 ./gather2d
rank, mystart, myend 2 7 9
rank, mystart, myend 1 4 6
rank, mystart, myend 0 1 3
rank, mystart, myend 3 10 12
1 101 201 301 401
2 102 202 302 402
3 103 203 303 403
4 104 204 304 404
5 105 205 305 405
6 106 206 306 406
7 107 207 307 407
8 108 208 308 408
9 109 209 309 409
10 110 210 310 410
11 111 211 311 411
12 112 212 312 412
Here's the code:
program gather2d
use mpi
implicit none
integer :: nlines, nsteps
integer :: comm, rank, size, ierr, arraytype, arraytyperesized
integer :: mystart, myend
integer :: i, j
integer :: dblesize
double precision, allocatable, dimension(:,:) :: B_lines
integer(kind=mpi_address_kind) lb, extent
comm = MPI_COMM_WORLD
nlines = 12
nsteps = 4
call MPI_Init(ierr)
call MPI_Comm_size(comm, size, ierr)
call MPI_Comm_rank(comm, rank, ierr)
mystart = nlines/size * rank + 1
myend = nlines/size * (rank+1)
write(*,*) 'rank, mystart, myend ', rank, mystart, myend
if (rank == 0) then
allocate(B_lines(1:nlines, 0:nsteps))
else
allocate(B_lines(mystart:myend, 0:nsteps))
end if
do i = mystart, myend
do j = 0, nsteps
B_lines(i,j) = i+100*j
end do
end do
call MPI_Type_vector(nsteps+1, myend-mystart+1, nlines, &
MPI_DOUBLE_PRECISION, arraytype, ierr)
call MPI_Type_size(MPI_DOUBLE_PRECISION, dblesize, ierr)
lb = 0
extent = (myend-mystart+1)*dblesize
call MPI_Type_Create_resized(arraytype, lb, extent, arraytyperesized, ierr)
call MPI_Type_commit(arraytyperesized, ierr)
if (rank == 0) then
call MPI_Gather(MPI_IN_PLACE, (nsteps+1)*(myend-mystart+1), &
MPI_DOUBLE_PRECISION, &
B_lines, 1, arraytyperesized, 0, comm, ierr)
else
call MPI_Gather(B_lines, (nsteps+1)*(myend-mystart+1), &
MPI_DOUBLE_PRECISION, &
B_lines, 1, arraytyperesized, 0, comm, ierr)
end if
if (rank == 0) then
do i = 1, nlines
write(*,*) (int(B_lines(i,j)), j = 0, nsteps)
end do
end if
call MPI_Finalize(ierr)
end program gather2d
OK so I found a memory hungry way to do this. Basically I put everything is globally sized arrays and use MPI_REDUCE. This is much faster than my old queue system but at the cost of memory. Here's the code
SUBROUTINE TRANSMIT_2DDBL(n1,n2,m1,m2,data_in,n1_gbl,n2_gbl,id,root,COMM_local,ier)
IMPLICIT NONE
INCLUDE 'mpif.h' ! MPI
INTEGER, INTENT(in) :: n1,n2,m1,m2,id,root,COMM_local
INTEGER, INTENT(in) :: n1_gbl, n2_gbl
DOUBLE PRECISION, INTENT(inout) :: data_in(n1:n2,m1:m2)
INTEGER, INTENT(inout) :: ier
INTEGER :: nt_gbl
DOUBLE PRECISION, ALLOCATABLE :: buffer_temp(:,:)
IF (ier <0) RETURN
nt_gbl=(n2_gbl-n1_gbl+1)*(m2-m1+1)
ALLOCATE(buffer_temp(n1_gbl:n2_gbl,m1:m2))
buffer_temp = 0
buffer_temp(n1:n2,m1:m2) = data_in(n1:n2,m1:m2)
IF (id == root) THEN
CALL MPI_REDUCE(MPI_IN_PLACE,buffer_temp,nt_gbl,MPI_DOUBLE_PRECISION,MPI_SUM,&
root,COMM_local,ier)
data_in = buffer_temp
ELSE
CALL MPI_REDUCE(buffer_temp,buffer_temp,nt_gbl,MPI_DOUBLE_PRECISION,MPI_SUM,&
root,COMM_local,ier)
END IF
DEALLOCATE(buffer_temp)
ier = 0
CALL MPI_BARRIER(COMM_local, ier)
RETURN
END SUBROUTINE TRANSMIT_2DDBL
Of course the root process needs to pass n1_gbl and n2_gbl as n1 and n2 respectively before entering. But it seems to improve performance for me.

Negative numbers in Zmod?

I'm doing the following in sage:
sage: Zp = Zmod(101)
sage: Zp(5)
5
sage: Zp(-1)
100
sage: Zp(100)
100
I understand that -1 = 100 mod 101, but I would like for sage to output -1 instead of 100 in both instances.
More generally, when working in Zmod(p), I would like the output to be in the interval (-p/2, p/2].
Since IntegerMod_int is implemented in Cython for speed, you can't change this behavior at runtime. The easiest way to get the feature you want is to change the repr function defined at sage/rings/finite_rings/integer_mod.pyx, line 1462 (at least, that's the line number in 5.0-beta12). Replace it with something like
def _repr_(self):
x = self.lift()
modulus = self.parent().modulus()
if x <= modulus // 2:
return str(x)
else:
return str(x-modulus)

Resources