Diversity prediction theorem

From Rosetta Code
Task
Diversity prediction theorem
You are encouraged to solve this task according to the task description, using any language you may know.

The   wisdom of the crowd   is the collective opinion of a group of individuals rather than that of a single expert.

Wisdom-of-the-crowds research routinely attributes the superiority of crowd averages over individual judgments to the elimination of individual noise,   an explanation that assumes independence of the individual judgments from each other.

Thus the crowd tends to make its best decisions if it is made up of diverse opinions and ideologies.


Scott E. Page introduced the diversity prediction theorem:

The squared error of the collective prediction equals the average squared error minus the predictive diversity.


Therefore,   when the diversity in a group is large,   the error of the crowd is small.


Definitions
  •   Average Individual Error:   Average of the individual squared errors
  •   Collective Error:   Squared error of the collective prediction
  •   Prediction Diversity:   Average squared distance from the individual predictions to the collective prediction
  •   Diversity Prediction Theorem:   Given a crowd of predictive models,     then
  Collective Error   =   Average Individual Error   ─   Prediction Diversity
Task

For a given   true   value and a number of number of estimates (from a crowd),   show   (here on this page):

  •   the true value   and   the crowd estimates
  •   the average error
  •   the crowd error
  •   the prediction diversity


Use   (at least)   these two examples:

  •   a true value of   49   with crowd estimates of:   48   47   51
  •   a true value of   49   with crowd estimates of:   48   47   51   42


Also see
  •   Wikipedia entry:   Wisdom of the crowd
  •   University of Michigan: PDF paper         (exists on a web archive,   the Wayback Machine).



11l

Translation of: C++
F average_square_diff(a, predictions)
   R sum(predictions.map(x -> (x - @a) ^ 2)) / predictions.len

F diversity_theorem(truth, predictions)
   V average = sum(predictions) / predictions.len
   print(‘average-error: ’average_square_diff(truth, predictions)"\n"‘’
         ‘crowd-error:   ’((truth - average) ^ 2)"\n"‘’
         ‘diversity:     ’average_square_diff(average, predictions))

diversity_theorem(49.0, [Float(48), 47, 51])
diversity_theorem(49.0, [Float(48), 47, 51, 42])
Output:
average-error: 3
crowd-error:   0.111111111
diversity:     2.888888889
average-error: 14.5
crowd-error:   4
diversity:     10.5

Ada

Translation of: C
with Ada.Text_IO;
with Ada.Command_Line;

