1
$\begingroup$

The problem is that reap only returns one value when I was expecting a string resulting from Do.

For context:

This is a simple democratic deficiency model. Where m is the number of periods, n is the number of voters,and r is the frequency of elections. c is the table which represents the preferences of voters, currently random. v is the rule which determines the policy set by the government based on the simple average of preferences. mode is the function which sets elections. e is a dummy variable for elections. u is a placeholder vector. g is the function which allows the government to update policies in election years. dgpcpp is the democratic deficiency generated by the current government per person per year. I would like to run this program multiple (maybe 100) times for varying values of r and plot the values of dgpcpp. Eventually I would also like to add a function of interaction between voters which replaces RandomnInteger in how their preferences are determined. Finally would like to give each individual a vector of preferences so that I could compare this model with an indirect (first past the post) voting model where preferences determine candidate selection.

 Do[m = 10;
 n = 5;
 r = 4;
 c = RandomInteger[1, {m, n}];
 avg = Total[c, {2}]/n;
 v = If[0.5 <= # <= 1, 1, 0] & /@ avg;
 de = Abs[v - avg];
 Total[de];
 depcpp = Total[de]/n/m;
 mode = Mod[r - 1 + Range[m], r];
 e = If[# == 0, 1, 0] & /@ mode;
 u = RandomInteger[1, m];
 g = MapThread[If[#1 == 1, #2, #3] &, {e, v, u}];
 dg = Abs[g - avg];
 Total[dg];
 dgpcpp = Total[dg]/n/m; Sow[dgpcpp], {100}]
 Reap[dgpcpp]
 Total[dgpcpp]/r
$\endgroup$
  • 1
    $\begingroup$ Any use of Sow[] should really be within a Reap[]: Reap[Do[(* stuff *); Sow[dgpcpp]; (* more stuff *)]]. $\endgroup$ – J. M. will be back soon Jan 8 '17 at 21:28
  • $\begingroup$ Thank you! I must have misunderstood the documentation. Could you explain why the first result is null or how to change it so I can sum over the list? $\endgroup$ – CharlesBouwer Jan 8 '17 at 21:34
  • $\begingroup$ Why don't you use Table instead of Do, Sow & Reap? $\endgroup$ – Sjoerd C. de Vries Jan 8 '17 at 21:52
  • $\begingroup$ I am not sure how to make a table of tables. I would also like to learn a functional programming or pure function approach but am brand new to the software. $\endgroup$ – CharlesBouwer Jan 8 '17 at 22:03
4
$\begingroup$

Let's try something very simple first

try1 = Do[dgcpp = n^2; Sow[dgcpp], {n, 4}]

Reap[try1]
(* {Null, {}} *)

Now Null, the output of Do, is returned as the first element and an empty list as the second element. Now try:

try2 = Reap[
  Do[dgcpp = n^2; Sow[dgcpp], {n, 4}]
  ]
(* {Null, {{1, 4, 9, 16}}} *)

Now Null is returned as the first element and the Sow values are a list within a list for the second element.

A slightly more functional approach

try3 = Reap[
  Scan[Sow[#^2] &, Range[4]]
  ]
(* {Null, {{1, 4, 9, 16}}} *)

produces a similar result.

Applying to your problem

dgpcppList = Reap[
  Scan[
   m = 10;
    n = 5;
    r = 4;
    c = RandomInteger[1, {m, n}];
    avg = Total[c, {2}]/n;
    v = If[0.5 <= # <= 1, 1, 0] & /@ avg;
    de = Abs[v - avg];
    Total[de];
    depcpp = Total[de]/n/m;
    mode = Mod[r - 1 + Range[m], r];
    e = If[# == 0, 1, 0] & /@ mode;
    u = RandomInteger[1, m];
    g = MapThread[If[#1 == 1, #2, #3] &, {e, v, u}];
    dg = Abs[g - avg];
    Total[dg];
    dgpcpp = Total[dg]/n/m;
    Sow[dgpcpp]; &,
   Range[100]
   ]
  ]
(* {Null, {{9/125, 11/125, 11/125, 21/250, 1/10, 11/125, 9/125, 
   29/250, 23/250, 23/250, 2/25, 13/125, 11/125, 1/10, 27/250, 2/25, 
   8/125, 11/125, 19/250, 23/250, 21/250, 3/25, 23/250, 27/250, 23/
   250, 2/25, 11/125, 23/250, 2/25, 21/250, 13/125, 1/10, 23/250, 11/
   125, 21/250, 2/25, 14/125, 2/25, 13/125, 2/25, 23/250, 12/125, 19/
   250, 23/250, 29/250, 23/250, 2/25, 3/25, 9/125, 21/250, 23/250, 1/
   10, 3/50, 13/125, 19/250, 12/125, 17/250, 12/125, 21/250, 8/125, 
   23/250, 11/125, 19/250, 12/125, 9/125, 2/25, 11/125, 17/250, 13/
   125, 1/10, 12/125, 19/250, 12/125, 9/125, 13/125, 12/125, 2/25, 12/
   125, 21/250, 12/125, 14/125, 2/25, 21/250, 9/125, 21/250, 21/250, 
   11/125, 12/125, 29/250, 13/125, 13/125, 12/125, 19/250, 19/250, 2/
   25, 2/25, 19/250, 1/10, 11/125, 19/250}}} *)

Now you can extract the interior of the second list and apply Total to get

Total@dgpcppList[[2, 1]]
(* 2227/250 *)
$\endgroup$
  • $\begingroup$ Thanks Jack very helpful. I will look into scan. $\endgroup$ – CharlesBouwer Jan 8 '17 at 22:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.