version: 1
title: Pi
contributor: https://github.com/emanb29
summary: Incrementally approximates pi using Leibniz' formula
description: |-
  Incrementally approximates pi using Leibniz' formula -- the arctangent function is incrementally
  (corecursively) computed along :improved_by edges, and each arctangent approximation is quadrupled
  to yield an approximation of pi.

ingestStreams: []

standingQueries:
  - pattern:
      type: Cypher
      query: MATCH (n:arctan) WHERE n.approximation IS NOT NULL AND n.denominator IS NOT NULL RETURN DISTINCT id(n) AS id
    outputs:
      # iterate over arctan
      iterate:
        type: CypherQuery
        query: |-
          MATCH (n)
          WHERE id(n) = $that.data.id
          WITH n, -sign(n.denominator)*(abs(n.denominator)+2) as nextDenom
          WITH n, nextDenom, n.approximation+(1/nextDenom) as nextApprox
          MATCH (next) WHERE id(next) = idFrom(nextDenom)
          SET next:arctan, next.denominator = nextDenom, next.approximation=nextApprox
          CREATE (n)-[:improved_by]->(next)
      # map arctan to piApprox
      piApprox:
        type: CypherQuery
        query: |-
          MATCH (arctan)
          WHERE id(arctan) = $that.data.id
          WITH arctan, arctan.denominator AS denominator, arctan.approximation*4 AS approximatedPi
          MATCH (approximation) WHERE id(approximation) = idFrom('approximation', denominator)
          SET approximation:piApproximation, approximation.approximatedPi = approximatedPi
          CREATE (arctan)-[:approximates]->(approximation)
          RETURN approximatedPi
        andThen:
          type: WriteToFile
          path: $out_file

nodeAppearances:
  - predicate:
      propertyKeys: []
      knownValues: {}
      dbLabel: piApproximation
    icon: π
    size: 40
    color: "#f1c232"
    label:
      type: Property
      key: approximatedPi
      prefix:
  - predicate:
      propertyKeys: []
      knownValues: {}
      dbLabel: arctan
    icon: ⦛
    size: 20
    color: "#000000"
    label:
      type: Constant
      value: 𝚊𝚛𝚌𝚝𝚊𝚗 

sampleQueries:
  - name: "[No Output] Run this query to begin processing."
    query: WITH 1 AS initialDenominator MATCH (n) WHERE id(n) = idFrom(1) SET n.denominator = toFloat(1), n.approximation = toFloat(1), n:arctan
  - name: "[Node] Get Best Approximation (so far)"
    query:
      CALL recentNodes(15) YIELD node AS nId
      MATCH (n)
      WHERE id(n) = nId AND n.approximatedPi IS NOT NULL
      RETURN n LIMIT 1
  - name: "[Text] Get Best Approximation (so far)"
    query:
      CALL recentNodes(15) YIELD node AS nId
      MATCH (n)
      WHERE id(n) = nId AND n.approximatedPi IS NOT NULL
      RETURN n.approximatedPi LIMIT 1
  - name: "[Text] Repeatedly Get Best Approximation (so far)"
    query:
      UNWIND range(0, 1000) AS x UNWIND range(0, 1000) AS y
      CALL util.sleep(1000)
      CALL cypher.doIt("
        CALL recentNodes(15) YIELD node AS nId
        MATCH (n)
        WHERE id(n) = nId AND n.approximatedPi IS NOT NULL
        RETURN n.approximatedPi AS approximatedPi LIMIT 1
      ") YIELD value
      RETURN value.approximatedPi AS approximatedPi, abs(pi() - value.approximatedPi) AS error
quickQueries: [ ]