procedure Diversity_Prediction is

   type Real is new Float;
   type Real_Array is array (Positive range <>) of Real;

   package Real_IO is new Ada.Text_Io.Float_IO (Real);
   use Ada.Text_IO, Ada.Command_Line, Real_IO;

   function Mean (Data : Real_Array) return Real is
      Sum : Real := 0.0;
   begin
      for V of Data loop
         Sum := Sum + V;
      end loop;
      return Sum / Real (Data'Length);
   end Mean;

   function Variance (Reference : Real; Data : Real_Array) return Real is
      Res : Real_Array (Data'Range);
   begin
      for A in Data'Range loop
         Res (A) := (Reference - Data (A)) ** 2;
      end loop;
      return Mean (Res);
   end Variance;

   procedure Diversity (Truth : Real; Estimates : Real_Array)
   is
      Average       : constant Real := Mean (Estimates);
      Average_Error : constant Real := Variance (Truth, Estimates);
      Crowd_Error   : constant Real := (Truth - Average) ** 2;
      Diversity     : constant Real := Variance (Average, Estimates);
   begin
      Real_IO.Default_Exp := 0;
      Real_IO.Default_Aft := 5;
      Put ("average-error : "); Put (Average_Error);  New_Line;
      Put ("crowd-error   : "); Put (Crowd_Error);    New_Line;
      Put ("diversity     : "); Put (Diversity);      New_Line;
   end Diversity;

begin
   if Argument_Count <= 1 then
      Put_Line ("Usage: diversity_prediction <truth> <data_1> <data_2> ...");
      return;
   end if;

   declare
      Truth     : constant Real := Real'Value (Argument (1));
      Estimates : Real_Array (2 .. Argument_Count);
   begin
      for A in 2 .. Argument_Count loop
         Estimates (A) := Real'Value (Argument (A));
      end loop;

      Diversity (Truth, Estimates);
   end;
end Diversity_Prediction;
Output:
% ./diversity_prediction 49 48 47 51
average-error :  3.00000
crowd-error   :  0.11111
diversity     :  2.88889
% ./diversity_prediction 49 48 47 51 42
average-error : 14.50000
crowd-error   :  4.00000
diversity     : 10.50000

ALGOL 68

Translation of: Phix
BEGIN # Diversity Prediction Theorem                                         #

    # utility operators                                                      #
    OP   LENGTH = ( []REAL a )INT: ( UPB a - LWB a ) + 1;
    OP   LENGTH = ( STRING a )INT: ( UPB a - LWB a ) + 1;
    OP   SUM    = ( []REAL a )REAL:
         BEGIN
            REAL result := 0;
            FOR i FROM LWB a TO UPB a DO result +:= a[ i ] OD;
            result
         END # SUM # ;
    PRIO PAD    = 9;
    OP   PAD    = ( INT width, STRING v )STRING: # left blank pad v to width #
         IF LENGTH v >= width THEN v ELSE ( " " * ( width - LENGTH v ) ) + v FI;
    OP   - = ( []REAL a, REAL v )[]REAL:        # return a with elements - v #
         BEGIN
            [ LWB a : UPB a ]REAL result;
            FOR i FROM LWB a TO UPB a DO result[ i ] := v - a[ i ] OD;
            result
         END # - # ;
    OP   ^ = ( []REAL a, INT p )[]REAL: # return a with elements raised to p #
         BEGIN
            [ LWB a : UPB a ]REAL result;
            FOR i FROM LWB a TO UPB a DO result[ i ] := a[ i ] ^ p OD;
            result
         END # |^ # ;
    PRIO FMT = 1;    
    OP   FMT = ( REAL v, INT d )STRING:   # formats v with up to d decimals  #
         BEGIN
            STRING result := fixed( v, -0, d );
            IF result[ LWB result ] = "." THEN "0" +=: result FI;
            WHILE result[ UPB result ] = "0" DO result := result[ : UPB result - 1 ] OD;
            IF result[ UPB result ] = "." THEN result := result[ : UPB result - 1 ] FI;
            " " + result
         END # FMT # ; 

    # task                                                                   #

    MODE NAMEDVALUE = STRUCT( STRING name, REAL value );

    PROC mean = ( []REAL s )REAL: SUM s / LENGTH s;
 
    PROC variance = ( []REAL s, REAL d )REAL: mean( ( s - d ) ^ 2 );
 
    PROC diversity theorem = ( REAL reference, []REAL observations )[]NAMEDVALUE:
         BEGIN
            REAL average = mean( observations );
            ( ( "average_error", variance( observations, reference ) )
            , ( "crowd_error",   ( reference - average ) ^ 2         )
            , ( "diversity",     variance( observations, average   ) )
            )
         END # diversity theorem # ;
 
    PROC test = ( REAL reference, []REAL observations )VOID:
         BEGIN
            []NAMEDVALUE res = diversity theorem( reference, observations );
            FOR i FROM LWB res TO UPB res DO
                print( ( 14 PAD name OF res[ i ], " : ", value OF res[ i ] FMT 6, newline ) )
            OD
         END # test # ;

    test( 49, ( 48, 47, 51     ) );
    test( 49, ( 48, 47, 51, 42 ) )

END
Output:
 average_error :  3
   crowd_error :  0.111111
     diversity :  2.888889
 average_error :  14.5
   crowd_error :  4
     diversity :  10.5

BASIC

ANSI BASIC

Translation of: QuickBASIC
Works with: Decimal BASIC
100 PROGRAM DiversityPredictionTheorem
110 OPTION BASE 0
120 DIM Estimates(1, 4)
130 FOR I = 0 TO 1
140    LET J = 0
150    READ Estimates(I, J)
160    DO WHILE Estimates(I, J) <> 0
170       LET J = J + 1
180       READ Estimates(I, J)
190    LOOP
200 NEXT I
210 DATA 48.0, 47.0, 51.0, 0.0
220 DATA 48.0, 47.0, 51.0, 42.0, 0.0
230 LET TrueVal = 49
240 FOR I = 0 TO 1
250    LET Sum = 0
260    LET J = 0
270    DO WHILE Estimates(I, J) <> 0
280       LET Sum = Sum + (Estimates(I, J) - TrueVal) ^ 2
290       LET J = J + 1
300    LOOP
310    LET AvgErr = Sum / J
320    PRINT USING "Average error : ##.###": AvgErr
330    LET Sum = 0
340    LET J = 0
350    DO WHILE Estimates(I, J) <> 0
360       LET Sum = Sum + Estimates(I, J)
370       LET J = J + 1
380    LOOP
390    LET Avg = Sum / J
400    LET CrowdErr = (TrueVal - Avg) ^ 2
410    PRINT USING "Crowd error   : ##.###": CrowdErr
420    PRINT USING "Diversity     : ##.###": AvgErr - CrowdErr
430    PRINT
440 NEXT I
450 END
Output:
Average error :  3.000
Crowd error   :   .111
Diversity     :  2.889

Average error : 14.500
Crowd error   :  4.000
Diversity     : 10.500

BASIC256

Translation of: FreeBASIC
dim test = {{48.0, 47.0, 51.0, 0.0}, {48.0, 47.0, 51.0, 42.0, 0.0}}
TrueVal = 49.0

for i = 0 to 1
	Vari = 0.0
	Sum = 0.0
	c = 0
	while test[i,c] <> 0
		Vari += (test[i,c] - TrueVal) ^2
		Sum += test[i,c]
		c += 1
	end while
	AvgErr = Vari / c
	RefAvg = Sum / c
	CrowdErr = (TrueVal - RefAvg) ^2

	print "Average error : "; AvgErr
	print "  Crowd error : "; CrowdErr
	print "    Diversity : "; AvgErr - CrowdErr
	print
next i

FreeBASIC

Translation of: XPL0
Dim As Double test(0 To 1, 0 To 4) => {_
                {48.0, 47.0, 51.0}, _
                {48.0, 47.0, 51.0, 42.0}}
Dim As Double TrueVal = 49
Dim As Double AvgErr, CrowdErr, RefAvg, Vari, Sum
Dim As Integer i, c

For i = 0 To 1
    Vari = 0
    Sum = 0 
    c = 0
    While test(i,c) <> 0
        Vari += (test(i,c) - TrueVal) ^2
        Sum += test(i,c) 
        c += 1
    Wend
    AvgErr = Vari / c
    RefAvg = Sum / c
    CrowdErr = (TrueVal - RefAvg) ^2
    
    Print Using "Average error : ###.###"; AvgErr
    Print Using "  Crowd error : ###.###"; CrowdErr
    Print Using "    Diversity : ###.###"; AvgErr - CrowdErr
    Print

Sleep
Output:
Average error :   3.000
  Crowd error :   0.111
    Diversity :   2.889

Average error :  14.500
  Crowd error :   4.000
    Diversity :  10.500

Nascom BASIC

Translation of: QuickBASIC
Works with: Nascom ROM BASIC version 4.7
10 REM Diversity prediction theorem
20 DIM EST(1,4):REM Estimates
30 FOR I=0 TO 1
40 J=0:READ EST(I,J)
50 IF EST(I,J)=0 THEN 80
60 J=J+1:READ EST(I,J)
70 GOTO 50
80 NEXT I
90 DATA 48.0,47.0,51.0,0.0
100 DATA 48.0,47.0,51.0,42.0,0.0
110 TV=49:REM True value
120 FOR I=0 TO 1
130 SUM=0:J=0
140 IF EST(I,J)=0 THEN 170
150 SUM=SUM+(EST(I,J)-TV)^2:J=J+1
160 GOTO 140
170 AER=SUM/J
180 PRINT "Average error :";AER
190 SUM=0:J=0
200 IF EST(I,J)=0 THEN 230
210 SUM=SUM+EST(I,J):J=J+1
220 GOTO 200
230 AVG=SUM/J
240 CER=(TV-AVG)^2
250 PRINT "Crowd error   :";CER
260 PRINT "Diversity     :";AER-CER
270 PRINT
280 NEXT I
290 END
Output:
Average error : 3
Crowd error   : .11111
Diversity     : 2.88889

Average error : 14.5
Crowd error   : 4
Diversity     : 10.5

PureBasic

Define.f ref=49.0, mea
NewList argV.f()

Macro put
  Print(~"\n["+StrF(ref)+"]"+#TAB$)
  ForEach argV() : Print(StrF(argV())+#TAB$) : Next  
  PrintN(~"\nAverage Error : "+StrF(vari(argV(),ref),5))
  PrintN("Crowd Error   : "+StrF((ref-mea)*(ref-mea),5))
  PrintN("Diversity     : "+StrF(vari(argV(),mea),5)) 
EndMacro

Macro LetArgV(v)
  AddElement(argV()) : argV()=v
EndMacro

Procedure.f mean(List x.f())
  Define.f m  
  ForEach x() : m+x() : Next  
  ProcedureReturn m/ListSize(x())
EndProcedure

Procedure.f vari(List x.f(),r.f)
  NewList nx.f()  
  ForEach x() : AddElement(nx()) : nx()=(r-x())*(r-x()) : Next  
  ProcedureReturn mean(nx())
EndProcedure

If OpenConsole()=0 : End 1 : EndIf
Gosub SetA : ClearList(argV())
Gosub SetB : Input()
End

SetA:
  LetArgV(48.0) : LetArgV(47.0) : LetArgV(51.0)
  mea=mean(argV()) : put
Return

SetB:
  LetArgV(48.0) : LetArgV(47.0) : LetArgV(51.0) : LetArgV(42.0)
  mea=mean(argV()) : put
Return
Output:
[49]	48	47	51	
Average Error : 3.00000
Crowd Error   : 0.11111
Diversity     : 2.88889

[49]	48	47	51	42	
Average Error : 14.50000
Crowd Error   : 4.00000
Diversity     : 10.50000

QuickBASIC

Translation of: XPL0
REM Diversity prediction theorem
DIM Estimates(1, 4)
FOR I% = 0 TO 1
  J% = 0
  READ Estimates(I%, J%)
  WHILE Estimates(I%, J%) <> 0!
    J% = J% + 1
    READ Estimates(I%, J%)
  WEND
NEXT I%
DATA 48.0, 47.0, 51.0, 0.0
DATA 48.0, 47.0, 51.0, 42.0, 0.0
TrueVal = 49!
FOR I% = 0 TO 1
  Sum = 0!: J% = 0
  WHILE Estimates(I%, J%) <> 0!
    Sum = Sum + (Estimates(I%, J%) - TrueVal) ^ 2: J% = J% + 1
  WEND
  AvgErr = Sum / J%
  PRINT USING "Average error : ##.###"; AvgErr
  Sum = 0!: J% = 0
  WHILE Estimates(I%, J%) <> 0!
    Sum = Sum + Estimates(I%, J%): J% = J% + 1
  WEND
  Avg = Sum / J%
  CrowdErr = (TrueVal - Avg) ^ 2
  PRINT USING "Crowd error   : ##.###"; CrowdErr
  PRINT USING "Diversity     : ##.###"; AvgErr - CrowdErr
  PRINT
NEXT I%
END
Output:
Average error :  3.000
Crowd error   :  0.111
Diversity     :  2.889

Average error : 14.500
Crowd error   :  4.000
Diversity     : 10.500

Visual Basic .NET

Translation of: C#
Module Module1

    Function Square(x As Double) As Double
        Return x * x
    End Function

    Function AverageSquareDiff(a As Double, predictions As IEnumerable(Of Double)) As Double
        Return predictions.Select(Function(x) Square(x - a)).Average()
    End Function

    Sub DiversityTheorem(truth As Double, predictions As IEnumerable(Of Double))
        Dim average = predictions.Average()
        Console.WriteLine("average-error: {0}", AverageSquareDiff(truth, predictions))
        Console.WriteLine("crowd-error: {0}", Square(truth - average))
        Console.WriteLine("diversity: {0}", AverageSquareDiff(average, predictions))
    End Sub

    Sub Main()
        DiversityTheorem(49.0, {48.0, 47.0, 51.0})
        DiversityTheorem(49.0, {48.0, 47.0, 51.0, 42.0})
    End Sub

End Module
Output:
average-error: 3
crowd-error: 0.111111111111113
diversity: 2.88888888888889
average-error: 14.5
crowd-error: 4
diversity: 10.5

C

Accepts inputs from command line, prints out usage on incorrect invocation.

#include<string.h>
#include<stdlib.h>
#include<stdio.h>

float mean(float* arr,int size){
	int i = 0;
	float sum = 0;
	
	while(i != size)
		sum += arr[i++];
	
	return sum/size;
}

float variance(float reference,float* arr, int size){
	int i=0;
	float* newArr = (float*)malloc(size*sizeof(float));
	
	for(;i<size;i++)
		newArr[i] = (reference - arr[i])*(reference - arr[i]);
	
	return mean(newArr,size);
}

float* extractData(char* str, int *len){
	float* arr;
	int i=0,count = 1;
	char* token;
	
	while(str[i]!=00){
		if(str[i++]==',')
			count++;
	}
	
	arr = (float*)malloc(count*sizeof(float));
	*len = count;
	
	token = strtok(str,",");
	
	i = 0;
	
	while(token!=NULL){
		arr[i++] = atof(token);
		token = strtok(NULL,",");
	}
	
	return arr;
}

int main(int argC,char* argV[])
{
	float* arr,reference,meanVal;
	int len;
	if(argC!=3)
		printf("Usage : %s <reference value> <observations separated by commas>");
	else{
		arr = extractData(argV[2],&len);
		
		reference = atof(argV[1]);
		
		meanVal = mean(arr,len);

		printf("Average Error : %.9f\n",variance(reference,arr,len));
		printf("Crowd Error : %.9f\n",(reference - meanVal)*(reference - meanVal));
		printf("Diversity : %.9f",variance(meanVal,arr,len));
	}
	
	return 0;
}

Invocation and Output :

C:\rosettaCode>diversityTheorem.exe 49 48,47,51
Average Error : 3.000000000
Crowd Error : 0.111110263
Diversity : 2.888888597
C:\rosettaCode>diversityTheorem.exe 49 48,47,51,42
Average Error : 14.500000000
Crowd Error : 4.000000000
Diversity : 10.500000000

C#

using System;
using System.Linq;
using System.Collections.Generic;

public class MainClass {
    static double Square(double x) => x * x;

    static double AverageSquareDiff(double a, IEnumerable<double> predictions)
        => predictions.Select(x => Square(x - a)).Average();

    static void DiversityTheorem(double truth, IEnumerable<double> predictions)
    {
        var average = predictions.Average();
        Console.WriteLine($@"average-error: {AverageSquareDiff(truth, predictions)}
crowd-error: {Square(truth - average)}
diversity: {AverageSquareDiff(average, predictions)}");
    }
	
    public static void Main() {
	DiversityTheorem(49, new []{48d,47,51});
    	DiversityTheorem(49, new []{48d,47,51,42});
    }
}
Output:
average-error: 3
crowd-error: 0.11111
diversity: 2.88889
average-error: 14.5
crowd-error: 4
diversity: 10.5

C++

#include <iostream>
#include <vector>
#include <numeric>

float sum(const std::vector<float> &array)
{
    return std::accumulate(array.begin(), array.end(), 0.0);
}

float square(float x)
{
    return x * x;
}

float mean(const std::vector<float> &array)
{
    return sum(array) / array.size();
}

float averageSquareDiff(float a, const std::vector<float> &predictions)
{
    std::vector<float> results;
    for (float x : predictions)
        results.push_back(square(x - a));
    return mean(results);
}

void diversityTheorem(float truth, const std::vector<float> &predictions)
{
    float average = mean(predictions);
    std::cout
        << "average-error: " << averageSquareDiff(truth, predictions) << "\n"
        << "crowd-error: " << square(truth - average) << "\n"
        << "diversity: " << averageSquareDiff(average, predictions) << std::endl;
}

int main() {
    diversityTheorem(49, {48,47,51});
    diversityTheorem(49, {48,47,51,42});
    return 0;
}
Output:
average-error: 3
crowd-error: 0.11111
diversity: 2.88889
average-error: 14.5
crowd-error: 4
diversity: 10.5

Clojure

John Lawrence Aspden's code posted on Diversity Prediction Theorem.

(defn diversity-theorem [truth predictions]
  (let [square (fn[x] (* x x))
        mean (/ (reduce + predictions) (count predictions))
        avg-sq-diff (fn[a] (/ (reduce + (for [x predictions] (square (- x a)))) (count predictions)))]
    {:average-error (avg-sq-diff truth)
     :crowd-error (square (- truth mean))
     :diversity (avg-sq-diff mean)}))

(println (diversity-theorem 49 '(48 47 51)))
(println (diversity-theorem 49 '(48 47 51 42)))
Output:
{:average-error 3, :crowd-error 1/9, :diversity 26/9}
{:average-error 29/2, :crowd-error 4, :diversity 21/2}

Delphi

Works with: Delphi version 6.0

Delphi math libraries make this easier.

function AveSqrDiff(TrueVal: double; Data: array of double): double;
var I: integer;
begin
Result:=0;
for I:=0 to High(Data) do Result:=Result+Sqr(Data[I]-TrueVal);
Result:=Result/Length(Data);
end;

procedure DoDiversityPrediction(Memo: TMemo; TrueValue: double; Crowd: array of double);
var AveError,AvePredict,Diversity: double;
var S: string;
begin
AveError:=AveSqrDiff(Truevalue,Crowd);
AvePredict:=Mean(Crowd);
Diversity:=AveSqrDiff(AvePredict,Crowd);
S:='Ave Error: '+FloatToStrF(AveError,ffFixed,18,2)+#$0D#$0A;
S:=S+'Crowd Error: '+FloatToStrF(Sqr(TrueValue - AvePredict),ffFixed,18,2)+#$0D#$0A;
S:=S+'Diversity: '+FloatToStrF(Diversity,ffFixed,18,2)+#$0D#$0A;
Memo.Lines.Add(S);
end;

procedure ShowDiversityPrediction(Memo: TMemo);
begin
DoDiversityPrediction(Memo,49,[48,47,51]);
DoDiversityPrediction(Memo,49,[48,47,51,42]);
end;
Output:
Ave Error: 3.00
Crowd Error: 0.11
Diversity: 2.89

Ave Error: 14.50
Crowd Error: 4.00
Diversity: 10.50



D

Translation of: C#
import std.algorithm;
import std.stdio;

auto square = (real x) => x * x;

auto meanSquareDiff(R)(real a, R predictions) {
    return predictions.map!(x => square(x - a)).mean;
}

void diversityTheorem(R)(real truth, R predictions) {
    auto average = predictions.mean;
    writeln("average-error: ", meanSquareDiff(truth, predictions));
    writeln("crowd-error: ", square(truth - average));
    writeln("diversity: ", meanSquareDiff(average, predictions));
    writeln;
}

void main() {
    diversityTheorem(49.0, [48.0, 47.0, 51.0]);
    diversityTheorem(49.0, [48.0, 47.0, 51.0, 42.0]);
}
Output:
average-error: 3
crowd-error: 0.111111
diversity: 2.88889

average-error: 14.5
crowd-error: 4
diversity: 10.5

EasyLang

Translation of: BASIC256
proc calc TrueVal test[] . .
   for test in test[]
      h = (test - TrueVal)
      Vari += h * h
      Sum += test
      c += 1
   .
   AvgErr = Vari / c
   RefAvg = Sum / c
   h = (TrueVal - RefAvg)
   CrowdErr = h * h
   print "Average error : " & AvgErr
   print "  Crowd error : " & CrowdErr
   print "    Diversity : " & AvgErr - CrowdErr
   print ""
.
calc 49 [ 48 47 51 ]
calc 49 [ 48 47 51 42 ]

Factor

Works with: Factor version 0.99 2020-01-23
USING: kernel math math.statistics math.vectors prettyprint ;

TUPLE: div avg-err crowd-err diversity ;

: diversity ( x seq -- obj )
    [ n-v dup v* mean ] [ mean swap - sq ]
    [ nip dup mean v-n dup v* mean ] 2tri div boa ;

49 { 48 47 51 } diversity .
49 { 48 47 51 42 } diversity .
Output:
T{ div { avg-err 3 } { crowd-err 1/9 } { diversity 2+8/9 } }
T{ div { avg-err 14+1/2 } { crowd-err 4 } { diversity 10+1/2 } }

Fōrmulæ

Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.

Programs in Fōrmulæ are created/edited online in its website.

In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.

Solution

Test case 1. A true value of 49 with crowd estimates of 48, 47 and 51

Test case 2. A true value of 49 with crowd estimates of 48, 47, 51 and 42

Go

package main

import "fmt"

func averageSquareDiff(f float64, preds []float64) (av float64) {
    for _, pred := range preds {
        av += (pred - f) * (pred - f)
    }
    av /= float64(len(preds))
    return
}

func diversityTheorem(truth float64, preds []float64) (float64, float64, float64) {
    av := 0.0
    for _, pred := range preds {
        av += pred
    }
    av /= float64(len(preds))
    avErr := averageSquareDiff(truth, preds)
    crowdErr := (truth - av) * (truth - av)
    div := averageSquareDiff(av, preds)
    return avErr, crowdErr, div
}

func main() {
    predsArray := [2][]float64{{48, 47, 51}, {48, 47, 51, 42}}
    truth := 49.0
    for _, preds := range predsArray {
        avErr, crowdErr, div := diversityTheorem(truth, preds)
        fmt.Printf("Average-error : %6.3f\n", avErr)
        fmt.Printf("Crowd-error   : %6.3f\n", crowdErr)
        fmt.Printf("Diversity     : %6.3f\n\n", div)
    }
}
Output:
Average-error :  3.000
Crowd-error   :  0.111
Diversity     :  2.889

Average-error : 14.500
Crowd-error   :  4.000
Diversity     : 10.500

Groovy

Translation of: Java
class DiversityPredictionTheorem {
    private static double square(double d) {
        return d * d
    }

    private static double averageSquareDiff(double d, double[] predictions) {
        return Arrays.stream(predictions)
                .map({ it -> square(it - d) })
                .average()
                .orElseThrow()
    }

    private static String diversityTheorem(double truth, double[] predictions) {
        double average = Arrays.stream(predictions)
                .average()
                .orElseThrow()
        return String.format("average-error : %6.3f%n", averageSquareDiff(truth, predictions)) + String.format("crowd-error   : %6.3f%n", square(truth - average)) + String.format("diversity     : %6.3f%n", averageSquareDiff(average, predictions))
    }

    static void main(String[] args) {
        println(diversityTheorem(49.0, [48.0, 47.0, 51.0] as double[]))
        println(diversityTheorem(49.0, [48.0, 47.0, 51.0, 42.0] as double[]))
    }
}
Output:
average-error :  3.000
crowd-error   :  0.111
diversity     :  2.889

average-error : 14.500
crowd-error   :  4.000
diversity     : 10.500

Haskell

mean :: (Fractional a, Foldable t) => t a -> a
mean lst = sum lst / fromIntegral (length lst)

meanSq :: Fractional c => c -> [c] -> c
meanSq x = mean . map (\y -> (x-y)^^2)

diversityPrediction x estimates = do
   putStrLn $ "TrueValue:\t" ++ show x
   putStrLn $ "CrowdEstimates:\t" ++ show estimates
   let avg = mean estimates
   let avgerr = meanSq x estimates
   putStrLn $ "AverageError:\t" ++ show avgerr
   let crowderr = (x - avg)^^2
   putStrLn $ "CrowdError:\t" ++ show crowderr
   let diversity = meanSq avg estimates
   putStrLn $ "Diversity:\t" ++ show diversity
λ> diversityPrediction 49 [48,47,51]
TrueValue:	49.0
CrowdEstimates:	[48.0,47.0,51.0]
AverageError:	3.0
CrowdError:	0.11111111111111269
Diversity:	2.888888888888889

λ> diversityPrediction 49 [48,47,51,42]
TrueValue:	49.0
CrowdEstimates:	[48.0,47.0,51.0,42.0]
AverageError:	14.5
CrowdError:	4.0
Diversity:	10.5

J

Accepts inputs from command line, prints out usage on incorrect invocation. Were this compressed adaptation from C the content of file d.ijs

echo 'Use: ' , (;:inv 2 {. ARGV) , ' <reference value>  <observations>'

data=: ([: ". [: ;:inv 2&}.) ::([: exit 1:) ARGV

([: exit (1: echo@('insufficient data'"_)))^:(2 > #) data

mean=: +/ % #
variance=: [: mean [: *: -

averageError=: ({. variance }.)@:]
crowdError=:  variance {.
diversity=:  variance }.

echo (<;._2'average error;crowd error;diversity;') ,: ;/ (averageError`crowdError`diversity`:0~ mean@:}.) data

exit 0

example uses follow

$ ijconsole d.ijs bad data
Use: ijconsole d.ijs <reference value>  <observations>
insufficient data
$ ijconsole d.ijs 1
Use: ijconsole d.ijs <reference value>  <observations>
insufficient data
$ ijconsole d.ijs 1 2
Use: ijconsole d.ijs <reference value>  <observations>
┌─────────────┬───────────┬─────────┐
│average error│crowd error│diversity│
├─────────────┼───────────┼─────────┤
│1            │1          │0        │
└─────────────┴───────────┴─────────┘
$ ijconsole d.ijs a 3
Use: ijconsole d.ijs <reference value>  <observations>
$ ijconsole d.ijs 49 48,47,51,42
Use: ijconsole d.ijs <reference value>  <observations>
┌─────────────┬───────────┬─────────┐
│average error│crowd error│diversity│
├─────────────┼───────────┼─────────┤
│14.5         │4          │10.5     │
└─────────────┴───────────┴─────────┘
$ ijconsole d.ijs 49 48,47,51
Use: ijconsole d.ijs <reference value>  <observations>
┌─────────────┬───────────┬─────────┐
│average error│crowd error│diversity│
├─────────────┼───────────┼─────────┤
│3            │0.111111   │2.88889  │
└─────────────┴───────────┴─────────┘
$ ijconsole d.ijs 49 48 47 51         # commas don't interfere
Use: ijconsole d.ijs <reference value>  <observations>
┌─────────────┬───────────┬─────────┐
│average error│crowd error│diversity│
├─────────────┼───────────┼─────────┤
│3            │0.111111   │2.88889  │
└─────────────┴───────────┴─────────┘

Java

Translation of: Kotlin
import java.util.Arrays;

public class DiversityPredictionTheorem {
    private static double square(double d) {
        return d * d;
    }

    private static double averageSquareDiff(double d, double[] predictions) {
        return Arrays.stream(predictions)
            .map(it -> square(it - d))
            .average()
            .orElseThrow();
    }

    private static String diversityTheorem(double truth, double[] predictions) {
        double average = Arrays.stream(predictions)
            .average()
            .orElseThrow();
        return String.format("average-error : %6.3f%n", averageSquareDiff(truth, predictions))
            + String.format("crowd-error   : %6.3f%n", square(truth - average))
            + String.format("diversity     : %6.3f%n", averageSquareDiff(average, predictions));
    }

    public static void main(String[] args) {
        System.out.println(diversityTheorem(49.0, new double[]{48.0, 47.0, 51.0}));
        System.out.println(diversityTheorem(49.0, new double[]{48.0, 47.0, 51.0, 42.0}));
    }
}
Output:
average-error :  3.000
crowd-error   :  0.111
diversity     :  2.889

average-error : 14.500
crowd-error   :  4.000
diversity     : 10.500

JavaScript

ES5

'use strict';

function sum(array) {
    return array.reduce(function (a, b) {
        return a + b;
    });
}

function square(x) {
    return x * x;
}

function mean(array) {
    return sum(array) / array.length;
}

function averageSquareDiff(a, predictions) {
    return mean(predictions.map(function (x) {
        return square(x - a);
    }));
}

function diversityTheorem(truth, predictions) {
    var average = mean(predictions);
    return {
        'average-error': averageSquareDiff(truth, predictions),
        'crowd-error': square(truth - average),
        'diversity': averageSquareDiff(average, predictions)
    };
}

console.log(diversityTheorem(49, [48,47,51]))
console.log(diversityTheorem(49, [48,47,51,42]))
Output:
{ 'average-error': 3,
  'crowd-error': 0.11111111111111269,
  diversity: 2.888888888888889 }
{ 'average-error': 14.5, 'crowd-error': 4, diversity: 10.5 }

ES6

(() => {
    'use strict';

    // diversityValues :: [Num] -> {
    //      mean-error ::  Float, 
    //     crowd-error :: Float, 
    //       diversity :: Float
    // }
    const diversityValues = observed =>
        predictions => {
            const predictionMean = mean(predictions);
            return {
                'mean-error': meanErrorSquared(observed)(
                    predictions
                ),
                'crowd-error': Math.pow(
                    observed - predictionMean,
                    2
                ),
                'diversity': meanErrorSquared(predictionMean)(
                    predictions
                )
            };
        };

    // meanErrorSquared :: Num a => a -> [a] -> b
    const meanErrorSquared = observed =>
        predictions => mean(
            predictions.map(x => Math.pow(x - observed, 2))
        );

    // mean :: Num a => [a] -> b
    const mean = xs => {
        const lng = xs.length;
        return lng > 0 ? (
            xs.reduce((a, b) => a + b, 0) / lng
        ) : undefined;
    };


    // ----------------------- TEST ------------------------
    const main = () =>
        JSON.stringify([{
            observed: 49,
            predictions: [48, 47, 51]
        }, {
            observed: 49,
            predictions: [48, 47, 51, 42]
        }].map(x => dictionaryAtPrecision(3)(
            diversityValues(x.observed)(
                x.predictions
            )
        )), null, 2);


    // ---------------------- GENERIC ----------------------

    // dictionaryAtPrecision :: Int -> Dict -> Dict
    const dictionaryAtPrecision = n =>
        // A dictionary of Float values, with 
        // all Floats adjusted to a given precision.
        dct => Object.keys(dct).reduce(
            (a, k) => Object.assign(
                a, {
                    [k]: dct[k].toPrecision(n)
                }
            ), {}
        );

    // MAIN ---
    return main()
})();
Output:
[
  {
    "mean-error": "3.00",
    "crowd-error": "0.111",
    "diversity": "2.89"
  },
  {
    "mean-error": "14.5",
    "crowd-error": "4.00",
    "diversity": "10.5"
  }
]

Jsish

From Typescript entry.

/* Diverisity Prediction Theorem, in Jsish */
"use strict";

function sum(arr:array):number {
    return arr.reduce(function(acc, cur, idx, arr) { return acc + cur; });
}
 
function square(x:number):number {
    return x * x;
}
 
function mean(arr:array):number {
    return sum(arr) / arr.length;
}

function averageSquareDiff(a:number, predictions:array):number {
    return mean(predictions.map(function(x:number):number { return square(x - a); }));
}

function diversityTheorem(truth:number, predictions:array):object {
    var average = mean(predictions);
    return {
        "average-error": averageSquareDiff(truth, predictions),
        "crowd-error": square(truth - average),
        "diversity": averageSquareDiff(average, predictions)
    };
}

;diversityTheorem(49, [48,47,51]);
;diversityTheorem(49, [48,47,51,42]);

/*
=!EXPECTSTART!=
diversityTheorem(49, [48,47,51]) ==> { "average-error":3, "crowd-error":0.1111111111111127, diversity:2.888888888888889 }
diversityTheorem(49, [48,47,51,42]) ==> { "average-error":14.5, "crowd-error":4, diversity:10.5 }
=!EXPECTEND!=
*/
Output:
prompt$ jsish -u diversityPrediction.jsi
[PASS] diversityPrediction.jsi

jq

Works with: jq

Works with gojq, the Go implementation of jq

def diversitytheorem($actual; $predicted):
  def mean: add/length;

  ($predicted | mean) as $mean
  | { avgerr: ($predicted | map(. - $actual) | map(pow(.; 2)) | mean),
      crderr: pow($mean - $actual; 2),
      divers: ($predicted | map(. - $mean) | map(pow(.;2)) | mean) } ;
# The task:
([49, [48, 47, 51]],
[49, [48, 47, 51, 42]
])
| . as [$actual, $predicted]
| diversitytheorem($actual; $predicted)
Output:
{
  "avgerr": 3,
  "crderr": 0.11111111111111269,
  "divers": 2.888888888888889
}
{
  "avgerr": 14.5,
  "crderr": 4,
  "divers": 10.5
}

Julia

Works with: Julia version 1.2
import Statistics: mean

function diversitytheorem(truth::T, pred::Vector{T}) where T<:Number
    μ = mean(pred)
    avgerr = mean((pred .- truth) .^ 2)
    crderr = (μ - truth) ^ 2
    divers = mean((pred .- μ) .^ 2)
    avgerr, crderr, divers
end

for (t, s) in [(49, [48, 47, 51]),
               (49, [48, 47, 51, 42])]
    avgerr, crderr, divers = diversitytheorem(t, s)
    println("""
    average-error : $avgerr
    crowd-error   : $crderr
    diversity     : $divers
    """)
end
Output:
average-error : 3.0
crowd-error   : 0.11111111111111269
diversity     : 2.888888888888889

average-error : 14.5
crowd-error   : 4.0
diversity     : 10.5

Kotlin

Translation of: TypeScript
// version 1.1.4-3

fun square(d: Double) = d * d

fun averageSquareDiff(d: Double, predictions: DoubleArray) = 
    predictions.map { square(it - d) }.average()

fun diversityTheorem(truth: Double, predictions: DoubleArray): String {
    val average = predictions.average()
    val f = "%6.3f"
    return "average-error : ${f.format(averageSquareDiff(truth, predictions))}\n" +
           "crowd-error   : ${f.format(square(truth - average))}\n" +
           "diversity     : ${f.format(averageSquareDiff(average, predictions))}\n"
}

fun main(args: Array<String>) {
    println(diversityTheorem(49.0, doubleArrayOf(48.0, 47.0, 51.0)))
    println(diversityTheorem(49.0, doubleArrayOf(48.0, 47.0, 51.0, 42.0)))
}
Output:
average-error :  3.000
crowd-error   :  0.111
diversity     :  2.889

average-error : 14.500
crowd-error   :  4.000
diversity     : 10.500

Lua

Translation of: C++
function square(x)
    return x * x
end

function mean(a)
    local s = 0
    local c = 0
    for i,v in pairs(a) do
        s = s + v
        c = c + 1
    end
    return s / c
end

function averageSquareDiff(a, predictions)
    local results = {}
    for i,x in pairs(predictions) do
        table.insert(results, square(x - a))
    end
    return mean(results)
end

function diversityTheorem(truth, predictions)
    local average = mean(predictions)
    print("average-error: " .. averageSquareDiff(truth, predictions))
    print("crowd-error: " .. square(truth - average))
    print("diversity: " .. averageSquareDiff(average, predictions))
end

function main()
    diversityTheorem(49, {48, 47, 51})
    diversityTheorem(49, {48, 47, 51, 42})
end

main()
Output:
average-error: 3
crowd-error: 0.11111111111111
diversity: 2.8888888888889
average-error: 14.5
crowd-error: 4
diversity: 10.5

Mathematica/Wolfram Language

ClearAll[DiversityPredictionTheorem]
DiversityPredictionTheorem[trueval_?NumericQ, estimates_List] := 
 Module[{avg, avgerr, crowderr, diversity},
  avg = Mean[estimates];
  avgerr = Mean[(estimates - trueval)^2];
  crowderr = (trueval - avg)^2;
  diversity = Mean[(estimates - avg)^2];
  <|
   "TrueValue" -> trueval,
   "CrowdEstimates" -> estimates,
   "AverageError" -> avgerr,
   "CrowdError" -> crowderr,
   "Diversity" -> diversity
   |>
  ]
DiversityPredictionTheorem[49, {48, 47, 51}] // Dataset
DiversityPredictionTheorem[49, {48, 47, 51, 42}] // Dataset
Output:
TrueValue	49
CrowdEstimates	{48,47,51}
AverageError	3
CrowdError	1/9
Diversity	26/9

TrueValue	49
CrowdEstimates	{48,47,51,42}
AverageError	29/2
CrowdError	4
Diversity	21/2

Nim

import strutils, math, stats

func meanSquareDiff(refValue: float; estimates: seq[float]): float =
  ## Compute the mean of the squares of the differences
  ## between estimated values and a reference value.
  for estimate in estimates:
    result += (estimate - refValue)^2
  result /= estimates.len.toFloat


const Samples = [(trueValue: 49.0, estimates: @[48.0, 47.0, 51.0]),
                 (trueValue: 49.0, estimates: @[48.0, 47.0, 51.0, 42.0])]

for (trueValue, estimates, ) in Samples:
  let m = mean(estimates)
  echo "True value:           ", trueValue
  echo "Estimates:            ", estimates.join(", ")
  echo "Average error:        ", meanSquareDiff(trueValue, estimates)
  echo "Crowd error:          ", (m - trueValue)^2
  echo "Prediction diversity: ", meanSquareDiff(m, estimates)
  echo ""
Output:
True value:           49.0
Estimates:            48.0, 47.0, 51.0
Average error:        3.0
Crowd error:          0.1111111111111127
Prediction diversity: 2.888888888888889

True value:           49.0
Estimates:            48.0, 47.0, 51.0, 42.0
Average error:        14.5
Crowd error:          4.0
Prediction diversity: 10.5

Perl

sub diversity {
    my($truth, @pred) = @_;
    my($ae,$ce,$cp,$pd,$stats);

    $cp += $_/@pred for @pred;      # collective prediction
    $ae = avg_error($truth, @pred); # average individual error
    $ce = ($cp - $truth)**2;        # collective error
    $pd = avg_error($cp, @pred);    # prediction diversity

    my $fmt = "%13s: %6.3f\n";
    $stats  = sprintf $fmt, 'average-error', $ae;
    $stats .= sprintf $fmt, 'crowd-error',   $ce;
    $stats .= sprintf $fmt, 'diversity',     $pd;
}

sub avg_error {
    my($m, @v) = @_;
    my($avg_err);
    $avg_err += ($_ - $m)**2 for @v;
    $avg_err/@v;
}

print diversity(49, qw<48 47 51>) . "\n";
print diversity(49, qw<48 47 51 42>);
Output:
average-error:  3.000
  crowd-error:  0.111
    diversity:  2.889

average-error: 14.500
  crowd-error:  4.000
    diversity: 10.500

Phix

with javascript_semantics
function mean(sequence s)
    return sum(s)/length(s)
end function
 
function variance(sequence s, atom d)
    return mean(sq_power(sq_sub(s,d),2))
end function
 
function diversity_theorem(atom reference, sequence observations)
    atom average_error = variance(observations,reference),
         average = mean(observations),
         crowd_error = power(reference-average,2),
         diversity = variance(observations,average)
    return {{"average_error",average_error},
            {"crowd_error",crowd_error},
            {"diversity",diversity}}
end function
 
procedure test(atom reference, sequence observations)
    sequence res = diversity_theorem(reference, observations)
    for i=1 to length(res) do
        printf(1," %14s : %g\n",res[i])
    end for
end procedure
test(49, {48, 47, 51})
test(49, {48, 47, 51, 42})
Output:
  average_error : 3
    crowd_error : 0.111111
      diversity : 2.88889
  average_error : 14.5
    crowd_error : 4
      diversity : 10.5

Python

By composition of pure functions:

Works with: Python version 3.7
'''Diversity prediction theorem'''

from itertools import chain
from functools import reduce


#  diversityValues :: Num a => a -> [a] ->
#  { mean-Error :: a, crowd-error :: a, diversity :: a }
def diversityValues(x):
    '''The mean error, crowd error and
       diversity, for a given observation x
       and a non-empty list of predictions ps.
    '''
    def go(ps):
        mp = mean(ps)
        return {
            'mean-error': meanErrorSquared(x)(ps),
            'crowd-error': pow(x - mp, 2),
            'diversity': meanErrorSquared(mp)(ps)
        }
    return go


# meanErrorSquared :: Num -> [Num] -> Num
def meanErrorSquared(x):
    '''The mean of the squared differences
       between the observed value x and
       a non-empty list of predictions ps.
    '''
    def go(ps):
        return mean([
            pow(p - x, 2) for p in ps
        ])
    return go


# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''Observed value: 49,
       prediction lists: various.
    '''

    print(unlines(map(
        showDiversityValues(49),
        [
            [48, 47, 51],
            [48, 47, 51, 42],
            [50, '?', 50, {}, 50],  # Non-numeric values.
            []                      # Missing predictions.
        ]
    )))
    print(unlines(map(
        showDiversityValues('49'),  # String in place of number.
        [
            [50, 50, 50],
            [40, 35, 40],
        ]
    )))


# ---------------------- FORMATTING ----------------------

# showDiversityValues :: Num -> [Num] -> Either String String
def showDiversityValues(x):
    '''Formatted string representation
       of diversity values for a given
       observation x and a non-empty
       list of predictions p.
    '''
    def go(ps):
        def showDict(dct):
            w = 4 + max(map(len, dct.keys()))

            def showKV(a, kv):
                k, v = kv
                return a + k.rjust(w, ' ') + (
                    ' : ' + showPrecision(3)(v) + '\n'
                )
            return 'Predictions: ' + showList(ps) + ' ->\n' + (
                reduce(showKV, dct.items(), '')
            )

        def showProblem(e):
            return (
                unlines(map(indented(1), e)) if (
                    isinstance(e, list)
                ) else indented(1)(repr(e))
            ) + '\n'

        return 'Observation:  ' + repr(x) + '\n' + (
            either(showProblem)(showDict)(
                bindLR(numLR(x))(
                    lambda n: bindLR(numsLR(ps))(
                        compose(Right, diversityValues(n))
                    )
                )
            )
        )
    return go


# ------------------ GENERIC FUNCTIONS -------------------

# Left :: a -> Either a b
def Left(x):
    '''Constructor for an empty Either (option type) value
       with an associated string.
    '''
    return {'type': 'Either', 'Right': None, 'Left': x}


# Right :: b -> Either a b
def Right(x):
    '''Constructor for a populated Either (option type) value'''
    return {'type': 'Either', 'Left': None, 'Right': x}


# bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
def bindLR(m):
    '''Either monad injection operator.
       Two computations sequentially composed,
       with any value produced by the first
       passed as an argument to the second.
    '''
    def go(mf):
        return (
            mf(m.get('Right')) if None is m.get('Left') else m
        )
    return go


# compose :: ((a -> a), ...) -> (a -> a)
def compose(*fs):
    '''Composition, from right to left,
       of a series of functions.
    '''
    def go(f, g):
        def fg(x):
            return f(g(x))
        return fg
    return reduce(go, fs, identity)


# concatMap :: (a -> [b]) -> [a] -> [b]
def concatMap(f):
    '''A concatenated list over which a function has been mapped.
       The list monad can be derived by using a function f which
       wraps its output in a list,
       (using an empty list to represent computational failure).
    '''
    def go(xs):
        return chain.from_iterable(map(f, xs))
    return go


# either :: (a -> c) -> (b -> c) -> Either a b -> c
def either(fl):
    '''The application of fl to e if e is a Left value,
       or the application of fr to e if e is a Right value.
    '''
    return lambda fr: lambda e: fl(e['Left']) if (
        None is e['Right']
    ) else fr(e['Right'])


# identity :: a -> a
def identity(x):
    '''The identity function.'''
    return x


# indented :: Int -> String -> String
def indented(n):
    '''String indented by n multiples
       of four spaces.
    '''
    return lambda s: (4 * ' ' * n) + s

# mean :: [Num] -> Float
def mean(xs):
    '''Arithmetic mean of a list
       of numeric values.
    '''
    return sum(xs) / float(len(xs))


# numLR :: a -> Either String Num
def numLR(x):
    '''Either Right x if x is a float or int,
       or a Left explanatory message.'''
    return Right(x) if (
        isinstance(x, (float, int))
    ) else Left(
        'Expected number, saw: ' + (
            str(type(x)) + ' ' + repr(x)
        )
    )


# numsLR :: [a] -> Either String [Num]
def numsLR(xs):
    '''Either Right xs if all xs are float or int,
       or a Left explanatory message.'''
    def go(ns):
        ls, rs = partitionEithers(map(numLR, ns))
        return Left(ls) if ls else Right(rs)
    return bindLR(
        Right(xs) if (
            bool(xs) and isinstance(xs, list)
        ) else Left(
            'Expected a non-empty list, saw: ' + (
                str(type(xs)) + ' ' + repr(xs)
            )
        )
    )(go)


# partitionEithers :: [Either a b] -> ([a],[b])
def partitionEithers(lrs):
    '''A list of Either values partitioned into a tuple
       of two lists, with all Left elements extracted
       into the first list, and Right elements
       extracted into the second list.
    '''
    def go(a, x):
        ls, rs = a
        r = x.get('Right')
        return (ls + [x.get('Left')], rs) if None is r else (
            ls, rs + [r]
        )
    return reduce(go, lrs, ([], []))


# showList :: [a] -> String
def showList(xs):
    '''Compact string representation of a list'''
    return '[' + ','.join(str(x) for x in xs) + ']'


# showPrecision :: Int -> Float -> String
def showPrecision(n):
    '''A string showing a floating point number
       at a given degree of precision.'''
    def go(x):
        return str(round(x, n))
    return go


# unlines :: [String] -> String
def unlines(xs):
    '''A single string derived by the intercalation
       of a list of strings with the newline character.'''
    return '\n'.join(xs)


# MAIN ---
if __name__ == '__main__':
    main()
Output:
Observation:  49
Predictions: [48,47,51] ->
     mean-error : 3.0
    crowd-error : 0.111
      diversity : 2.889

Observation:  49
Predictions: [48,47,51,42] ->
     mean-error : 14.5
    crowd-error : 4.0
      diversity : 10.5

Observation:  49
    Expected number, saw: <class 'str'> '?'
    Expected number, saw: <class 'dict'> {}

Observation:  49
    "Expected a non-empty list, saw: <class 'list'> []"

Observation:  '49'
    "Expected number, saw: <class 'str'> '49'"

Observation:  '49'
    "Expected number, saw: <class 'str'> '49'"

R

R's vectorisation shines here. The hardest part of this task was giving each estimate its own numbered column, which is little more than a printing luxury. The actual mathematics was trivial, with each part done in essentially one line.

diversityStats <- function(trueValue, estimates)
{
  collectivePrediction <- mean(estimates)
  data.frame("True Value" = trueValue,
             as.list(setNames(estimates, paste("Guess", seq_along(estimates)))), #Guesses, each with a title and column.
             "Average Error" = mean((trueValue - estimates)^2),
             "Crowd Error" = (trueValue - collectivePrediction)^2,
             "Prediction Diversity" = mean((estimates - collectivePrediction)^2))
}
diversityStats(49, c(48, 47, 51))
diversityStats(49, c(48, 47, 51, 42))
Output:
> diversityStats(49, c(48, 47, 51))
  True.Value Guess.1 Guess.2 Guess.3 Average.Error Crowd.Error Prediction.Diversity
1         49      48      47      51             3   0.1111111             2.888889

> diversityStats(49, c(48, 47, 51, 42))
  True.Value Guess.1 Guess.2 Guess.3 Guess.4 Average.Error Crowd.Error Prediction.Diversity
1         49      48      47      51      42          14.5           4                 10.5

Racket

Translation of: Clojure
#lang racket

(define (mean l)
  (/ (apply + l) (length l)))

(define (diversity-theorem truth predictions)
  (define μ (mean predictions))
  (define (avg-sq-diff a)
    (mean (map (λ (p) (sqr (- p a))) predictions)))
  (hash 'average-error (avg-sq-diff truth)
        'crowd-error (sqr (- truth μ))
        'diversity (avg-sq-diff μ)))
 
(println (diversity-theorem 49 '(48 47 51)))
(println (diversity-theorem 49 '(48 47 51 42)))
Output:
'#hash((average-error . 3) (crowd-error . 1/9) (diversity . 2 8/9))
'#hash((average-error . 14 1/2) (crowd-error . 4) (diversity . 10 1/2))

Raku

(formerly Perl 6)

sub diversity-calc($truth, @pred) {
    my $ae = avg-error($truth, @pred); # average individual error
    my $cp = ([+] @pred)/+@pred;       # collective prediction
    my $ce = ($cp - $truth)**2;        # collective error
    my $pd = avg-error($cp, @pred);    # prediction diversity
    return $ae, $ce, $pd;
}

sub avg-error ($m, @v) { ([+] (@v X- $m) X**2) / +@v }

sub diversity-format (@stats) {
    gather {
        for <average-error crowd-error diversity> Z @stats -> ($label,$value) {
            take $label.fmt("%13s") ~ ':' ~ $value.fmt("%7.3f");
        }
    }
}

.say for diversity-format diversity-calc(49, <48 47 51>);
.say for diversity-format diversity-calc(49, <48 47 51 42>);
Output:
average-error:  3.000
  crowd-error:  0.111
    diversity:  2.889
average-error: 14.500
  crowd-error:  4.000
    diversity: 10.500

REXX

version 1

/* REXX */
Numeric Digits 20
Call diversityTheorem 49,'48 47 51'
Say '--------------------------------------'
Call diversityTheorem 49,'48 47 51 42'
Exit

diversityTheorem:
  Parse Arg truth,list
  average=average(list)
  Say 'average-error='averageSquareDiff(truth,list)
  Say 'crowd-error='||(truth-average)**2
  Say 'diversity='averageSquareDiff(average,list)
  Return

average: Procedure
  Parse Arg list
  res=0
  Do i=1 To words(list)
    res=res+word(list,i)  /* accumulate list elements */
    End
  Return res/words(list)  /* return the average */

averageSquareDiff: Procedure
  Parse Arg a,list
  res=0
  Do i=1 To words(list)
    x=word(list,i)
    res=res+(x-a)**2      /* accumulate square of differences */
    End
  Return res/words(list)  /* return the average */
Output:
average-error=3
crowd-error=0.11111111111111111089
diversity=2.8888888888888888889
--------------------------------------
average-error=14.5
crowd-error=4
diversity=10.5

version 2

Uses greater precision, but rounds the output to six decimal digits past the decimal point   (see the last comment in the program).

/*REXX program calculates the  average error,  crowd error,  and  prediction diversity. */
                               numeric digits 50 /*use precision of fifty decimal digits*/
call diversity 49,   48  47  51                  /*true value and the crowd predictions.*/
call diversity 49,   48  47  51  42              /*  "    "    "   "    "        "      */
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
avg:   $= 0;           do j=1  for #;  $= $ +  word(x, j)        ;   end;     return $ / #
avgSD: $= 0;  arg y;   do j=1  for #;  $= $ + (word(x, j) - y)**2;   end;     return $ / #
/*──────────────────────────────────────────────────────────────────────────────────────*/
diversity: parse arg true, x;    #= words(x);     a= avg()   /*get args; count #est; avg*/
           say '   the  true   value: '   true  copies("═", 20)  "crowd estimates: "   x
           say '   the average error: '   format( avgSD(true) , , 6) / 1
           say '   the  crowd  error: '   format( (true-a) **2, , 6) / 1
           say 'prediction diversity: '   format( avgSD(a)    , , 6) / 1;        say;  say
           return                                            /*   └─── show 6 dec. digs.*/
output   when using the default inputs:
   the  true   value:  49 ════════════════════ crowd estimates:  48 47 51
   the average error:  3
   the  crowd  error:  0.111111
prediction diversity:  2.888889


   the  true   value:  49 ════════════════════ crowd estimates:  48 47 51 42
   the average error:  14.5
   the  crowd  error:  4
prediction diversity:  10.5

RPL

Works with: HP version 48G
RPL code Comment
« → pivot 
  « 1 « pivot - SQ » DOLIST 
    ∑LIST LASTARG SIZE /
» » 'SQDIF' STO
 
« → preds truth 
  « preds truth SQDIF "avg_err" →TAG
    preds ∑LIST LASTARG SIZE /
    DUP truth - SQ "cwd_err" →TAG
    preds ROT SQDIF "pred_div" →TAG
    3 →LIST
» » 'CROWD' STO
SQDIF ( { values } pivot → average((value-pivot)²) )
get (value-pivot)²
get average


CROWD ( { preds } truth → { report } )
avg_err = mean((pred-truth)²)
average = ∑preds / number of preds
cwd_err = (average-truth)²
prd_div = mean((pred-cwd_err)²)
put them all into a list
 
{ 48 47 51 } 49 CROWD
{ 48 47 51 42 } 49 CROWD
Output:
2: { avg_err:3 cwd_err:0.111111111111 pred_div:2.88888888889 }
1: { avg_err:14.5 cwd_err:4 pred_div:10.5 }

Ruby

Translation of: D
def mean(a) = a.sum(0.0) / a.size
def mean_square_diff(a, predictions) = mean(predictions.map { |x| square(x - a)**2 })
 
def diversity_theorem(truth, predictions)
    average = mean(predictions)
    puts "truth: #{truth}, predictions #{predictions}",
         "average-error: #{mean_square_diff(truth, predictions)}",
         "crowd-error: #{(truth - average)**2}",
         "diversity: #{mean_square_diff(average, predictions)}",""
end
 
diversity_theorem(49.0, [48.0, 47.0, 51.0])
diversity_theorem(49.0, [48.0, 47.0, 51.0, 42.0])
Output:
truth: 49.0, predictions [48.0, 47.0, 51.0]
average-error: 3.0
crowd-error: 0.11111111111111269
diversity: 2.888888888888889

truth: 49.0, predictions [48.0, 47.0, 51.0, 42.0]
average-error: 14.5
crowd-error: 4.0
diversity: 10.5

Scala

Translation of: Kotlin
object DiversityPredictionTheorem {
  def square(d: Double): Double
  = d * d

  def average(a: Array[Double]): Double
  = a.sum / a.length

  def averageSquareDiff(d: Double, predictions: Array[Double]): Double
  = average(predictions.map(it => square(it - d)))

  def diversityTheorem(truth: Double, predictions: Array[Double]): String = {
    val avg = average(predictions)
    f"average-error : ${averageSquareDiff(truth, predictions)}%6.3f\n" +
    f"crowd-error   : ${square(truth - avg)}%6.3f\n"+
    f"diversity     : ${averageSquareDiff(avg, predictions)}%6.3f\n"
  }

  def main(args: Array[String]): Unit = {
    println(diversityTheorem(49.0, Array(48.0, 47.0, 51.0)))
    println(diversityTheorem(49.0, Array(48.0, 47.0, 51.0, 42.0)))
  }
}
Output:
average-error :  3.000
crowd-error   :  0.111
diversity     :  2.889

average-error : 14.500
crowd-error   :  4.000
diversity     : 10.500

Sidef

Translation of: Raku
func avg_error(m, v) {
    v.map { (_ - m)**2 }.sum / v.len
}

func diversity_calc(truth, pred) {
    var ae = avg_error(truth, pred)
    var cp = pred.sum/pred.len
    var ce = (cp - truth)**2
    var pd = avg_error(cp, pred)
    return [ae, ce, pd]
}

func diversity_format(stats) {
    gather {
        for t,v in (%w(average-error crowd-error diversity) ~Z stats) {
            take(("%13s" % t) + ':' + ('%7.3f' % v))
        }
    }
}

diversity_format(diversity_calc(49, [48, 47, 51])).each{.say}
diversity_format(diversity_calc(49, [48, 47, 51, 42])).each{.say}
Output:
average-error:  3.000
  crowd-error:  0.111
    diversity:  2.889
average-error: 14.500
  crowd-error:  4.000
    diversity: 10.500

TypeScript

function sum(array: Array<number>): number {
    return array.reduce((a, b) => a + b)
}

function square(x : number) :number {
    return x * x
}

function mean(array: Array<number>): number {
    return sum(array) / array.length
}

function averageSquareDiff(a: number, predictions: Array<number>): number {
    return mean(predictions.map(x => square(x - a)))
}

function diversityTheorem(truth: number, predictions: Array<number>): Object {
    const average: number = mean(predictions)
    return {
        "average-error": averageSquareDiff(truth, predictions),
        "crowd-error": square(truth - average),
        "diversity": averageSquareDiff(average, predictions)
    }
}

console.log(diversityTheorem(49, [48,47,51]))
console.log(diversityTheorem(49, [48,47,51,42]))
Output:
{ 'average-error': 3,
  'crowd-error': 0.11111111111111269,
  diversity: 2.888888888888889 }
{ 'average-error': 14.5, 'crowd-error': 4, diversity: 10.5 }

Wren

Translation of: Go
import "./fmt" for Fmt

var averageSquareDiff = Fn.new { |f, preds|
    var av = 0
    for (pred in preds) av = av + (pred-f)*(pred-f)
    return av/preds.count
}

var diversityTheorem = Fn.new { |truth, preds|
    var av = (preds.reduce { |sum, pred| sum + pred }) / preds.count
    var avErr = averageSquareDiff.call(truth, preds)
    var crowdErr = (truth-av) * (truth-av)
    var div = averageSquareDiff.call(av, preds)
    return [avErr, crowdErr, div]
}

var predsList = [ [48, 47, 51], [48, 47, 51, 42] ]
var truth = 49
for (preds in predsList) {
    var res = diversityTheorem.call(truth, preds)
    Fmt.print("Average-error : $6.3f", res[0])
    Fmt.print("Crowd-error   : $6.3f", res[1])
    Fmt.print("Diversity     : $6.3f\n", res[2])
}
Output:
Average-error :  3.000
Crowd-error   :  0.111
Diversity     :  2.889

Average-error : 14.500
Crowd-error   :  4.000
Diversity     : 10.500

XPL0

real Estimates, TrueVal, AvgErr, CrowdErr, Sum, Avg;
int  I, J;
[Estimates:= [ [48., 47., 51., 0.], [48., 47., 51., 42., 0.] ];
TrueVal:= 49.;
Format(2, 3);
for I:= 0 to 1 do
    [Sum:= 0.;  J:= 0;
    while Estimates(I,J) # 0. do
        [Sum:= Sum + sq(Estimates(I,J) - TrueVal);  J:= J+1];
    AvgErr:= Sum/float(J);
    Text(0, "Average error : ");  RlOut(0, AvgErr);  CrLf(0);

    Sum:= 0.;  J:= 0;
    while Estimates(I,J) # 0. do
        [Sum:= Sum + Estimates(I,J);  J:= J+1];
    Avg:= Sum/float(J);
    CrowdErr:= sq(TrueVal-Avg);
    Text(0, "Crowd error   : ");  RlOut(0, CrowdErr);  CrLf(0);

    Text(0, "Diversity     : ");  RlOut(0, AvgErr-CrowdErr);  CrLf(0);
    CrLf(0);
    ];
]
Output:
Average error :  3.000
Crowd error   :  0.111
Diversity     :  2.889

Average error : 14.500
Crowd error   :  4.000
Diversity     : 10.500

zkl

Translation of: Sidef
fcn avgError(m,v){ v.apply('wrap(n){ (n - m).pow(2) }).sum(0.0)/v.len() }
 
fcn diversityCalc(truth,pred){  //(Float,List of Float)
   ae,cp := avgError(truth,pred), pred.sum(0.0)/pred.len();
   ce,pd := (cp - truth).pow(2),  avgError(cp, pred);
   return(ae,ce,pd)
}
 
fcn diversityFormat(stats){  // ( (averageError,crowdError,diversity) )
   T("average-error","crowd-error","diversity").zip(stats)
   .pump(String,Void.Xplode,"%13s :%7.3f\n".fmt)
}
diversityCalc(49.0, T(48.0,47.0,51.0)) : diversityFormat(_).println();
diversityCalc(49.0, T(48.0,47.0,51.0,42.0)) : diversityFormat(_).println();
Output:
average-error :  3.000
  crowd-error :  0.111
    diversity :  2.889

average-error : 14.500
  crowd-error :  4.000
    diversity : 10.500