{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a79b597b",
   "metadata": {},
   "source": [
    "# Switching privacy definition in Session and privacy mechanism in aggregation"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ec5a89c",
   "metadata": {},
   "source": [
    "## Import Libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d6be7958",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyspark.sql import SparkSession\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b2a3ad6",
   "metadata": {},
   "source": [
    "In order to build any session and answer queries **QueryBuilder** and **Session** are needed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84230cdd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tmlt.analytics.query_builder import QueryBuilder\n",
    "from tmlt.analytics.privacy_budget import PureDPBudget, RhoZCDPBudget\n",
    "from tmlt.analytics.session import Session"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c2bd63a",
   "metadata": {},
   "source": [
    "We also need to specify privacy_budget in Session and mechanism in query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6db4327",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tmlt.analytics.query_expr import CountMechanism\n",
    "from tmlt.core.measures import RhoZCDP, PureDP"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d6121d6",
   "metadata": {},
   "source": [
    "## Load a Simple Dataset\n",
    "\n",
    "We use a very simple dataset here to illustrate the example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17fe526e",
   "metadata": {},
   "outputs": [],
   "source": [
    "spark = SparkSession.builder.getOrCreate()\n",
    "private_data = spark.createDataFrame(pd.DataFrame([[\"0\", 1, 0], [\"1\", 0, 1]], columns=[\"A\", \"B\", \"X\"]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1567e3d1",
   "metadata": {},
   "source": [
    "## Build Session with appropriate privacy budget\n",
    "\n",
    "A privacy budget associates a privacy definition with one or more numeric values.\n",
    "\n",
    "To build a session under rho-Zero-Concentrated Differential Privacy/RhoZCDP privacy definition, a RhoZCDPBudget privacy_budget is passed in as argument. The associated value is the rho privacy parameter.  \n",
    "\n",
    "To build a session under Pure Differential Privacy/PureDP privacy definition, a PureDPBudget privacy_budget is passed. This privacy definition is also known as epsilon-differential privacy, and the associated value is the epsilon privacy parameter.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "701790ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Session with RhoZCDP.\n",
    "zcdp_sess = Session.from_dataframe(\n",
    "    privacy_budget=RhoZCDPBudget(10),\n",
    "    source_id=\"my_private_data\",\n",
    "    dataframe=private_data,\n",
    ")\n",
    "\n",
    "# Session with PureDP.\n",
    "puredp_sess = Session.from_dataframe(\n",
    "    privacy_budget=PureDPBudget(10),\n",
    "    source_id=\"my_private_data\",\n",
    "    dataframe=private_data,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec04e618",
   "metadata": {},
   "source": [
    "### Gaussian noise can be used with RhoZCDP.\n",
    "\n",
    "This example illustrates the use of discrete Gaussian noise with RhoZCDP. We pass the `mechanism` argument to the query and specify discrete gaussian noise."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "163c29d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "query_with_guassian = QueryBuilder(\"my_private_data\").count(mechanism=CountMechanism.GAUSSIAN)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e31fd118",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "answer = zcdp_sess.evaluate(query_expr=query_with_guassian, privacy_budget=RhoZCDPBudget(1))\n",
    "answer.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "482e6759",
   "metadata": {},
   "source": [
    "### Laplace or Geometric noise can be used with RhoZCDP or PureDP.\n",
    "\n",
    "This example illustrates the use of Laplace noise with RhoZCDP and PureDP. We pass the `mechanism` argument to the query and specify Laplace noise. Laplace noise is used if measure column is floating-point valued, while double-sided geometric noise is used if measure column is integer-valued. Since count query is always integer-valued, double-sided geometric noise gets applied."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8deb0d0d",
   "metadata": {},
   "outputs": [],
   "source": [
    "query_with_laplace = QueryBuilder(\"my_private_data\").count(mechanism=CountMechanism.LAPLACE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8fcfa1f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "answer = zcdp_sess.evaluate(query_expr=query_with_laplace, privacy_budget=RhoZCDPBudget(1))\n",
    "answer.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d6d122bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "answer = puredp_sess.evaluate(query_expr=query_with_laplace, privacy_budget=PureDPBudget(1))\n",
    "answer.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afbfdc59",
   "metadata": {},
   "source": [
    "### Gaussian noise can not be used with PureDP.\n",
    "\n",
    "This example illustrates that discrete Gaussian noise with PureDP is currently not supported."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f07599c",
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    puredp_sess.evaluate(\n",
    "        query_expr=query_with_guassian,\n",
    "        privacy_budget=PureDPBudget(1)\n",
    "    )\n",
    "except Exception as e:\n",
    "    print(e)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
