home *** CD-ROM | disk | FTP | other *** search
- Listing 1. The secant method algorithm in pseudocode form.
-
- To solve Left = Right:
-
- function Dif(X) = Left - Right
- where X occurs in Left and/or Right;
-
- procedure Solve;
- begin
- Guess1 := 1;
- Guess2 := 2;
- repeat
- Slope := (Dif(Guess2)-Dif(Guess1))/(Guess2-Guess1);
- Guess1 := Guess2;
- Guess2 := Guess2 - (Dif(Guess2)/Slope)
- until Guess2 is sufficiently close to Guess1;
- result is Guess2
- end.
-
- Listing 2. Procedures to set up the problem.
-
- % solve(Left=Right)
- %
- % On entry, Left=Right is an arithmetic
- % equation containing an uninstantiated
- % variable.
- %
- % On exit, that variable is instantiated
- % to an approximate numeric solution.
- %
- % The syntax of Left and Right is the same
- % as for expressions for the 'is' predicate.
-
- solve(Left=Right) :-
- free_in(Left=Right,X),
- !, /* accept only one solution of free_in */
- define_dif(X,Left=Right),
- solve_for(X).
-
- % free_in(Term,Variable)
- %
- % Variable occurs in Term and is uninstantiated.
-
- free_in(X,X) :- % An atomic term
- var(X).
-
- free_in(Term,X) :- % A complex term
- Term \== [[]],
- Term =.. [_,Arg|Args],
- (free_in(Arg,X) ; free_in(Args,X)).
-
- % define_dif(X,Left=Right)
- %
- % Defines a predicate to compute Left-Right
- % for the specified equation, given X.
-
- define_dif(X,Left=Right) :-
- abolish(dif,2),
- assert((dif(X,Dif) :- Dif is Left-Right)).
-
- Listing 3. Procedures to implement the secant method.
-
- % solve_for(Variable)
- %
- % Sets up arguments and calls solve_aux (below).
-
- solve_for(Variable) :-
- dif(1,Dif1),
- solve_aux(Variable,1,Dif1,2,1).
-
-
- % solve_aux(Variable,Guess1,Dif1,Guess2,Iteration)
- %
- % Uses the secant method to find a value of
- % Variable that will make the 'dif' procedure
- % return a value very close to zero.
- %
- % Arguments are:
- % Variable -- Will contain result.
- % Guess1 -- Previous estimated value.
- % Dif1 -- What 'dif' gave with Guess1.
- % Guess2 -- A better estimate.
- % Iteration -- Count of tries taken.
-
-
- solve_aux(cannot_solve,_,_,_,100) :-
- !,
- write('[Gave up at 100th iteration]'),nl,
- fail.
-
- solve_aux(Guess2,Guess1,_,Guess2,_) :-
- close_enough(Guess1,Guess2),
- !,
- write('[Found a satisfactory solution]'),nl.
-
- solve_aux(Variable,Guess1,Dif1,Guess2,Iteration) :-
- write([Guess2]),nl,
- dif(Guess2,Dif2),
- Slope is (Dif2-Dif1) / (Guess2-Guess1),
- Guess3 is Guess2 - (Dif2/Slope),
- NewIteration is Iteration + 1,
- solve_aux(Variable,Guess2,Dif2,Guess3,NewIteration).
-
- % close_enough(X,Y)
- %
- % True if X and Y are the same number to
- % within a factor of 0.0001.
- %
-
- close_enough(X,Y) :-
- Quot is X / Y,
- Quot > 0.9999,
- Quot < 1.0001.
-