This is a very simple question, but found surprisingly very little about it online...
I want to find the minimizer of a function in maple, I am not sure how to indicate which is the variable of interest? Let us take a very simple case, I want the symbolic minimizer of a quadratic expression in x, with parameters a, b and c.
Without specifying something, it does minimize over all variables, a, b, c and x.
f4 := a+b*x+c*x^2
minimize(f4, location)
I tried to specify the variable in the function, did not work either:
f5 :=(x) ->a+b*x+c*x^2
minimize(f5, location)
How should I do this? And, how would I do if I wanted over two variables, x and y?
fxy := a+b*x+c*x^2 + d*y^2 +e*y
f4 := a+b*x+c*x^2:
extrema(f4, {}, x);
/ 2\
|4 a c - b |
< ---------- >
| 4 c |
\ /
fxy := a+b*x+c*x^2 + d*y^2 +e*y:
extrema(fxy, {}, {x,y});
/ 2 2\
|4 a c d - b d - c e |
< --------------------- >
| 4 c d |
\ /
The nature of the extrema will depend upon the values of the parameters. For your first example above (quadratic in x) it will depend on the signum of c.
The command extrema accepts an optional fourth argument, such as an unassigned name (or an uneval-quoted name) to which is assigns the candidate solution points (as a side-effect of its calculation). Eg,
restart;
f4 := a+b*x+c*x^2:
extrema(f4, {}, x, 'cand');
2
4 a c - b
{----------}
4 c
cand;
b
{{x = - ---}}
2 c
fxy := a+b*x+c*x^2 + d*y^2 +e*y:
extrema(fxy, {}, {x,y}, 'cand');
2 2
4 a c d - b d - c e
{---------------------}
4 c d
cand;
b e
{{x = - ---, y = - ---}}
2 c 2 d
Alternatively, you may set up the partial derivatives and solve them manually. Note that for these two examples there is just a one result (for each) returned by solve.
restart:
f4 := a+b*x+c*x^2:
solve({diff(f4,x)},{x});
b
{x = - ---}
2 c
normal(eval(f4,%));
2
4 a c - b
----------
4 c
fxy := a+b*x+c*x^2 + d*y^2 +e*y:
solve({diff(fxy,x),diff(fxy,y)},{x,y});
b e
{x = - ---, y = - ---}
2 c 2 d
normal(eval(fxy,%));
2 2
4 a c d - b d - c e
---------------------
4 c d
The code for the extrema command can be viewed, by issuing the command showstat(extrema). You can see how it accounts for the case of solve returning multiple results.
I am trying to decrypt a RSA message using the Chinese Remainder Theorem:
p = random_prime(2^512-1, False, 2^511)
q = random_prime(2^512-1, False, 2^511)
n = p * q
phi = (p - 1) * (q - 1)
m = 235432543543345
e = 65537
bezout = xgcd(e, phi)
d = Integer(mod(bezout[1], phi))
c = 0
m_decrypted = 0
def encrypt_rsa():
global c
c = mod(m ^ e, n)
print 'c = ', c
def decrypt_rsa_crt():
global m_decrypted
c1 = p * inverse_mod(p % q, q)
c2 = q * inverse_mod(q % p, p)
n1 = ((c % p) ^ (d % (p - 1))) % p
n2 = ((c % q) ^ (d % (q - 1))) % q
m_decrypted = (n1 * c1 + n2 * c2) % n
encrypt_rsa()
decrypt_rsa_crt()
print 'm_decrypted = ', m_decrypted
However I'm getting this error:
Error in lines 40-40
Traceback (most recent call last):
File "/projects/sage/sage-6.9/local/lib/python2.7/site-packages/smc_sagews/sage_server.py", line 905, in execute
exec compile(block+'\n', '', 'single') in namespace, locals
File "", line 1, in <module>
File "", line 15, in decrypt_rsa_crt
File "sage/structure/element.pyx", line 1700, in sage.structure.element.RingElement.__add__ (/projects/sage/sage-6.9/src/build/cythonized/sage/structure/element.c:16570)
return coercion_model.bin_op(left, right, add)
File "sage/structure/coerce.pyx", line 1070, in sage.structure.coerce.CoercionModel_cache_maps.bin_op (/projects/sage/sage-6.9/src/build/cythonized/sage/structure/coerce.c:9739)
raise TypeError(arith_error_message(x,y,op))
TypeError: unsupported operand parent(s) for '+': 'Ring of integers modulo 13171665913556629928579831399279531345454405227507363358767433731944129138880990155192020899186190552971738190528920869626603617749599336864307309151600773' and 'Ring of integers modulo 7040259687366349269925712273121165166901616380486072254231627613746850969231618371638459623994615760442997840722561781585598181676625437161073288718538017'
The line of the error is the m_decrypted = (n1 * c1 + n2 * c2) % n line. I'm not sure what I'm doing wrong here and how to fix it?
inverse_mod puts things in the ring of integers modulo q or p, in your code. But there is no canonical way to add c1 and c2 since they are in different rings of integers, as the error message indicates. I guess you may want to try to get those to be integers mod n instead, or even better to get just one of the integers.
I have a ppn array in Fortran, and I want to extract k*k subarray from that bigger array. I tried like this, but not sure does it work:
do i=1,p
vp(i)=i
end do
help=y(1:p,t)*vp
do t = 1, n
A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t)
end do
where y contains values 0 and 1, 1 meaning that row/column is wanted to subarray. Does that work, and if not, how that same thing could be archieved? Thanks.
If I understand what you want to do, here is an example program that extracts selected columns and rows, but not using much array notation.
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb
if (count (good_row) /= Adim .or. count (good_col) /= Adim) then
write (*, *) 'selection arrays not setup correctly.'
stop
end if
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
ja = 0
do jb=1, Bdim
if (good_col (jb)) then
ja = ja + 1
!write (*, *) ia, ja, ib, jb
A(ia,ja) = B(ib,jb)
end if
end do
end if
end do
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
Solution two, using array operations at the vector (1D array) level -- replace the main loop with:
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
A (ia,:) = pack (B(ib,:), good_col)
end if
end do
Solution three, fully using array operations:
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j
mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
A = reshape ( pack (B, mask), [Adim, Adim] )
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
Not sure if these fragments of non-code are any use to you but;
Don't forget the array sectioning features of Fortran.
Don't forget that you can use vector subscripts to get array sections, for example, you might select elements of a vector v like this:
v( (/1, 3, 6, 5, 10 /) )
Vector subscripting can be applied to arrays of rank greater than 1. It would hurt my head to figure out your subscripting requirements this way, but you might want to try it.
Yes it should work, and you even do not need the do t = ... loop
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
integer,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
y = (/ 1 , 0 , 1 , 1 /)
idx = (/ (i,i=1,4) /)
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
a(:,:,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end
compiled with gfortran 4.2.3 correctly gives me
b=
111 112 113 114
121 122 123 124
131 132 133 134
141 142 143 144
211 212 213 214
221 222 223 224
231 232 233 234
241 242 243 244
a=
111 113 114
131 133 134
141 143 144
211 213 214
231 233 234
241 243 244
You could also use
k = count( y> 0)
a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
Or think using LOGICAL .true. and .false. instead of 1 and 0...
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
logical,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
idx = (/ (i,i=1,4) /)
y = idx /= 2
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
k = count( y )
a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end