Probability of a disjunction on N dependent events in Prolog - prolog

Does anybody know where to find a Prolog algorithm for computing the probability of a disjunction for N dependent events? For N = 2 i know that P(E1 OR E2) = P(E1) + P(E2) - P(E1) * P(E2), so one could do:
prob_disjunct(E1, E2, P):- P is E1 + E2 - E1 * E2
But how can this predicate be generalised to N events when the input is a list? Maybe there is a package which does this?
Kinds regards/JCR

The recursive formula from Robert Dodier's answer directly translates to
p_or([], 0).
p_or([P|Ps], Or) :-
p_or(Ps, Or1),
Or is P + Or1*(1-P).
Although this works fine, e.g.
?- p_or([0.5,0.3,0.7,0.1],P).
P = 0.9055
hardcore Prolog programmers can't help noticing that the definition isn't tail-recursive. This would really only be a problem when you are processing very long lists, but since the order of list elements doesn't matter, it is easy to turn things around. This is a standard technique, using an auxiliary predicate and an "accumulator pair" of arguments:
p_or(Ps, Or) :-
p_or(Ps, 0, Or).
p_or([], Or, Or).
p_or([P|Ps], Or0, Or) :-
Or1 is P + Or0*(1-P),
p_or(Ps, Or1, Or). % tail-recursive call

I don't know anything about Prolog, but anyway it's convenient to write the probability of a disjunction of a number of independent items p_m = Pr(S_1 or S_2 or S_3 or ... or S_m) recursively as
p_m = Pr(S_m) + p_{m - 1} (1 - P(S_m))
You can prove this by just peeling off the last item -- look at Pr((S_1 or ... or S_{m - 1}) or S_m) and just write that in terms of the usual formula, writing Pr(A or B) = Pr(A) + Pr(B) - Pr(A) Pr(B) = Pr(B) + Pr(A) (1 - Pr(B)), for A and B independent.
The formula above is item C.3.10 in my dissertation: http://riso.sourceforge.net/docs/dodier-dissertation.pdf It is a simple result, and I suppose it must be an exercise in some textbooks, although I don't remember seeing it.

