parameter passing strategy in a semi-C code - pass-by-reference

it's a problem in my assignment.
Following code written in semi-C language. Set parameter passing type for f, g and h functions in order to have 29, 34 and 43 at the end of execution.for instance, for acquiring 29 we have to use call-by-value in f,g and h . but I don't know what should I do for 34 and 43?
f(x) {return g(2*x);}
g(x) {let y = 1 in {h(y); return x + y + x;}}
h(x) {x = x + 5; return 0}
main() {printf(f(7));}

Related

Using a function that has another function as parameter:

I want to integrate x^2 from 2 to 4 with the trapezoidal integration method. For this, I defined a function trap that takes 4 arguments:
function y = trap( fn, a, b, h )
n = (b-a)/h;
x = a + [1:n-1]*h;
y = h/2*(feval(fn, a) + feval(fn, b) + 2*sum(feval(fn,x)));
and a function f
function y= f(x)
y=x^2
end
Now, by executing trap(f,2,4,0.1), I get the following error:
Not enough input arguments.
Error in f (line 2)
y=x^2
What is the origin of that error?
You have to call trap using the function handle #f, not f.
trap(#f,2,4,0.1)
function y = trap( fn, a, b, h )
n = (b-a)/h;
x = a + [1:n-1]*h;
y = h/2*(fn(a) + fn(b) + 2*sum(fn(x)));
end
function y= f(x)
y = x.^2;
end
which gives, as expected,
ans =
18.67
Also you needed element-wise multiplication in f(x) to compute y = x.^2.
And feval is not necessary. You can directly call fn(a) to evaluate the function.

Integral within exponential within integral

I am trying to numerically integrate a few different expressions, but they all have an integral within an exponential, surrounded by another integral, i.e.
I can't seem to get this to solve using the code below:
syms s p t
W = 3.18*10^(-22);
b = 10^(-23);
X = 300;
L = 0.374;
intlim = 0.589;
myfuncirc = #(s,p,t) (-W).*sqrt((L.^2)-(s.^2)).*(((-p.*cos(t))+sqrt(1-((p.^2).*((sin(t)).^2)))-sqrt(L.^2-s.^2)).^(-2));
s_min = 0;
s_max = L;
t_min = 0;
t_max = pi;
integral(#(p)(p.*exp(-(integral2(#(s,t) myfuncirc(s,t,p),s_min,s_max,t_min,t_max))/(b.*X))),0,intlim,'Arrayvalued',true)
I get the error message shown below, but I'm expecting a number between 0 and 1:
Warning: Infinite or Not-a-Number value encountered.
In funfun\private\integralCalc>iterateArrayValued at 267
In funfun\private\integralCalc>vadapt at 130
In funfun\private\integralCalc at 75
In integral at 88
I'm also attempting a similar integration in the following form, but also not getting expected answers:
pmax = y;
pmin = 0;
ymax = 1;
ymin = #(x) x;
xmax = 1;
xmin = 0;
integral3(#(x,y,p) (exp(-(integral(#(s)myfun(s,p),0,lam,'ArrayValued',true)./(k.*T)))),xmin,xmax,ymin,ymax,pmin,pmax,'Method','iterated')
Warning: Infinite or Not-a-Number value encountered. > In funfun\private\integralCalc>iterateScalarValued at 349 In funfun\private\integralCalc>vadapt at 132 In funfun\private\integralCalc at 75 In funfun\private\integral2Calc>#(xi,y1i,y2i)integralCalc(#(y)fun(xiones(size(y)),y),y1i,y2i,opstruct.integralOptions) at 17 In funfun\private\integral2Calc>#(x)arrayfun(#(xi,y1i,y2i)integralCalc(#(y)fun(xiones(size(y)),y),y1i,y2i,opstruct.integralOptions),x,ymin(x),ymax(x)) at 17 In funfun\private\integralCalc>iterateScalarValued at 314 In funfun\private\integralCalc>vadapt at 132 In funfun\private\integralCalc at 75 In funfun\private\integral2Calc>integral2i at 20 In funfun\private\integral2Calc at 7 In integral3>innerintegral at 137 In funfun\private\integralCalc>iterateScalarValued at 314 In funfun\private\integralCalc>vadapt at 132 In funfun\private\integralCalc at 75 In integral3 at 121 Warning: The integration was unsuccessful. > In integral3 at 125
Problem 1 is you define
myfuncirc = #(s,p,t) ...
But when it is called it is called as
myfuncirc(s,t,p)
The arguments are not in the same order. You should change the definition of myfuncirc to
myfuncirc = #(s, t, p) ...
It's harder to tell for the second one because what you posted doesn't give the results you printed, it errors - several values are undefined such as myfun and k. However, I think the problem is that pmax is not defined as a function handle, but as a value - whatever is in y at the time pmax is assigned to. I suspect you want
pmax = #(x,y) y;

python optimising multiple functions with common variables

i am trying to minimize (globally) 3 functions that use common variables, i tried to combine them into one function and minimize that using L-BFGS-B(i need to set boundaries for the variables), but it has shown to be very difficult to balance each parameter with weightings, i.e. when one is minimised the other will not be. I also tried to use SLSQP method to minimize one of them while setting others as constraints, but the constraints are often ignored/not met.
Here are what need to be minimized, all the maths are done in meritscalculation and meritoflength, meritofROC, meritofproximity, heightorderreturnedare returned from the calculations as globals.
def lengthmerit(x0):
meritscalculation(x0)
print meritoflength
return meritoflength
def ROCmerit(x0):
meritscalculation(x0)
print meritofROC
return meritofROC
def proximitymerit(x0):
meritscalculation(x0)
print meritofproximity+heightorder
return meritofproximity+heightorder
i want to minimize all of them using a common x0 (with boundaries) as independent variable, is there a way to achieve this?
Is this what you want to do ?
minimize a * amerit(x) + b * bmerit(x) + c * cmerit(x)
over a, b, c, x:
a + b + c = 1
a >= 0.1, b >= 0.1, c >= 0.1 (say)
x in xbounds
If x is say [x0 x1 .. x9], set up a new variable abcx = [a b c x0 x1 .. x9],
constrain a + b + c = 1 with a penalty term added to the objective function,
and minimize this:
define fabc( abcx ):
""" abcx = a, b, c, x
-> a * amerit(x) + ... + penalty 100 (a + b + c - 1)^2
"""
a, b, c, x = abcx[0], abcx[1], abcx[2], abcx[3:] # split
fa = a * amerit(x)
fb = b * bmerit(x)
fc = c * cmerit(x)
penalty = 100 * (a + b + c - 1) ** 2 # 100 ?
f = fa + fb + fc + penalty
print "fabc: %6.2g = %6.2g + %6.2g + %6.2g + %6.2g a b c: %6.2g %6.2g %6.2g" % (
f, fa, fb, fc, penalty, a, b, c )
return f
and bounds = [[0.1, 0.5]] * 3 + xbounds, i.e. each of a b c in 0.1 .. 0.5 or so.
The long print s should show you why one of a b c approach 0 --
maybe one of amerit() bmerit() cmerit() is way bigger than the others ?
Plots instead of prints would be easy too.
Summary:
1) formulate the problem clearly on paper, as at the top
2) translate that into python.
here is the result of some scaling and weighting
objective function:
merit_function=wa*meritoflength*1e3+wb*meritofROC+wc*meritofproximity+wd*heightorder*10+1000 * (wa+wb+wc+wd-1) ** 2
input:
abcdex=np.array(( 0.5, 0.5, 0.1, 0.3, 0.1...))
output:
fun: array([ 7.79494644])
x: array([ 4.00000000e-01, 2.50000000e-01, 1.00000000e-01,
2.50000000e-01...])
meritoflength : 0.00465499380753. #target 1e-5, usually start at 0.1
meritofROC: 23.7317956542 #target ~1, range <33
Heightorder: 0 #target :strictly 0, range <28
meritofproximity : 0.0 #target:less than 0.02, range <0.052
i realised after a few runs, all the weightings tend to stay at the minimum values of the bound, and im back to manually tuning the scaling problem i started with.
Is there a possibility that my optimisation function isnt finding the true global minimum?
here is how i minimised it:
minimizer_kwargs = {"method": "L-BFGS-B", "bounds": bnds, "tol":1e0 }
ret = basinhopping(merit_function, abcdex, minimizer_kwargs=minimizer_kwargs, niter=10)
zoom = ret['x']
res = minimize(merit_function, zoom, method = 'L-BFGS-B', bounds=bnds, tol=1e-6)

Hash collision H(x)=H(y) with x!=y, does that also mean H(x+z)=H(y+z) for random z?

Suppose H is some hash function (such as MD5 or SHA256 or whatever) and I have a collision for this hash: two different pieces of data x and y, that have the same hash.
In other words x≠y but H(x)=H(y).
Now if I concatenate some random data z, will H(x+z) be the same as H(y+z) ?
The idea is: x and y being a collision may imply that they happen to bring the H function in the same state (thus resulting in the same hash). From that point on, it doesn't matter what other data we append, their hashes will remain equal.
I tested the above for this MD5 collision and it seemed to work there. But I don't know if this is true in general?
This particular technique is called a length extension attack. Whether or not a hash function is vulnerable obviously depends on the particular hash function. Hash functions based on the Merkle–Damgård construction, such as MD5 and SHA-1, are vulnerable. SHA-3 is not vulnerable, and HMAC constructions are also not vulnerable.
Depends on the has function. Since hash functions are not homomorphic (that is, where: f(x) = f(y) implies x = y), it does not follow that f(x + z) and f(y + z) will map to the same item. Consider a counter example:
Given the hash function
f(x) = (x * 3) + 1 mod 6
then f(2) = 1 and f(6) = 1. Let z = 1. Then:
f(2 + z) = 4 and f(6 + z) = 1
thus f(2) = f(6) but f(2 + z) ≠ f(6 + z).
However, if the hash function were homomorphic, then by definition of homomorphism:
f(p + q) = f(p) + f(q)
and therefore:
f(x + z) = f(x) + f(z)
f(y + z) = f(y) + f(z)
which but since f(x) = f(y) as you initially stated:
f(x) + f(z) = f(y) + f(z)
and so their hashes would be the same.
(Please be indulgent, it's my first answer :D)
Not necessarily:
Consider the following data (as lists of numbers)
x = [8 0 4]
y = [8 1 0]
z = [5]
and the hashing function:
H([a b c]) = a + b*c
H([a b c d]) = H([b c d]) + H([a b c])
Then, a collision for x and y occurs:
H(x) = H([8 0 4]) = 8 + 0*4 = 8
H(y) = H([8 1 0]) = 8 + 1*0 = 8
But when appending data, the hashes aren't equal:
H(z + x) = H([5 8 0 4]) = H([5 0 8]) + H([8 0 4]) = 5 + 8 = 13
H(z + y) = H([5 8 1 0]) = H([5 8 1]) + H([8 1 0]) = 13 + 8 = 21

Selecting k*k subarray from p*p*n array in Fortran

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