MathGroup Archive 2007

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Self-teaching snag

  • To: mathgroup at smc.vnet.net
  • Subject: [mg74573] Re: Self-teaching snag
  • From: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>
  • Date: Tue, 27 Mar 2007 03:55:28 -0500 (EST)
  • Organization: The Open University, Milton Keynes, UK
  • References: <eu7re0$b6p$1@smc.vnet.net>

Todd Allen wrote:
[snip]
> Here is the scenario:  I have written a basic function
> to tell me what percentage of battery power will
> remain in a battery after x number of days, provided
> that we start with a full charge and lose 5% of that
> charge per day.
> 
> If you execute the following code in Mathematica
> (V5.1):
> 
> charge[0]=1.0 (* 100% *);
> charge[day_]:=(charge[day-1]-(0.05*charge[day-1]));
> charge[20]
> 
> I receive an output of 0.358486 for my query at the 20
> day mark.....so, no problem so far.

You already have a major issue with the general recurrence relation. 
Basically, what you have defined is a double recurrence (like 
Fibonacci's numbers, but here the double recurrence is not needed. See 
below.) and the computational time grow exponentially.

Say you want the charge of the battery after 3 days.
To compute charge[3], you must compute charge[2] twice.
To compute charge[2], you must compute charge[1] twice.
To compute charge[1], you must compute charge[0] twice.

Therefore, to compute charge[3], you must compute charge[2] twice, 
charge[1] four times, and charge[0] eight times. You ask Mathematica to 
do 2 + 4 + 8 == 2^1 + 2^2 + 2^3 == 14 computations. (Here computation is 
synonymous of function call, overlooking details such as retrieving 
values, adding and multiplying them, and memory consumption.)

Without proving it formally (proof by induction), the relationship 
between the number of computations and the number of days (starting at 
1) is of the form Sum[2^i, {i, n}].

Let's check, with the help of Mathematica, how many computations are 
required for some number of days.

c[n_] := Sum[2^i, {i, n}]
Table[c[n], {n, 1, 10}]

{2, 6, 14, 30, 62, 126, 254, 510, 1022, 2046}

To get the value of the charge of the battery after 20 days, you must 
compute c[20] == 2097150 (over 2 millions of computation), and to get 
the value after 35 days, Mathematica must compute c[35] == 68719476734 
(nearly 70 billions of computations). No wonder it might takes some time 
to Mathematica to return an answer.

> However, when I try to ask for the output at
> charge[35], mathematica seems to enter an endless
> calculation.  I've let the computer run for as long as
> 5 minutes without getting an answer.  Is there
> something wrong with my function, my version of
> Mathematica or something else I haven't considered?

Now, let's improve the code. As stated previously, you do not need a 
double recursion, since the charge of the battery as of today, say, is 
95% of the charge of the battery of yesterday. (This is equivalent to 
charge of the battery of yesterday minus 5% of charge of battery of 
yesterday.)

Now, compare your original code against this simplified formula:

In[1]:=
Clear[charge];
charge[0] = 1.;
charge[day_Integer] := charge[day - 1] - 0.05*charge[day - 1];
Timing[charge[20]]

Out[4]=
{5.485 Second, 0.358486}

In[5]:=
Clear[charge];
charge[0] = 1.;
charge[day_Integer] := 0.95*charge[day - 1];
Timing[charge[20]]

Out[8]=
{0. Second, 0.358486}

We can even improve the performances, although this is not noticeable 
here, by using the technique described in section 2.5.9 of The 
Mathematica Book [1]. Note that it is easy to plot the values of the 
charge against the number of days and to check that the relationship is 
a decaying exponential, indeed.

In[9]:=
Clear[charge];
charge[0] = 1.;
charge[day_] := charge[day] = 0.95*charge[day - 1];
Timing[charge[50]]
ListPlot[Table[charge[n], {n, 0, 50}]];

Out[12]=
{0. Second, 0.076945}

[...graphic deleted...]


> Additionally,
> 
> When I try the following:
> 
> In[145]:=
> Solve[charge[day]==0.15,day];
> 
> Mathematica gives me the error:
> "$RecursionLimit::reclim: Recursion depth of 256
> exceeded."
> 
> I am trying to ask Mathematica to tell my how many
> days it takes to reduce the battery power to 15
> percent, but I must be messing something up??
[snip]

To get an answer, you can use a plot, or an interpolating function, or 
solve the following initial-value problem (first-order differential 
equation of an exponential decay).

In[14]:=
Clear[charge];
eqn = Derivative[1][charge][t] == (-5/100)*charge[t];
iv = charge[0] == 1;
sol = DSolve[eqn && iv, charge, t]
Plot[charge[t] /. sol[[1]], {t, 0, 50}];

Out[17]=
                            -t/20
{{charge -> Function[{t}, E     ]}}

[...graphic deleted...]

In[19]:=
Solve[(charge[t] /. sol[[1]]) == 0.15, t]

Solve::ifun: Inverse functions are being used by Solve, so some 
solutions may not be found; use Reduce for complete solution 
information. More...

(* You can disregard the warning message above. *)

Out[19]=
{{t -> 37.9424}}

In[20]:=
charge[t] /. sol[[1]] /. %[[1]]

Out[20]=
0.15

In[21]:=
Reduce[(charge[t] /. sol[[1]]) == 15/100, t, Reals]

Out[21]=
             20
t == 20 Log[--]
             3

In[22]:=
N[%]

Out[22]=
t == 37.9424

Regards,
Jean-Marc

[1] "2.5.9 Functions That Remember Values They Have Found"
http://documents.wolfram.com/mathematica/book/section-2.5.9


  • Prev by Date: Re: Self-teaching snag
  • Next by Date: Re: Re: Definite Integration in Mathematica
  • Previous by thread: Re: Self-teaching snag
  • Next by thread: Re: Self-teaching snag