{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9fa015f3-ab7b-406b-92ca-db2a2fd4bcdb",
   "metadata": {},
   "source": [
    "# Order of Reactants and Products\n",
    "\n",
    "In this section, we will construct an example model to show how the order of reactants and products affects a meta-reaction. MobsPy uses a round-robin structure to assign reactant states to product states."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c61b4b9b-705c-4d73-bd8e-5fb7b99b9413",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<mobspy.modules.meta_class.Reacting_Species at 0x7fd853316820>,\n",
       " <mobspy.modules.meta_class.Reacting_Species at 0x7fd8533a4eb0>)"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mobspy import *\n",
    "\n",
    "Age = BaseSpecies(1)\n",
    "Age.young >> Age.old [1]\n",
    "\n",
    "Animal = New(Age)\n",
    "Animal.a1, Animal.a2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56a573b8-42d9-45e6-bd87-ca9588a4d174",
   "metadata": {},
   "source": [
    "The Round-Robin mechanism is demonstrated with the reaction below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4af91b90-0a96-47c0-8a44-1be77cd7ccf7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<mobspy.modules.meta_class.Reactions at 0x7fd853345370>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Animal.old + Animal.young >> Animal.old [1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bfd0e362-ccc5-4d0c-baa2-60da1b42ce4d",
   "metadata": {},
   "source": [
    "In the meta-reaction presented above, if the order is not considered, the meaning of the reaction becomes ambiguous. \n",
    "There are two possibilities: either the old animal kills the young one and survives, or the young animal kills the old one and becomes old himself. \n",
    "\n",
    "MobsPy solves this ambiguity by taking into consideration the order of the reactants. \n",
    "The state of the first animal is used to generate the first animal that appears in the product, and so it continues with the matching order.\n",
    "If a case happens where there are more reactants than products, the states of the reactants will not be used to generate the products (considered dead). \n",
    "If a case happens where there are more products than reactants, the extra products will use the state of the first reactant, then the second, etc, in a cyclic round-robin fashion.  \n",
    "It stops once all the products are assigned a reactant state.  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36909283-d9de-4365-8eb5-699051d6b25d",
   "metadata": {},
   "source": [
    "If required, the .label() can be used to circumvent this default behavior, with products using the state of reactants with the same matching label. \n",
    "In the next reaction, the young Animal kills the old and becomes old itself. \n",
    "The rate of two is assigned to distinguish the reactions after compilation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3ae158e1-7ca2-4473-bddc-7acdb93e94cd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<mobspy.modules.meta_class.Reactions at 0x7fd85948df40>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Animal.old + Animal.young.label(1) >> Animal.old.label(1) [2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af014d01-d04d-479f-9951-a8cf4106b26a",
   "metadata": {},
   "source": [
    "The cyclic round-robin style is valuable in reproduction reactions. \n",
    "Since the assignment cycles in a round-robin fashion, the first product will be assigned the first reactant, and the second product will cycle through the reactants and be assigned the first reactant as well. It is most useful when dealing with cellular reproduction, as the daughter cells keep several aspects of their parent. \n",
    "\n",
    "In the example below, the two products will be generated in the same state as the reactant when duplicated. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d41d8c71-f39e-4f62-83bf-4936697138a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<mobspy.modules.meta_class.Reactions at 0x7fd8533453a0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Animal >> 2*Animal [3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3fc1f8f-0579-4015-a3d6-c05a0d667a54",
   "metadata": {},
   "source": [
    "Finally, the compilation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "aafeea6d-dd47-4368-8ec5-f0c22b48bb49",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Compiling model\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Species\n",
      "Animal.a1.old,0\n",
      "Animal.a1.young,0\n",
      "Animal.a2.old,0\n",
      "Animal.a2.young,0\n",
      "\n",
      "Mappings\n",
      "Animal :\n",
      "Animal.a1.old\n",
      "Animal.a1.young\n",
      "Animal.a2.old\n",
      "Animal.a2.young\n",
      "\n",
      "Parameters\n",
      "volume,1\n",
      "\n",
      "Reactions\n",
      "reaction_0,{'re': [(1, 'Animal.a1.old'), (1, 'Animal.a1.young')], 'pr': [(1, 'Animal.a1.old')], 'kin': 'Animal.a1.old * Animal.a1.young * 1 * volume^-1'}\n",
      "reaction_1,{'re': [(1, 'Animal.a1.old'), (1, 'Animal.a1.young')], 'pr': [(1, 'Animal.a1.old')], 'kin': 'Animal.a1.old * Animal.a1.young * 2 * volume^-1'}\n",
      "reaction_2,{'re': [(1, 'Animal.a1.old'), (1, 'Animal.a2.young')], 'pr': [(1, 'Animal.a1.old')], 'kin': 'Animal.a1.old * Animal.a2.young * 1 * volume^-1'}\n",
      "reaction_3,{'re': [(1, 'Animal.a1.old'), (1, 'Animal.a2.young')], 'pr': [(1, 'Animal.a2.old')], 'kin': 'Animal.a1.old * Animal.a2.young * 2 * volume^-1'}\n",
      "reaction_4,{'re': [(1, 'Animal.a1.old')], 'pr': [(2, 'Animal.a1.old')], 'kin': 'Animal.a1.old * 3'}\n",
      "reaction_5,{'re': [(1, 'Animal.a1.young')], 'pr': [(1, 'Animal.a1.old')], 'kin': 'Animal.a1.young * 1'}\n",
      "reaction_6,{'re': [(1, 'Animal.a1.young')], 'pr': [(2, 'Animal.a1.young')], 'kin': 'Animal.a1.young * 3'}\n",
      "reaction_7,{'re': [(1, 'Animal.a2.old'), (1, 'Animal.a1.young')], 'pr': [(1, 'Animal.a1.old')], 'kin': 'Animal.a2.old * Animal.a1.young * 2 * volume^-1'}\n",
      "reaction_8,{'re': [(1, 'Animal.a2.old'), (1, 'Animal.a1.young')], 'pr': [(1, 'Animal.a2.old')], 'kin': 'Animal.a2.old * Animal.a1.young * 1 * volume^-1'}\n",
      "reaction_9,{'re': [(1, 'Animal.a2.old'), (1, 'Animal.a2.young')], 'pr': [(1, 'Animal.a2.old')], 'kin': 'Animal.a2.old * Animal.a2.young * 1 * volume^-1'}\n",
      "reaction_10,{'re': [(1, 'Animal.a2.old'), (1, 'Animal.a2.young')], 'pr': [(1, 'Animal.a2.old')], 'kin': 'Animal.a2.old * Animal.a2.young * 2 * volume^-1'}\n",
      "reaction_11,{'re': [(1, 'Animal.a2.old')], 'pr': [(2, 'Animal.a2.old')], 'kin': 'Animal.a2.old * 3'}\n",
      "reaction_12,{'re': [(1, 'Animal.a2.young')], 'pr': [(1, 'Animal.a2.old')], 'kin': 'Animal.a2.young * 1'}\n",
      "reaction_13,{'re': [(1, 'Animal.a2.young')], 'pr': [(2, 'Animal.a2.young')], 'kin': 'Animal.a2.young * 3'}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "MySim = Simulation(Animal)\n",
    "print(MySim.compile())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
