I'm doing a homework assignment in which I have to model the motion of an aircraft with a 4th order RK approximation. However, for some reason I keep getting results that indicate that all of my K values are zero when I iterate.
my main loop is as follows:
for(i=0;i<duration;i++){
t[i]=(i)*delta_t;
rho[i]=1.225*(exp((-0.0001)*z[i]));
Kx1=f(i, V_x[i], V_z[i], rho[i], z[i], m, S, Cl);
Kz1=g(i, V_x[i], V_z[i], rho[i], z[i], m, S, Cl, G);
Kx2=f(i, (V_x[i]+((Kx1*h)/2)), (V_z[i]+((Kz1*h)/2)), rho[i], z[i], m, S, Cl);
Kz2=g(i, (V_x[i]+((Kx1*h)/2)), (V_z[i]+((Kz1*h)/2)), rho[i], z[i], m, S, Cl, G);
Kx3=f(i, (V_x[i]+((Kx2*h)/2)), (V_z[i]+((Kz2*h)/2)), rho[i], z[i], m, S, Cl);
Kz3=g(i, (V_x[i]+((Kx2*h)/2)), (V_z[i]+((Kz2*h)/2)), rho[i], z[i], m, S, Cl, G);
Kx4=f(i, (V_x[i]+((Kx3*h)/2)), (V_z[i]+((Kz3*h)/2)), rho[i], z[i], m, S, Cl);
Kz4=g(i, (V_x[i]+((Kx3*h)/2)), (V_z[i]+((Kz3*h)/2)), rho[i], z[i], m, S, Cl, G);
V_x[i+1]=V_x[i]+(delta_t/6)*(Kx1+2*Kx2+2*Kx3+Kx4);
x[i+1]=x[i]+(V_x[i+1])*delta_t;
V_z[i+1]=V_z[i]+(delta_t/6)*(Kz1+2*Kz2+2*Kz3+Kz4);
z[i+1]=z[i]+(V_z[i+1])*delta_t;
t[0]=0;
x[0]=0;
z[0]=4800;
V_z[0]=0;
V_x[0]=210;
}
with V_z, V_x, x, z, and rho all being 1xduration arrays (I have duration defined as 400). f and g are two functions that return acceleration in x and z directions respectively. I've tested both externally and by hand and they work. I reinforced the boundary conditions in the loop (I've written them outside as well) because I was getting weird results otherwise, but that's beside the point of what I'm having trouble with: my K values all seem to be ending up equal to zero because V_x stays at 210 for each iteration, V_z stays at 0, and obviously then x and z don't change.
I created a quick test code in a separate file to calculate the K values without iterating just to make sure the algorithm is sound (all the same BCs, constants, etc., just no loop):
Kx1=f(i, V_x[0], V_z[0], rho[0], z[0], m, S, Cl);
Kz1=g(i, V_x[0], V_z[0], rho[0], z[0], m, S, Cl, G);
Kx2=f(i, (V_x[0]+((Kx1*h)/2)), (V_z[0]+((Kz1*h)/2)), rho[0], z[0], m, S, Cl);
Kz2=g(i, (V_x[0]+((Kx1*h)/2)), (V_z[0]+((Kz1*h)/2)), rho[0], z[0], m, S, Cl, G);
Kx3=f(i, (V_x[0]+((Kx2*h)/2)), (V_z[0]+((Kz2*h)/2)), rho[0], z[0], m, S, Cl);
Kz3=g(i, (V_x[0]+((Kx2*h)/2)), (V_z[0]+((Kz2*h)/2)), rho[0], z[0], m, S, Cl, G);
Kx4=f(i, (V_x[0]+((Kx3*h)/2)), (V_z[0]+((Kz3*h)/2)), rho[0], z[0], m, S, Cl);
Kz4=g(i, (V_x[0]+((Kx3*h)/2)), (V_z[0]+((Kz3*h)/2)), rho[0], z[0], m, S, Cl, G);
This returns the proper K values, so I'm at a complete loss as to why my V_x[i] and V_x[i] aren't changing in the loop.
Related
How to use maplist on inner term?
Assuming the KB is:
gate(not(o), i).
gate(not(i), o).
gate(and(o, i), o).
gate(and(i, o), o).
gate(and(B, B), B).
bits([i,o,o,i,i]).
The following is not working:
?- bits(BITS), maplist(gate(not(X), Y), BITS, ANS)
How can I map over the list so that:
[i,o,o,i,i] -> [not(i), not(o), not(o), not(i), not(i)] ->[o,i,i,o,o]
This is to be done on any list length:
:- bits([A,B,C,D,E]), gate(not(A), Anew), gate(not(B), Bnew), gate(not(C), Cnew), gate(not(D), Dnew), gate(not(E), Enew), ANS = [Anew, Bnew, Cnew, Dnew, Enew].
So that the answer would be: ANS = [o, i, i, o, o]
With a helper predicate:
not(A, Z) :-
gate(not(A), Z).
?- bits(BITS), maplist(not, BITS, ANS).
ANS = [o, i, i, o, o],
BITS = [i, o, o, i, i]
But if you are going to add two lines of helper, skip the gate() stuff and write directly:
not(o, i).
not(i, o).
?- bits(BITS), maplist(not, BITS, ANS).
ANS = [o, i, i, o, o],
BITS = [i, o, o, i, i]
If you don't want to do that, or cannot change the database at all, the only way I know is using a lambda library such as yall in SWI Prolog, others may be available to write this:
?- bits(BITS), maplist([In, Out]>>gate(not(In), Out), BITS, ANS).
ANS = [o, i, i, o, o],
BITS = [i, o, o, i, i]
(It might be bad form to name it not, but this is not/2 and the builtin is not/1 so I don't think it will clash).
0
https://docs.google.com/spreadsheets/d/1siXWH_83AFnymr58f72xBmwFlPG1O5ZHZgA1JqQNt0w/edit?usp=sharing Above is test document. I am trying to import information from sheet "AM Trip" to Sheet "BL AM", I only need some columns and only depending on if column T,U, or V has a 1 in it and that seems to be working. My problem is I wish the dropdown list in Cell B2 to change the information being imported which is starting from cell B6. I used below formula in Cell B6, but I have a parse error and not sure how to fix it.
=IFS(B2="That", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W WHERE (U is not null)", false)", B2="This", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W WHERE (V is not null)", false)", B2="Other", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W WHERE (T is not null)", false)")
When I look into the cell the section from "Select" to "is not null)" it is black and I am sure that is the issue but not sure how to fix it. Thanks for any help. Paul.
I'm new at this, but I think I found a couple of minor problems in your sheet.
First, your data validation list for, B2, does not require quotes. And I changed your list of values for B2 from "This","That","Other" to Soca,Salsa,Calypso.
The main issue was that your formula in B6 had quotes around the Query functions.
Lastly, I don't believe that IFS and QUERY work reliably together, so changed it to a multiple IF formula.
So I changed this:
=IFS(B2="Salsa", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (U is not null)", false)",
B2="Soca", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (V is not null)", false)",
B2="Calypso", "=QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (T is not null)", false)")
to this:
=IF( B2="Soca", QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (U is not null)", false),
IF( B2="Salsa", QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (V is not null)", false),
IF(B2="Calypso", QUERY('AM trip'!B7:W42,"SELECT C, E, G, L, O, P, Q, R, S, W
WHERE (T is not null)", false), "Blank")))
Here is a working example - your sheet was locked for editing, so I made a copy.
https://docs.google.com/spreadsheets/d/1HgyZURww4K_UTynxKCwZq6MxLh-58j3fccSC0fvxBa0/edit?usp=sharing
Let me know if you still have issues after seeing this.
Issue
I am trying to move all new lists that I create into one super list of lists. Instead the output is formatted as a bunch of individually changed lists.
The problem likely stems from the fact I use between to assign Iterations and Size, but I am not sure what else I can do.
Input
placeRedBlocks(4, X), loopReplace(X, Y), append([X], [Y], Z).
Expectation
Z = [[b, b, b, b], [r, r, r, b], [r, r, r, r], [b, r, r, r]]
Reality
X = [b, b, b, b],
Y = [r, r, r, b],
Z = [[b, b, b, b], [r, r, r, b]]
X = [b, b, b, b],
Y = [r, r, r, r],
Z = [[b, b, b, b], [r, r, r, r]]
X = [b, b, b, b],
Y = [b, r, r, r],
Z = [[b, b, b, b], [b, r, r, r]]
false
Code Explanation
This prolog code takes a list of values and replaces the designated values and returns it into another list.
placeRedBlocks(Length, List) :-
findall('b', between(1, Length, _), List).
replace([_|T], 0, X, [X|T]).
replace([H|T], I, X, [H|R]):-
I > -1,
NI is I-1,
replace(T, NI, X, R), !.
replaceX(A,_,0,_,A):- !.
replaceX(Line,Index,NumElm,Elm,NLine) :-
replace(Line,Index,Elm,BLine),
Index1 is Index+1,
NumElm1 is NumElm-1,
replaceX(BLine,Index1,NumElm1,Elm,NLine).
loopReplace(ListToReplace, NewList) :-
length(ListToReplace, Len),
TotalCount is Len-3,
between(0, TotalCount, Iterations),
between(3, Len, Size),
replaceX(ListToReplace, Iterations, Size, 'r', NewList).
In replaceX:
Line is the list you are trying to replace the values in. Index is the position in the list where you start replacing values. NumElm is the number of elements you are replacing in total. Elm is the character or number that replaces the other values in the list. NLine is the list where the output will go.
After messing around with findall/3 and bagof/3 I found an answer that works for my question.
Input
placeRedBlocks(7, X), findall(Y, loopReplace(X, Y), Z).
would get me
Z = [[r, r, r, b, b, b, b], [r, r, r, r, b, b, b], [r, r, r, r, r, b, b], [r, r, r, r, r, r, b], [r, r, r, r, r, r, r], [b, r, r, r, b, b, b], [b, r, r, r, r, b, b], [b, r, r, r, r, r, b], [b, r, r, r, r, r, r], [b, b, r, r, r, b, b], [b, b, r, r, r, r, b], [b, b, r, r, r, r, r], [b, b, b, r, r, r, b], [b, b, b, r, r, r, r], [b, b, b, b, r, r, r]]
In the following Fortran program I use Intel's MKL library to perform matrix multiplications using dgemm. Initially, I used the matmul subroutine and got correct results. When I translated matmul to dgemm in the loop below, I got all zero vectors instead of the correct output. I appreciate your help.
program spectral_norm
implicit none
!
integer, parameter :: n = 5500, dp = kind(0.0d0)
real(dp), allocatable :: A(:, :), u(:), v(:), Au(:), Av(:)
integer :: i, j
allocate(u(n), v(n), A(n, n), Au(n), Av(n))
do j = 1, n
do i = 1, n
A(i, j) = Ac(i, j)
end do
end do
u = 1
do i = 1, 10
call dgemm('N','N', n, 1, n, 1.0, A, n, u, n, 0.0, Au, n)
call dgemm('N','N', n, 1, n, 1.0, Au, n, A, n, 0.0, v, n)
call dgemm('N','N', n, 1, n, 1.0, A, n, v, n, 0.0, Av, n)
call dgemm('N','N', n, 1, n, 1.0, Av, n, A, n, 0.0, u, n)
!v = matmul(matmul(A, u), A)
!u = matmul(matmul(A, v), A)
end do
write(*, "(f0.9)") sqrt(dot_product(u, v) / dot_product(v, v))
contains
pure real(dp) function Ac(i, j) result(r)
integer, intent(in) :: i, j
r = 1._dp / ((i+j-2) * (i+j-1)/2 + i)
end function
end program spectral_norm
This gives NaN, while the correct output from matmul is 1.274224153.
Well, thank you all for your suggestions. I think I figured out the source of the error. The order of multiplication was reversed in two cases, it should have been A * Au and A * Av instead. This is because A has order n x n and both Au ans Av have order n x 1. So, we can't multiply Au * A or Av * A due to dimensions mismatch. I posted the corrected version below.
program spectral_norm
implicit none
!
integer, parameter :: n = 5500, dp = kind(0.d0)
real(dp), allocatable :: A(:,:), u(:), v(:), Au(:), Av(:)
integer :: i, j
allocate(u(n), v(n), A(n, n), Au(n), Av(n))
do j = 1, n
do i = 1, n
A(i, j) = Ac(i, j)
end do
end do
u = 1
do i = 1, 10
call dgemm('N', 'N', n, 1, n, 1._dp, A, n, u, n, 0._dp, Au, n)
call dgemm('T', 'N', n, 1, n, 1._dp, A, n, Au, n, 0._dp, v, n)
call dgemm('N', 'N', n, 1, n, 1._dp, A, n, v, n, 0._dp, Av, n)
call dgemm('T', 'N', n, 1, n, 1._dp, A, n, Av, n, 0._dp, u, n)
end do
write(*, "(f0.9)") sqrt(dot_product(u, v) / dot_product(v, v))
contains
pure real(dp) function Ac(i, j) result(r)
integer, intent(in) :: i, j
r = 1._dp / ((i+j-2) * (i+j-1)/2 + i)
end function
end program spectral_norm
This gives the correct results:
1.274224153
Elapsed time 0.5150000 seconds
I'm currently working on a Prolog program and having a lot of trouble figuring out how to implement it.
I want to put a list such as [1,2,2,1] into a function. I want it to multiply into itself to make a new matrix by doing this example.
1 * [1,2,2,1] which would yield [1,2,2,1]
2 * [1,2,2,1] which would yield [2,4,4,2]
2 * [1,2,2,1] which would yield [2,4,4,2]
1 * [1,2,2,1] which would yield [1,2,2,1]
And I want it to create all those together in a matrix like:
[[1,2,2,1],[2,4,4,2],[2,4,4,2],[1,2,2,1]].
Last part would be I want to zero out when I multiply by itself. So the 2nd spot would zero out the second spot making the final matrix:
[[0,2,2,1],[2,0,4,2],[2,4,0,2],[1,2,2,0]].
I want to have a predicate that calls another which makes each list. So heres my thoughts:
main(A,O):-
second(A,A,O).
second([],_,[]).
second([A|As],B,[O|Os]):- %creates the list of lists.
third(A,B,O),
second(As,B,Os).
third(_,[],[]).
third(A,[B|Bs],[O|Os]):-
fourth(A,B,O),
third(A,Bs,Os). %multiplies single digit by list.
fourth(A,B,0):- A == B.
fourth(A,B,O):- O is A * B.
I am getting the correct matrix but can not get the zero diagonal.
I just cant figure out a correct way to get the matrix with zeros down the diagonal. Any thoughts?
You can do the zeroes by introducing indices that indicate row and column you are at and check for a match:
main(A, O) :-
second(A, A, 0, O).
second([], _, _, []).
second([A|As], B, R, [O|Os]) :- %creates the list of lists.
third(A, B, 0, R, O),
R1 is R + 1,
second(As, B, R1, Os).
third(_, [], _, _, []).
third(A, [B|Bs], C, R, [O|Os]) :-
fourth(A, B, C, R, O),
C1 is C + 1,
third(A, Bs, C1, R, Os). %multiplies single digit by list.
fourth(_, _, X, X, 0).
fourth(A, B, C, R, O) :- C \== R, O is A * B.
Check:
| ?- main([1,2,2,1], L).
L = [[0,2,2,1],[2,0,4,2],[2,4,0,2],[1,2,2,0]] ? ;
no
Another interesting approach would be to create a maplist_with_index predicate which works just like maplist but manages an index and implicitly assumes the given predicate accepts the index as its first argument:
maplist_with_index(Pred, L, M) :-
maplist_with_index_(Pred, 0, L, M).
maplist_with_index_(Pred, I, [H|T], [M|Ms]) :-
Pred =.. [P|Pt],
append([P,I|Pt], [H], NewPred),
Call =.. NewPred,
call(Call, M),
I1 is I + 1,
maplist_with_index_(Pred, I1, T, Ms).
maplist_with_index_(_, _, [], []).
Then, the matrix program, using this predicate, looks like:
main(A, O) :-
second(A, A, O).
second(M, A, O) :-
maplist_with_index(third(A), M, O).
third(R, A, E, O) :-
maplist_with_index(fourth(R, E), A, O).
fourth(X, X, _, _, 0).
fourth(C, R, A, B, O) :- C \== R, O is A * B.