For any event E I'll write E' for the complementary event (ie E' occurs iff E doesn't).
Then we have:
P(E') = 1 - P(E)
(A union B)' = A' inter B'
A and B are independent iff A' and B' are independent
so for independent E1..En
P( E1 union .. union En ) = 1 - P( E1' inter .. inter En')
= 1 - product{ i<=i<=n | 1 - P(E[i])}

Related

Solving chain reactions in prolog

One of the recent Advent of code challenges tasks me with solving for the smallest amount of input material that I can use to apply a given set of reactions and get 1 unit of output material.
For example, given
10 ORE => 10 A
1 ORE => 1 B
7 A, 1 B => 1 C
7 A, 1 C => 1 D
7 A, 1 D => 1 E
7 A, 1 E => 1 FUEL
We need 31 total ore to make 1 fuel (1 to produce a unit of B, then 30 to make the requisite 28 A).
This year, I've been trying to push my programming-language horizons, so I've done most of the challenges in SML/NJ. This one seems—seemed—like a good fit for Prolog, given the little I know about it: logic programming, constraint solving, etc.
I haven't, however, been able to successfully model the constraints.
I started by turning this simple example into some facts:
makes([ore(10)], a(10)).
makes([ore(1)], b(1)).
makes([a(7), b(7)], c(1)).
makes([a(7), c(1)], d(1)).
makes([a(7), d(1)], e(1)).
makes([a(7), e(1)], fuel(1)).
To be honest, I'm not even sure if the list argument is a good structure, or if the functor notation (ore(10)) is a good model either.
Then I wanted to build the rules that allow you to say, e.g., 10 ore makes enough for 7 a:
% handles the case where we have leftovers?
% is this even the right way to model all this... when we have leftovers, we may
% have to use them in the "reaction"...
makes(In, Out) :-
Out =.. [F,N],
Val #>= N,
OutN =.. [F,Val],
makes(In, OutN).
This works1, but I'm not sure it's going to be adequate, since we may care about leftovers (this is a minimization problem, after all)?
I'm stuck on the next two pieces though:
I can ask what makes 7 A and get back 10 ore, but I can't ask what is enough for 20 A: how do I write a rule which encodes multiplication/integer factors?
I can say that 7 A and 1 E makes 1 fuel, but I can't state that recursively: that is, I cannot state that 14 A and 1 D also make 1 fuel. How do I write the rule that encodes this?
I'm open to alternate data encodings for the facts I presented—ultimately, I'll be scripting the transformation from Advent's input to Prolog's facts, so that's the least of my worries. I feel that if I can get this small example working, I can solve the larger problem.
?- makes(X, a(7)). gives back X=[ore(10)] infinitely (i.e., if I keep hitting ; at the prompt, it keeps going). Is there a way to fix this?
Not a direct answer to your specific question but my first thought on this problem was to use chr in Prolog.
I then thought I would forward chain from fuel to the amount of ore I need.
The basic constraints:
:- chr_constraint ore/1, a/1, b/1,c/1, ab/1, bc/1, ca/1, fuel/0.
a(1),a(1) <=> ore(9).
b(1),b(1),b(1) <=> ore(8).
c(1),c(1),c(1),c(1),c(1) <=> ore(7).
ab(1) <=> a(3),b(4).
bc(1) <=> b(5),c(7).
ca(1) <=> c(4),a(1).
fuel <=> ab(2),bc(3),ca(4).
%Decompose foo/N into foo/1s
a(X) <=> X>1,Y#=X-1|a(Y),a(1).
b(X) <=> X>1,Y#=X-1|b(Y),b(1).
c(X) <=> X>1, Y#=X-1 | c(Y),c(1).
ab(X) <=> X>1, Y#=X-1|ab(Y),ab(1).
bc(X) <=> X>1,Y#=X-1| bc(Y),bc(1).
ca(X) <=> X>1, Y#= X-1| ca(Y),ca(1).
ore(X)<=>X >1, Y #= X -1 |ore(Y),ore(1).
%aggregation (for convenience)
:- chr_constraint ore_add/1, total_ore/1.
total_ore(A), total_ore(Total) <=> NewTotal #= A + Total, total_ore(NewTotal).
ore_add(A) ==> total_ore(A).
ore(1) <=> ore_add(1).
Query:
?-fuel.
b(1),
b(1),
c(1),
c(1),
ore_add(1),
ore_add(1),
...
total_ore(150).
Then you would need to add a search procedure to eliminate the two b/1s and two c/1s.
I have not implemented this but:
?-fuel,b(1),c(3).
ore_add(1),
...
total_ore(165)
This has only ore_add/1 constraints and is the correct result.
In the example there are no "alternative" path and no multiple "ore sources", so coding the example up in a very non-flexible way using Prolog can be done like this:
need(FUEL,OREOUT) :- need(FUEL,0,0,0,0,0,0,OREOUT).
need(FUEL,E,D,C,A,B,ORE,OREOUT) :- FUEL > 0, A2 is 7*FUEL+A, E2 is FUEL+E, need(0, E2, D, C, A2, B, ORE,OREOUT).
need(0,E,D,C,A,B,ORE,OREOUT) :- E > 0, A2 is 7*E+A, D2 is E+D, need(0, 0, D2, C, A2, B, ORE,OREOUT).
need(0,0,D,C,A,B,ORE,OREOUT) :- D > 0, A2 is 7*D+A, C2 is D+C, need(0, 0, 0, C2, A2, B, ORE,OREOUT).
need(0,0,0,C,A,B,ORE,OREOUT) :- C > 0, A2 is 7*C+A, B2 is C+B, need(0, 0, 0, 0, A2, B2, ORE,OREOUT).
need(0,0,0,0,A,B,ORE,OREOUT) :- X is A + B, X > 0, ORE2 is ORE + (A + 9)//10 + B, need(0, 0, 0, 0, 0, 0, ORE2,OREOUT).
need(0, 0, 0, 0, 0, 0, ORE, ORE).
Then
?- need(1011,ORE).
ORE = 3842
But this is just a silly and inelegant attempt.
There is a major general problem lurking thereunder, which includes parsing the arbitrarily complex reaction directed acyclic graph and building an appropriate structure. The good think is that it is a DAG, so one cannot generate an "earlier ingredient" from a "later one".
While making coffee, this is clearly something for the CLP(FD) engine.
If we have directed acyclic graph of reactions with
FUEL node on the right of the graph and
nodes for intermediate products IP[i] (i in 0..n) in between, with possibly
several FUEL nodes, i.e. several ways generating FUEL: FUEL[0] ... FUEL[v] and possibly
several nodes for intermediate products IP[i], i.e. several ways of creating intermediate product IP[i>0]: IP[i,1] ... IP[i,ways(i)] and
IP[0] identified with ORE on the left side of the graph
with the last two points giving us a way of choosing a strategy for the product mix, then:
FUEL_NEEDED = mix[0] * FUEL[0] + ... + mix[v] * FUEL[v]
with everything in the above a variable
and the following given by the problem statement, with FUEL[0] ... FUEL[v] variables and the rest constants:
out_fuel[0] * FUEL[0] = ∑_j ( IP[j] * flow(IPj->FUEL0) )
⋮
out_fuel[v] * FUEL[v] = ∑_j ( IP[j] * flow(IPj->FUELv) )
and for each IP[i>0], with the IP[i] variables and the rest constants:
out_ip[i] * IP[i] = ∑_j≠i ( IP[j] * flow(IPj->IPi) )
in case of a several ways to generate IP[i], we mix (this is like introducing a graph node for the mix of IP[i] from its possible ways IP[i,j]):
out_ip[i] * IP[i] = ∑_j(0..ways(i)) ( IP[i,j] * mix[i,j] )
out_ip[i,1] * IP[i,1] = ∑_j≠i ( IP[j] * flow(IP[j]->IP[i,1]) )
⋮
out_ip[i,ways(i)] * IP[i,ways(i)] = ∑_j≠i ( IP[j] * flow(IP[j]->IP[i,ways(i)]) )
and IP[0] (i.e. ORE) a free variable to be minimized.
You see an underspecified linear programming problem appearing here, with a matrix having zeroes below the diagonal because it's a DAG, but it contains variables to be optimized in the matrix itself. How to attack that?

Defining a mathematical language in prolog

So I have this mathematical language, it goes like this:
E -> number
[+,E,E,E] //e.g. [+,1,2,3] is 1+2+3 %we can put 2 to infinite Es here.
[-,E,E,E] //e.g. [-,1,2,3] is 1-2-3 %we can put 2 to infinite Es here.
[*,E,E,E] //e.g. [*,1,2,3] is 1*2*3 %we can put 2 to infinite Es here.
[^,E,E] //e.g. [^,2,3] is 2^3
[sin,E] //e.g. [sin,0] is sin 0
[cos,E] //e.g. [cos,0] is cos 0
and I want to write the set of rules that finds the numeric value of a mathematical expression written by this language in prolog.
I first wrote a function called "check", it checks to see if the list is written in a right way according to the language we have :
check1([]).
check1([L|Ls]):- number(L),check1(Ls).
check([L|Ls]):-atom(L),check1(Ls).
now I need to write the function "evaluate" that takes a list that is an expression written by this language, and a variable that is the numeric value corresponding to this language.
example:
?-evaluate([*,1,[^,2,2],[*,2,[+,[sin,0],5]]]],N) -> N = 40
so I wrote this:
sum([],0).
sum([L|Ls],N):- not(is_list(L)),sum(Ls,No),N is No + L.
min([],0).
min([L|Ls],N):-not(is_list(L)), min(Ls,No),N is No - L.
pro([],0).
pro([X],[X]).
pro([L|Ls],N):-not(is_list(L)), pro(Ls,No), N is No * L.
pow([L|Ls],N):-not(is_list(L)), N is L ^ Ls.
sin_(L,N):-not(is_list(L)), N is sin(L).
cos_(L,N):-not(is_list(L)), N is cos(L).
d([],0).
d([L|Ls],N):- L == '+' ,sum(Ls,N);
L == '-',min(Ls,N);
L == '*',pro(Ls,N);
L == '^',pow(Ls,N);
L == 'sin',sin_(Ls,N);
L == 'cos',cos_(Ls,N).
evaluate([],0).
evaluate([L|Ls],N):-
is_list(L) , check(L) , d(L,N),L is N,evaluate(Ls,N);
is_list(L), not(check(L)) , evaluate(Ls,N);
not(is_list(L)),not(is_list(Ls)),check([L|Ls]),d([L|Ls],N),
L is N,evaluate(Ls,N);
is_list(Ls),evaluate(Ls,N).
and it's working for just a list and returning the right answer , but not for multiple lists inside the main list, how should my code be?
The specification you work with looks like a production rule that describes that E (presumably short for Expression) might be a number or one of the 6 specified operations. That is the empty list [] is not an expression. So the fact
evaluate([],0).
should not be in your code. Your predicate sum/2 almost works the way you wrote it, except for the empty list and a list with a single element, that are not valid inputs according to your specification. But the predicates min/2 and pro/2 are not correct. Consider the following examples:
?- sum([1,2,3],X).
X = 6 % <- correct
?- sum([1],X).
X = 1 % <- incorrect
?- sum([],X).
X = 0 % <- incorrect
?- min([1,2,3],X).
X = -6 % <- incorrect
?- pro([1,2,3],X).
X = 6 ? ; % <- correct
X = 0 % <- incorrect
Mathematically speaking, addition and multiplication are associative but subtraction is not. In programming languages all three of these operations are usually left associative (see e.g. Operator associativity) to yield the mathematically correct result. That is, the sequence of subtractions in the above query would be calculated:
1-2-3 = (1-2)-3 = -4
The way you define a sequence of these operations resembles the following calculation:
[A,B,C]: ((0 op C) op B) op A
That works out fine for addition:
[1,2,3]: ((0 + 3) + 2) + 1 = 6
But it doesn't for subtraction:
[1,2,3]: ((0 - 3) - 2) - 1 = -6
And it is responsible for the second, incorrect solution when multiplying:
[1,2,3]: ((0 * 3) * 2) * 1 = 0
There are also some other issues with your code (see e.g. #lurker's comments), however, I won't go into further detail on that. Instead, I suggest a predicate that adheres closely to the specifying production rule. Since the grammar is describing expressions and you want to know the corresponding values, let's call it expr_val/2. Now let's describe top-down what an expression can be: It can be a number:
expr_val(X,X) :-
number(X).
It can be an arbitrarily long sequence of additions or subtractions or multiplications respectively. For the reasons above all three sequences should be evaluated in a left associative way. So it's tempting to use one rule for all of them:
expr_val([Op|Es],V) :-
sequenceoperator(Op), % Op is one of the 3 operations
exprseq_op_val(Es,Op,V). % V is the result of a sequence of Ops
The power function is given as a list with three elements, the first being ^ and the others being expressions. So that rule is pretty straightforward:
expr_val([^,E1,E2],V) :-
expr_val(E1,V1),
expr_val(E2,V2),
V is V1^V2.
The expressions for sine and cosine are both lists with two elements, the first being sin or cos and the second being an expression. Note that the argument of sin and cos is the angle in radians. If the second argument of the list yields the angle in radians you can use sin/1 and cos/2 as you did in your code. However, if you get the angle in degrees, you need to convert it to radians first. I include the latter case as an example, use the one that fits your application.
expr_val([sin,E],V) :-
expr_val(E,V1),
V is sin(V1*pi/180). % radians = degrees*pi/180
expr_val([cos,E],V) :-
expr_val(E,V1),
V is cos(V1*pi/180). % radians = degrees*pi/180
For the second rule of expr_val/2 you need to define the three possible sequence operators:
sequenceoperator(+).
sequenceoperator(-).
sequenceoperator(*).
And subsequently the predicate exprseq_op_val/3. As the leading operator has already been removed from the list in expr_val/2, the list has to have at least two elements according to your specification. In order to evaluate the sequence in a left associative way the value of the head of the list is passed as an accumulator to another predicate exprseq_op_val_/4
exprseq_op_val([E1,E2|Es],Op,V) :-
expr_val(E1,V1),
exprseq_op_val_([E2|Es],Op,V,V1).
that is describing the actual evaluation. There are basically two cases: If the list is empty then, regardless of the operator, the accumulator holds the result. Otherwise the list has at least one element. In that case another predicate, op_val_args/4, delivers the result of the respective operation (Acc1) that is then recursively passed as an accumulator to exprseq_op_val_/4 alongside with the tail of the list (Es):
exprseq_op_val_([],_Op,V,V).
exprseq_op_val_([E1|Es],Op,V,Acc0) :-
expr_val(E1,V1),
op_val_args(Op,Acc1,Acc0,V1),
exprseq_op_val_(Es,Op,V,Acc1).
At last you have to define op_val_args/4, that is again pretty straightforward:
op_val_args(+,V,V1,V2) :-
V is V1+V2.
op_val_args(-,V,V1,V2) :-
V is V1-V2.
op_val_args(*,V,V1,V2) :-
V is V1*V2.
Now let's see how this works. First your example query:
?- expr_val([*,1,[^,2,2],[*,2,[+,[sin,0],5]]],V).
V = 40.0 ? ;
no
The simplest expression according to your specification is a number:
?- expr_val(-3.14,V).
V = -3.14 ? ;
no
The empty list is not an expression:
?- expr_val([],V).
no
The operators +, - and * need at least 2 arguments:
?- expr_val([-],V).
no
?- expr_val([+,1],V).
no
?- expr_val([*,1,2],V).
V = 2 ? ;
no
?- expr_val([-,1,2,3],V).
V = -4 ? ;
no
The power function has exactly two arguments:
?- expr_val([^,1,2,3],V).
no
?- expr_val([^,2,3],V).
V = 8 ? ;
no
?- expr_val([^,2],V).
no
?- expr_val([^],V).
no
And so on...

Prolog program to get an (integer) number as the sum of two integer squares, why does it not work?

I'm starting learning Prolog and I want a program that given a integer P gives to integers A and B such that P = A² + B². If there aren't values of A and B that satisfy this equation, false should be returned
For example: if P = 5, it should give A = 1 and B = 2 (or A = 2 and B = 1) because 1² + 2² = 5.
I was thinking this should work:
giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B.
with the query:
giveSum(5, A, B).
However, it does not. What should I do? I'm very new to Prolog so I'm still making lot of mistakes.
Thanks in advance!
integer/1 is a non-monotonic predicate. It is not a relation that allows the reasoning you expect to apply in this case. To exemplify this:
?- integer(I).
false.
No integer exists, yes? Colour me surprised, to say the least!
Instead of such non-relational constructs, use your Prolog system's CLP(FD) constraints to reason about integers.
For example:
?- 5 #= A*A + B*B.
A in -2..-1\/1..2,
A^2#=_G1025,
_G1025 in 1..4,
_G1025+_G1052#=5,
_G1052 in 1..4,
B^2#=_G406,
B in -2..-1\/1..2
And for concrete solutions:
?- 5 #= A*A + B*B, label([A,B]).
A = -2,
B = -1 ;
A = -2,
B = 1 ;
A = -1,
B = -2 ;
etc.
CLP(FD) constraints are completely pure relations that can be used in the way you expect. See clpfd for more information.
Other things I noticed:
use_underscores_for_readability_as_is_the_convention_in_prolog instead ofMixingTheCasesToMakePredicatesHardToRead.
use declarative names, avoid imperatives. For example, why call it give_sum? This predicate also makes perfect sense if the sum is already given. So, what about sum_of_squares/3, for example?
For efficiency sake, Prolog implementers have choosen - many,many years ago - some compromise. Now, there are chances your Prolog implements advanced integer arithmetic, like CLP(FD) does. If this is the case, mat' answer is perfect. But some Prologs (maybe a naive ISO Prolog compliant processor), could complain about missing label/1, and (#=)/2. So, a traditional Prolog solution: the technique is called generate and test:
giveSum(P, A, B) :-
( integer(P) -> between(1,P,A), between(1,P,B) ; integer(A),integer(B) ),
P is A*A + B*B.
between/3 it's not an ISO builtin, but it's rather easier than (#=)/2 and label/1 to write :)
Anyway, please follow mat' advice and avoid 'imperative' naming. Often a description of the relation is better, because Prolog it's just that: a relational language.

Simplifying recursive mean calculation

If we have
Ei = mean [abs (Hi - p) for p in Pi]
H = mean [H0, H1, ... Hi, ... Hn]
P = concat [P0, P1, ... Pi, ... Pn]
then does there exist a more efficient way to compute
E = mean [abs (H - p) for p in P]
in terms of H, P, and the Eis and His, given that H, E, and P go on to be used as Hi, Ei, and Pi for some i, at a higher recursive level?
If we store the length of Pi as Li at each stage, then we can let
L = sum [L0, L1, ... Li, ... Ln]
allowing us to perform the somewhat easier calculation
E = sum ([abs (H - p) for p in P] / L)
but the use of the abs function seems to severely restrict the kinds of algebraic manipulations we can use to simplify the numerator.
No. Imagine you have just two groups, and one group has H1 = 1 and the other group has H2 = 2. Imagine that every p in P1 is either 0 or 2, and every p in P2 in is either 1 or 3. Now you will always have E1 = 1 and E2 = 1, regardless of the actual values in P1 and P2. However, you can see that if all p in P1 are 2, and all p in P2 are 1, then E will be minimized (specifically 0.5) because H = 1.5. Or all p in P1 could be 0 and all p in P2 could be 3, in which case E would be maximized. (specifically 1.5). And you could get any answer for E in between 0.5 and 1.5 depending on the distribution of the p. If you don't actually go and look at all the individual p, there's no way to tell what exact value of E you will get between 0.5 and 1.5. So you can't do any better than O(n) time to compute E, where n is the total size of P, which is the same running time if you just compute your desired quantity E directly from it's definition formula.

What's the formal term for a function that can be written in terms of `fold`?

I use the LINQ Aggregate operator quite often. Essentially, it lets you "accumulate" a function over a sequence by repeatedly applying the function on the last computed value of the function and the next element of the sequence.
For example:
int[] numbers = ...
int result = numbers.Aggregate(0, (result, next) => result + next * next);
will compute the sum of the squares of the elements of an array.
After some googling, I discovered that the general term for this in functional programming is "fold". This got me curious about functions that could be written as folds. In other words, the f in f = fold op.
I think that a function that can be computed with this operator only needs to satisfy (please correct me if I am wrong):
f(x1, x2, ..., xn) = f(f(x1, x2, ..., xn-1), xn)
This property seems common enough to deserve a special name. Is there one?
An Iterated binary operation may be what you are looking for.
You would also need to add some stopping conditions like
f(x) = something
f(x1,x2) = something2
They define a binary operation f and another function F in the link I provided to handle what happens when you get down to f(x1,x2).
To clarify the question: 'sum of squares' is a special function because it has the property that it can be expressed in terms of the fold functional plus a lambda, ie
sumSq = fold ((result, next) => result + next * next) 0
Which functions f have this property, where dom f = { A tuples }, ran f :: B?
Clearly, due to the mechanics of fold, the statement that f is foldable is the assertion that there exists an h :: A * B -> B such that for any n > 0, x1, ..., xn in A, f ((x1,...xn)) = h (xn, f ((x1,...,xn-1))).
The assertion that the h exists says almost the same thing as your condition that
f((x1, x2, ..., xn)) = f((f((x1, x2, ..., xn-1)), xn)) (*)
so you were very nearly correct; the difference is that you are requiring A=B which is a bit more restrictive than being a general fold-expressible function. More problematically though, fold in general also takes a starting value a, which is set to a = f nil. The main reason your formulation (*) is wrong is that it assumes that h is whatever f does on pair lists, but that is only true when h(x, a) = a. That is, in your example of sum of squares, the starting value you gave to Accumulate was 0, which is a does-nothing when you add it, but there are fold-expressible functions where the starting value does something, in which case we have a fold-expressible function which does not satisfy (*).
For example, take this fold-expressible function lengthPlusOne:
lengthPlusOne = fold ((result, next) => result + 1) 1
f (1) = 2, but f(f(), 1) = f(1, 1) = 3.
Finally, let's give an example of a functions on lists not expressible in terms of fold. Suppose we had a black box function and tested it on these inputs:
f (1) = 1
f (1, 1) = 1 (1)
f (2, 1) = 1
f (1, 2, 1) = 2 (2)
Such a function on tuples (=finite lists) obviously exists (we can just define it to have those outputs above and be zero on any other lists). Yet, it is not foldable because (1) implies h(1,1)=1, while (2) implies h(1,1)=2.
I don't know if there is other terminology than just saying 'a function expressible as a fold'. Perhaps a (left/right) context-free list function would be a good way of describing it?
In functional programming, fold is used to aggregate results on collections like list, array, sequence... Your formulation of fold is incorrect, which leads to confusion. A correct formulation could be:
fold f e [x1, x2, x3,..., xn] = f((...f(f(f(e, x1),x2),x3)...), xn)
The requirement for f is actually very loose. Lets say the type of elements is T and type of e is U. So function f indeed takes two arguments, the first one of type U and the second one of type T, and returns a value of type U (because this value will be supplied as the first argument of function f again). In short, we have an "accumulate" function with a signature f: U * T -> U. Due to this reason, I don't think there is a formal term for these kinds of function.
In your example, e = 0, T = int, U = int and your lambda function (result, next) => result + next * next has a signaturef: int * int -> int, which satisfies the condition of "foldable" functions.
In case you want to know, another variant of fold is foldBack, which accumulates results with the reverse order from xn to x1:
foldBack f [x1, x2,..., xn] e = f(x1,f(x2,...,f(n,e)...))
There are interesting cases with commutative functions, which satisfy f(x, y) = f(x, y), when fold and foldBack return the same result. About fold itself, it is a specific instance of catamorphism in category theory. You can read more about catamorphism here.

Resources