Source: compute/voteCasters/voteCasters/makeGrid1D.js

  1. import { normPDF } from '@paretoman/votekit-utilities'
  2. import * as types from '@paretoman/votekit-types'
  3. /**
  4. * makes 1D grid data structure
  5. * @param {types.typesGeoms.voterGeom1D} voterGeom
  6. * @returns {types.typesGrid.grid1D}
  7. */
  8. export default function makeGrid1D(voterGeom) {
  9. const { gridX, voterPoints, gridPointLength } = findGridX(voterGeom)
  10. const { density, voteCounts, totalVotes } = findDensity(voterGeom, gridX, gridPointLength)
  11. const grid = { x: gridX, density, voterPoints, voteCounts, totalVotes, voterGeom }
  12. return grid
  13. }
  14. /**
  15. * get x coordinates for grid
  16. * @param {types.typesGeoms.voterGeom1D} voterGeom
  17. * @returns {types.typesGrid.gridX}
  18. */
  19. function findGridX(voterGeom) {
  20. const isGauss = voterGeom.densityProfile === 'gaussian'
  21. const spread = (isGauss) ? 2 : 1
  22. const iWidth = Math.round(voterGeom.w * spread)
  23. const gridX = Array(iWidth)
  24. const voterPoints = Array(iWidth)
  25. const gridPointLength = 1
  26. for (let i = 0; i < iWidth; i++) {
  27. const x = i + 0.5 - iWidth * 0.5 + voterGeom.x
  28. gridX[i] = x
  29. voterPoints[i] = x
  30. }
  31. return { gridX, voterPoints, gridPointLength }
  32. }
  33. function findDensity(voterGeom, gridX, gridPointLength) {
  34. const { x, w, densityProfile, densityMax } = voterGeom
  35. const isGauss = densityProfile === 'gaussian'
  36. const density = Array(gridX.length)
  37. const voteCounts = Array(gridX.length)
  38. if (!isGauss) {
  39. const d = densityMax
  40. density.fill(d)
  41. voteCounts.fill(d)
  42. const totalVotes = voteCounts.length * d
  43. return { density, voteCounts, totalVotes }
  44. }
  45. const sigma = w / Math.sqrt(2 * Math.PI) // w = sigma * sqrt(2*pi)
  46. const invNorm = 1 / normPDF(0, 0, sigma)
  47. let totalVotes = 0
  48. for (let i = 0; i < gridX.length; i++) {
  49. const xi = gridX[i]
  50. const d = normPDF(xi, x, sigma) * invNorm * densityMax
  51. density[i] = d
  52. const voteCount = d * gridPointLength
  53. voteCounts[i] = voteCount
  54. totalVotes += voteCount
  55. }
  56. return { density, voteCounts, totalVotes }
  57. }