% We wish to cross a river swimming with speed v=1m/s, the river
% floating with vr=4m/s. The river is b=100m broad.
>v=1; vr=4; b=100;
% We take an angle a to the river coast. Let us first write a
% function that computes the time it takes to cross the river.
% 
% We access the global variables b,v and vr directly. An alternative
% is to pass these values as parameters.
>function t(a)
$global b,v;
$return b/(sin(a)*v);
$endfunction
% Then we write a function that computes the drift for angle a.
% This is the length that the river floats while we are crossing
% it, minus the work we do upstream during that time.
>function drift(a)
$global b,v,vr;
$t=t(a);
$return t*vr-cos(a)*v*t;
$endfunction
% We can compute the drift for various angles.
>fplot("drift(rad(x))",1,90);
>fplot("drift(rad(x))",40,90);
% There is an optimal angle.
>deg(fmin("drift",5°,90°))
      75.5225 
% If the river is slower, we get a different optimal angle.
>vr=2; deg(fmin("drift",5°,90°))
           60 
% Let us write a function to compute the optimal angle for any
% river speed.
>function opt (x)
$global vr;
$vr=x;
$return fmin("drift",5°,90°));
$endfunction
% And a variant returning the optimal angle in degrees.
>function optdeg (x)
$return deg(opt(x))
$endfunction
% Plot this function.
% 
% If the river speed goes to infinity, we must take the 90° angle,
% since it is important to cross as fast as possible. If the river
% moves as slow as the swimmer, we need to go towards 0°, essentially
% swimming upstream. The drift then goes to 0.
% 
% If the river flows slower than the swimmer, we can reach any
% point on the opposite river bank.
>fplot("optdeg",1,20);
% To study the dependence of the optimal angle on v, vr or b,
% we define the following function.
>function opt3 (v1,vr1,b1)
$global v,vr,b; v=v1; vr=vr1; b=b1;
$return fmin("drift",1°,90°));
$endfunction
% It is quite clear that the angle would not depend on b. Thus
% it does not help to change the angle during the crossover.
>deg(opt3(1,4,100)), deg(opt3(1,4,200)),
      75.5225 
      75.5225 
% The following plot does not help very much.
>v1=1:0.1:2; vr1=2:0.2:4; zoom(3); framedsolid(v1,vr1',map("opt3",v1,vr1',b),1);
% It's better to think a little bit and due to scaling, the angle
% will not change if the v/vr is the same as before.
>deg(opt3(1,4,100)), deg(opt3(2,8,100)),
      75.5225 
      75.5225 
% We now compute opt(x) with Yacas. This requires some handwork,
% since Yacas is not as mighty as Maple or other systems. Especially,
% the solve function does not work so well.
>yacas("(vr-Cos(a)*v)*b/(Sin(a)*v)")
((vr-Cos(a)*v)*b)/(Sin(a)*v)
% We differentiate to find the minimum.
>yacas("D(a) %")
(b*(Sin(a)*v)^2-(vr-Cos(a)*v)*b*Cos(a)*v)/(Sin(a)*v)^2
% To solve for a, we substitute t=Sin(a).
>yacas("Subst(Sin(a),t) Subst(Cos(a),Sqrt(1-t^2)) %")
(b*(t*v)^2-(vr-Sqrt(1-t^2)*v)*b*Sqrt(1-t^2)*v)/(t*v)^2
% Taking the numinator.
>yacas("Simplify(%*(t*v)^2)")
v*b*(t^2*v+v*(1-t^2)-vr*Sqrt(1-t^2))
% Dividing off constants.
>yacas("Simplify(%/(v*b))")
v-vr*Sqrt(1-t^2)
% We now see the solution t=sqrt(1-(v/vr)^2). This is indeed,
% what we got numerically.
>fplot("deg(asin(sqrt(1-(v/x)^2)))",2,20);
% Now to another problem.
% 
% Assume we want to reach a point on the other side by walking
% with speed vd=2 after we climb out of the water. What is the
% optimal time for this?
% 
% We first reset our variables.
>v=1; vr=4; b=100;
% Then we write a function, computing the total time it takes
% to cross the river. That is the swimmming plus the walking time.
% The point, we want to reach is d meters from the point of the
% exact other side downstream.
% 
% This time, we do not access global variables, but pass the location
% d and the walking speed vd as parameters.
>function totaltime(a,d,vd)
$return t(a)+abs(drift(a)-d)/vd
$endfunction
% Lets us minimize this time choosing an optimal angle. We assume
% the point is 100m downstream.
>fplot("totaltime(rad(x),100,2),",1,179);
>fplot("totaltime(rad(x),100,2),",45,120);
>amin=fmin("totaltime",1°,179°;100,2); deg(amin)
      80.4059 
>drift(amin)
      388.771 
% Thus we have to swim, land 388m down the river, and walk back
% about 288m to our point of interest.
% 
% Surprisingly the angle does not change with d for a long time.
>deg(fmin("totaltime",1°,179°;200,2))
      80.4059 
>deg(fmin("totaltime",1°,179°;300,2))
      80.4059 
% The reason is the following: As long as we have to walk back,
% different distances d change the time only by a constant not
% depending on the angle of swimming. Thus, d does not matter
% for the optimal angle.
% 
% However, it is not optimal to choose the angle for minimal drift
% and then walk back. Instead, we must choose an angle that would
% be optimal for drift for a river with speed vr+vd. To see this,
% we would need to study the formula for the total time.
>deg(asin(sqrt(1-(v/(vr+2))^2)))
      80.4059 
% When d becomes largen than 388.771m, it is better to swim directly
% to the target.
>deg(fmin("totaltime",1°,179°;400,2))
           90 
>amin=fmin("totaltime",1°,179°;500,2); deg(amin)
      117.019 
% It seems, we now directly swim to the destination.
>drift(amin)
          500 
% If d tends to infinity, the angle will tend to 180°.
>amin=fmin("totaltime",1°,179°;800,2); deg(amin)
       143.13 
>drift(amin)
          800 
>amin=fmin("totaltime",1°,179°;8000,2); deg(amin)
      176.418 
>drift(amin)
         8000 
% To investigate this, we write a function totalmin, that computes
% the minimal time for a distance d.
>function totalmin (d,vd)
$return totaltime(fmin("totaltime",1°,179°;d,vd),d,vd);
$endfunction
% Let us plot this function, using xplot. totalmin does not work
% for vectors. So we must use "map" to evaluate it for a vector
% d.
>d=0:10:1000; t=map("totalmin",d;2); xplot(d,t);
% It looks, as if the function consists of two almost linear parts.
% 
% A closer plot confirms this.
>d=300:1:600; t=map("totalmin",d;2); xplot(d,t);
% Since our angle is larger than 90°, it will not help to swim
% slower.
>v=1; totalmin(500,2)
      112.251 
>v=0.9; totalmin(500,2)
      116.857 
>
