Search Unity

Question [Not Solved] Training agents without movement

Discussion in 'ML-Agents' started by mateolopezareal, Jun 4, 2020.

  1. mateolopezareal

    mateolopezareal

    Joined:
    Jun 4, 2020
    Posts:
    54
    [NOT SOLVED]
    Hello there,
    I am making a project that consists in a matrix in which each cube is an agent. The cubes do not move, they just have to change their state (Material), so if they are dead, they are white; and if they are alive they can be 3 races, black, green or red. So the goal is to obtain a matrix with the three races alive and no dead.
    To do this I give a reward of -10 if the agent is dead, and a bunch of more things if it is alive (the reward depends of this depends if the cubes around a cube are of the same colour, so if the cube has turn into red but has 8 greens around it it will get a punishment for example).
    So, for the observations I give to the agent the color of the neighbours in numbers (dead=0, black=1, green=2 , red=3), the neighbours are the cubes above, on the left, on the right, etc so they are 8 observations plus the color of the agent, so 9.
    Taking all this into account the agents learn to have all the same colour to maximise the reward. To change this I am going to give as a reward the entropy of all the cubes. By doing this the agent will look to maximise also the entropy, so to have as much races alive as possible. But the problem is, ¿what do I give as an observation for this? If I put the entropy thing, and give as observation the color (the number) all the cubes in the matrix. my reward does not increase, it stays linear.
    Also, I have some questions about ml-agents:
    1. ¿It is possible to do a project of this type, because all the project that I have seen involved movement?
    2. I am using the fixed update so, all the cubes has the same entropy, because if I calculate the entropy in the agent action, the entropy changes, ¿is it a good idea?
    3. I am trying also to add a reward that represents a race, ¿any ideas?
    4. ¿If I give as observation the color (the number) all the cubes in the matrix, the vector observation size is 153, is this a problem?
    5. ¿Some time ago when I gave the entropy as a reward, the reward graphic went up but then down like a mountain, why is this?
    I know It is too much info, so I will be waiting for your response.

    Here is my code if it helps.
    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Text;
    6. using System.Security.Principal;
    7. using UnityScript.Steps;
    8. using UnityEditor.Experimental.UIElements;
    9. using Unity.MLAgents;
    10. using Unity.MLAgents.Sensors;
    11.  
    12. public class ConwayCube : Agent
    13. {
    14.     [Header("¿Que color es?")]
    15.     public int tipo;
    16.     [Header("Tiempo entre decisiones")]
    17.     public float timeBetweenDecisionsAtInference;
    18.     [Header("Materials")]
    19.     public Material dead;
    20.     public Material black;
    21.     public Material green;
    22.     public Material red;
    23.     [HideInInspector]
    24.     public Material actualmaterial;
    25.     [HideInInspector]
    26.     public bool contado;
    27.     private float m_TimeSinceDecision;
    28.     private new Rigidbody rigidbody;
    29.     private Material cubeBack, cubeForward, cubeRight, cubeLeft, cubeForwardRight, cubeForwardLeft, cubeBackRight, cubeBackLeft;
    30.     private Histograma histograma;
    31.     private float entropiaC, entropiaN, entropiaV, entropiaR;
    32.     private int colores0, coloresN, coloresV, coloresR;
    33.     private int coloresNT, coloresVT, coloresRT;
    34.  
    35.     public override void Initialize()
    36.     {
    37.         histograma = gameObject.GetComponentInParent<Histograma>();
    38.         entropiaC = getEntropyCompleta2(histograma.getHistogramaCompleto());
    39.         rigidbody = GetComponent<Rigidbody>();
    40.         ChooseRandomColor();
    41.         base.Initialize();
    42.         entropiaN = getEntropyVecinos(black);
    43.         entropiaV = getEntropyVecinos(green);
    44.         entropiaR = getEntropyVecinos(red);
    45.         int[] colores = CuentaColores();
    46.         colores0 = colores[0];
    47.         coloresN = colores[1];
    48.         coloresV = colores[2];
    49.         coloresR = colores[3];
    50.         /*if (tipo==1)
    51.         {
    52.             EstaNegro();
    53.         }else if (tipo==2)
    54.         {
    55.             EstaVerde();
    56.         }else if (tipo==3)
    57.         {
    58.             EstaRojo();
    59.         }else
    60.         {
    61.             EstaMuerto();
    62.         }*/
    63.     }
    64.  
    65.     public void EstaMuerto()
    66.     {
    67.         gameObject.GetComponentInChildren<Renderer>().material = dead;
    68.         actualmaterial = dead;
    69.     }
    70.     public void EstaRojo()
    71.     {
    72.         gameObject.GetComponentInChildren<Renderer>().material = red;
    73.         actualmaterial = red;
    74.     }
    75.     public void EstaVerde()
    76.     {
    77.         gameObject.GetComponentInChildren<Renderer>().material = green;
    78.         actualmaterial = green;
    79.     }
    80.     public void EstaNegro()
    81.     {
    82.         gameObject.GetComponentInChildren<Renderer>().material = black;
    83.         actualmaterial = black;
    84.     }
    85.  
    86.  
    87.     public override void CollectObservations(VectorSensor sensor)
    88.     {
    89.         List<Material> lista = new List<Material>();
    90.         lista.Add(actualmaterial);
    91.         lista.Add(cubeForward);
    92.         lista.Add(cubeForwardRight);
    93.         lista.Add(cubeRight);
    94.         lista.Add(cubeBackRight);
    95.         lista.Add(cubeBack);
    96.         lista.Add(cubeBackLeft);
    97.         lista.Add(cubeLeft);
    98.         lista.Add(cubeForwardLeft);
    99.         List<float> listanum = new List<float>();
    100.         foreach (Material material in lista)
    101.         {
    102.             if (material == dead)
    103.             {
    104.                 //AddVectorObs(0);
    105.                 listanum.Add(0);
    106.             }
    107.             else if (material == black)
    108.             {
    109.                 //AddVectorObs(1);
    110.                 listanum.Add(1);
    111.             }
    112.             else if (material == green)
    113.             {
    114.                 //AddVectorObs(2);
    115.                 listanum.Add(2);
    116.             }
    117.             else if (material == red)
    118.             {
    119.                 //AddVectorObs(3);
    120.                 listanum.Add(3);
    121.             }
    122.             else
    123.             {
    124.                 //AddVectorObs(4);
    125.                 listanum.Add(4);
    126.             }
    127.         }
    128.         foreach (int num in listanum)
    129.         {
    130.             sensor.AddObservation(num);
    131.         }
    132.         foreach (int hist in histograma.getListaCompleto())
    133.         {
    134.             sensor.AddObservation(hist);
    135.         }
    136.         //sensor.AddObservation(histograma.getHistogramaColorTrampas(actualmaterial));
    137.         //sensor.AddObservation(entropiaN);
    138.         //sensor.AddObservation(entropiaV);
    139.         //sensor.AddObservation(entropiaR);
    140.     }
    141.     public float getEntropyCompleta2(int[] histogram)
    142.     {
    143.         double[] lista = new double[histogram.Length];
    144.         double entropia = 0;
    145.         int muertos = histogram[0];
    146.  
    147.         for (int i = 1; i < histogram.Length; i++)
    148.         {
    149.             lista[i] = histogram[i];
    150.             lista[i] = lista[i] / (144 - muertos);
    151.             if (lista[i] != 0)
    152.             {
    153.                 entropia += (lista[i] * Math.Log(lista[i], 3));
    154.             }
    155.         }
    156.         return -(float)entropia;
    157.     }
    158.     //Pasar a clase histograma
    159.     public float getEntropyCompleta(int[] histogram)
    160.     {
    161.         double[] lista = new double[histogram.Length];
    162.         double entropia = 0;
    163.         int muertos = histogram[0];
    164.  
    165.         for (int i = 0; i < histogram.Length; i++)
    166.         {
    167.             lista[i] = histogram[i];
    168.             lista[i] = lista[i] / (144);
    169.             if (lista[i] != 0)
    170.             {
    171.                 entropia += (lista[i] * Math.Log(lista[i], 4));
    172.             }
    173.         }
    174.         return -(float)entropia;
    175.     }
    176.     public float getEntropyVecinos(Material color)
    177.     {
    178.         float[] histogram = histograma.getHistogramaColorTrampas(color);
    179.         int vecinos = histograma.getNumeroVecinos(color);
    180.  
    181.         int num;
    182.  
    183.         if (color == dead)
    184.         {
    185.             num = 0;
    186.         }
    187.         else if (color == black)
    188.         {
    189.             num = 1;
    190.         }
    191.         else if (color == green)
    192.         {
    193.             num = 2;
    194.         }
    195.         else if (color == red)
    196.         {
    197.             num = 3;
    198.         }
    199.         else
    200.         {
    201.             num = 4;
    202.         }
    203.         float aux2 = histogram[num];
    204.         float aux1 = vecinos;
    205.         float entropia = (aux2) / (aux1);
    206.         if (aux2 == 0)
    207.         {
    208.             entropia = -10;
    209.         }
    210.         return entropia;
    211.     }
    212.     public override void OnActionReceived(float[] vectorAction)
    213.     {
    214.         var color = (int)vectorAction[0];
    215.         contado = true;
    216.         if (coloresNT == 48 && coloresRT == 48 && coloresVT == 48)
    217.         {
    218.             AddReward(50f);
    219.             EndEpisode();
    220.         }
    221.         else
    222.         {
    223.             if (actualmaterial == dead)
    224.             {
    225.                 if (coloresV == 0 && coloresR == 0 && coloresN != 0)
    226.                 {
    227.                     EstaNegro();
    228.                     AddReward(0.00001f);
    229.                 }
    230.                 else if (coloresN == 0 && coloresR == 0 && coloresV != 0)
    231.                 {
    232.                     EstaVerde();
    233.                     AddReward(0.00001f);
    234.                 }
    235.                 else if (coloresV == 0 && coloresN == 0 && coloresR != 0)
    236.                 {
    237.                     EstaRojo();
    238.                     AddReward(0.00001f);
    239.                 }
    240.                 else if (coloresV == 0 && coloresR == 0 && coloresN == 0)
    241.                 {
    242.                     EstaMuerto();
    243.                     AddReward(-10f);
    244.                 }
    245.                 else
    246.                 {
    247.                     switch (color)
    248.                     {
    249.                         case 0:
    250.                             EstaMuerto();
    251.                             break;
    252.                         case 1:
    253.                             EstaNegro();
    254.                             break;
    255.                         case 2:
    256.                             EstaVerde();
    257.                             break;
    258.                         case 3:
    259.                             EstaRojo();
    260.                             break;
    261.                     }
    262.                     if (actualmaterial == dead)
    263.                     {
    264.                         AddReward(-10f);
    265.                     }
    266.                     else if (actualmaterial == black)
    267.                     {
    268.                         if (coloresN > coloresR && coloresN > coloresV && coloresN > colores0)
    269.                         {
    270.                             AddReward(0.001f);
    271.                         }
    272.                         else if (coloresN > coloresR && coloresN > coloresV && coloresN < colores0)
    273.                         {
    274.                             AddReward(0.0001f);
    275.                         }
    276.                         else if (coloresN > coloresR && coloresN < coloresV)
    277.                         {
    278.                             if (coloresR == 0)
    279.                             {
    280.                                 AddReward(-1f);
    281.                             }
    282.                             else
    283.                             {
    284.                                 AddReward(-0.1f);
    285.                             }
    286.                         }
    287.                         else if (coloresN < coloresR && coloresN > coloresV)
    288.                         {
    289.                             if (coloresV == 0)
    290.                             {
    291.                                 AddReward(-1f);
    292.                             }
    293.                             else
    294.                             {
    295.                                 AddReward(-0.1f);
    296.                             }
    297.                         }
    298.                         else if (coloresN < coloresR && coloresN < coloresV)
    299.                         {
    300.                             AddReward(-1f);
    301.                         }
    302.  
    303.                     }
    304.                     else if (actualmaterial == green)
    305.                     {
    306.                         if (coloresV > coloresR && coloresV > coloresN && coloresV > colores0)
    307.                         {
    308.                             AddReward(0.001f);
    309.                         }
    310.                         else if (coloresV > coloresR && coloresV > coloresN && coloresV < colores0)
    311.                         {
    312.                             AddReward(0.0001f);
    313.                         }
    314.                         else if (coloresV > coloresR && coloresV < coloresN)
    315.                         {
    316.                             if (coloresR == 0)
    317.                             {
    318.                                 AddReward(-1f);
    319.                             }
    320.                             else
    321.                             {
    322.                                 AddReward(-0.1f);
    323.                             }
    324.                         }
    325.                         else if (coloresV < coloresR && coloresV > coloresN)
    326.                         {
    327.                             if (coloresN == 0)
    328.                             {
    329.                                 AddReward(-1f);
    330.                             }
    331.                             else
    332.                             {
    333.                                 AddReward(-0.1f);
    334.                             }
    335.                         }
    336.                         else if (coloresV < coloresR && coloresV < coloresN)
    337.                         {
    338.                             AddReward(-1f);
    339.                         }
    340.                     }
    341.                     else if (actualmaterial == red)
    342.                     {
    343.                         if (coloresR > coloresN && coloresR > coloresV && coloresR > colores0)
    344.                         {
    345.                             AddReward(0.001f);
    346.                         }
    347.                         else if (coloresR > coloresN && coloresR > coloresV && coloresR < colores0)
    348.                         {
    349.                             AddReward(0.0001f);
    350.                         }
    351.                         else if (coloresR > coloresN && coloresR < coloresV)
    352.                         {
    353.                             if (coloresN == 0)
    354.                             {
    355.                                 AddReward(-1f);
    356.                             }
    357.                             else
    358.                             {
    359.                                 AddReward(-0.1f);
    360.                             }
    361.                         }
    362.                         else if (coloresR < coloresN && coloresR > coloresV)
    363.                         {
    364.                             if (coloresV == 0)
    365.                             {
    366.                                 AddReward(-1f);
    367.                             }
    368.                             else
    369.                             {
    370.                                 AddReward(-0.1f);
    371.                             }
    372.                         }
    373.                         else if (coloresR < coloresN && coloresR < coloresV)
    374.                         {
    375.                             AddReward(-1f);
    376.                         }
    377.                     }
    378.                 }
    379.             }
    380.             else
    381.             {
    382.                 switch (color)
    383.                 {
    384.                     case 0:
    385.                         EstaMuerto();
    386.                         break;
    387.                     case 1:
    388.                         EstaNegro();
    389.                         break;
    390.                     case 2:
    391.                         EstaVerde();
    392.                         break;
    393.                     case 3:
    394.                         EstaRojo();
    395.                         break;
    396.                 }
    397.                 if (actualmaterial == dead)
    398.                 {
    399.                     AddReward(-10f);
    400.                 }
    401.                 else if (actualmaterial == black)
    402.                 {
    403.                     if (coloresN > coloresR && coloresN > coloresV && coloresN > colores0)
    404.                     {
    405.                         AddReward(0.001f);
    406.                     }
    407.                     else if (coloresN > coloresR && coloresN > coloresV && coloresN < colores0)
    408.                     {
    409.                         AddReward(0.0001f);
    410.                     }
    411.                     else if (coloresN > coloresR && coloresN < coloresV)
    412.                     {
    413.                         if (coloresR == 0)
    414.                         {
    415.                             AddReward(-1f);
    416.                         }
    417.                         else
    418.                         {
    419.                             AddReward(-0.1f);
    420.                         }
    421.                     }
    422.                     else if (coloresN < coloresR && coloresN > coloresV)
    423.                     {
    424.                         if (coloresV == 0)
    425.                         {
    426.                             AddReward(-1f);
    427.                         }
    428.                         else
    429.                         {
    430.                             AddReward(-0.1f);
    431.                         }
    432.                     }
    433.                     else if (coloresN < coloresR && coloresN < coloresV)
    434.                     {
    435.                         AddReward(-1f);
    436.                     }
    437.  
    438.                 }
    439.                 else if (actualmaterial == green)
    440.                 {
    441.                     if (coloresV > coloresR && coloresV > coloresN && coloresV > colores0)
    442.                     {
    443.                         AddReward(0.001f);
    444.                     }
    445.                     else if (coloresV > coloresR && coloresV > coloresN && coloresV < colores0)
    446.                     {
    447.                         AddReward(0.0001f);
    448.                     }
    449.                     else if (coloresV > coloresR && coloresV < coloresN)
    450.                     {
    451.                         if (coloresR == 0)
    452.                         {
    453.                             AddReward(-1f);
    454.                         }
    455.                         else
    456.                         {
    457.                             AddReward(-0.1f);
    458.                         }
    459.                     }
    460.                     else if (coloresV < coloresR && coloresV > coloresN)
    461.                     {
    462.                         if (coloresN == 0)
    463.                         {
    464.                             AddReward(-1f);
    465.                         }
    466.                         else
    467.                         {
    468.                             AddReward(-0.1f);
    469.                         }
    470.                     }
    471.                     else if (coloresV < coloresR && coloresV < coloresN)
    472.                     {
    473.                         AddReward(-1f);
    474.                     }
    475.                 }
    476.                 else if (actualmaterial == red)
    477.                 {
    478.                     if (coloresR > coloresN && coloresR > coloresV && coloresR > colores0)
    479.                     {
    480.                         AddReward(0.001f);
    481.                     }
    482.                     else if (coloresR > coloresN && coloresR > coloresV && coloresR < colores0)
    483.                     {
    484.                         AddReward(0.0001f);
    485.                     }
    486.                     else if (coloresR > coloresN && coloresR < coloresV)
    487.                     {
    488.                         if (coloresN == 0)
    489.                         {
    490.                             AddReward(-1f);
    491.                         }
    492.                         else
    493.                         {
    494.                             AddReward(-0.1f);
    495.                         }
    496.                     }
    497.                     else if (coloresR < coloresN && coloresR > coloresV)
    498.                     {
    499.                         if (coloresV == 0)
    500.                         {
    501.                             AddReward(-1f);
    502.                         }
    503.                         else
    504.                         {
    505.                             AddReward(-0.1f);
    506.                         }
    507.                     }
    508.                     else if (coloresR < coloresN && coloresR < coloresV)
    509.                     {
    510.                         AddReward(-1f);
    511.                     }
    512.                 }
    513.             }
    514.         }
    515.         //Que si no hay niguno del color, no hay de donde restar
    516.         //¿Sumarlos?
    517.         /*AddReward((entropiaN) / 10);
    518.         AddReward(entropiaV / 10);
    519.         AddReward(entropiaR / 10);*/
    520.         AddReward(entropiaC / 2);
    521.     }
    522.  
    523.     public int[] CuentaColores()
    524.     {
    525.         int coloresN = 0, coloresR = 0, coloresV = 0, colores0 = 0;
    526.         Ray cubeRayForward = new Ray(transform.position, Vector3.forward);
    527.         Ray cubeRayBack = new Ray(transform.position, Vector3.back);
    528.         Ray cubeRayRight = new Ray(transform.position, Vector3.right);
    529.         Ray cubeRayLeft = new Ray(transform.position, Vector3.left);
    530.         Ray cubeRayForwardRight = new Ray(transform.position, new Vector3(1, 0, 1));
    531.         Ray cubeRayForwardLeft = new Ray(transform.position, new Vector3(-1, 0, 1));
    532.         Ray cubeRayBackRight = new Ray(transform.position, new Vector3(1, 0, -1));
    533.         Ray cubeRayBackLeft = new Ray(transform.position, new Vector3(-1, 0, -1));
    534.         RaycastHit hit;
    535.         if (Physics.Raycast(cubeRayForward, out hit, 1))
    536.         {
    537.             if (hit.collider.tag == "cube")
    538.             {
    539.                 cubeForward = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    540.                 if (cubeForward == dead)
    541.                 {
    542.                     colores0++;
    543.                 }
    544.                 else if (cubeForward == black)
    545.                 {
    546.                     coloresN++;
    547.                 }
    548.                 else if (cubeForward == red)
    549.                 {
    550.                     coloresR++;
    551.                 }
    552.                 else if (cubeForward == green)
    553.                 {
    554.                     coloresV++;
    555.                 }
    556.             }
    557.         }
    558.         if (Physics.Raycast(cubeRayBack, out hit, 1))
    559.         {
    560.             if (hit.collider.tag == "cube")
    561.             {
    562.                 cubeBack = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    563.                 if (cubeBack == dead)
    564.                 {
    565.                     colores0++;
    566.                 }
    567.                 else if (cubeBack == black)
    568.                 {
    569.                     coloresN++;
    570.                 }
    571.                 else if (cubeBack == red)
    572.                 {
    573.                     coloresR++;
    574.                 }
    575.                 else if (cubeBack == green)
    576.                 {
    577.                     coloresV++;
    578.                 }
    579.             }
    580.         }
    581.         if (Physics.Raycast(cubeRayRight, out hit, 1))
    582.         {
    583.             if (hit.collider.tag == "cube")
    584.             {
    585.                 cubeRight = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    586.                 if (cubeRight == dead)
    587.                 {
    588.                     colores0++;
    589.                 }
    590.                 else if (cubeRight == black)
    591.                 {
    592.                     coloresN++;
    593.                 }
    594.                 else if (cubeRight == red)
    595.                 {
    596.                     coloresR++;
    597.                 }
    598.                 else if (cubeRight == green)
    599.                 {
    600.                     coloresV++;
    601.                 }
    602.             }
    603.         }
    604.         if (Physics.Raycast(cubeRayLeft, out hit, 1))
    605.         {
    606.             if (hit.collider.tag == "cube")
    607.             {
    608.                 cubeLeft = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    609.                 if (cubeLeft == dead)
    610.                 {
    611.                     colores0++;
    612.                 }
    613.                 else if (cubeLeft == black)
    614.                 {
    615.                     coloresN++;
    616.                 }
    617.                 else if (cubeLeft == red)
    618.                 {
    619.                     coloresR++;
    620.                 }
    621.                 else if (cubeLeft == green)
    622.                 {
    623.                     coloresV++;
    624.                 }
    625.             }
    626.         }
    627.         if (Physics.Raycast(cubeRayForwardRight, out hit, 2))
    628.         {
    629.  
    630.             if (hit.collider.tag == "cube")
    631.             {
    632.                 cubeForwardRight = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    633.                 if (cubeForwardRight == dead)
    634.                 {
    635.                     colores0++;
    636.                 }
    637.                 else if (cubeForwardRight == black)
    638.                 {
    639.                     coloresN++;
    640.                 }
    641.                 else if (cubeForwardRight == red)
    642.                 {
    643.                     coloresR++;
    644.                 }
    645.                 else if (cubeForwardRight == green)
    646.                 {
    647.                     coloresV++;
    648.                 }
    649.             }
    650.         }
    651.         if (Physics.Raycast(cubeRayForwardLeft, out hit, 2))
    652.         {
    653.             if (hit.collider.tag == "cube")
    654.             {
    655.                 cubeForwardLeft = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    656.                 if (cubeForwardLeft == dead)
    657.                 {
    658.                     colores0++;
    659.                 }
    660.                 else if (cubeForwardLeft == black)
    661.                 {
    662.                     coloresN++;
    663.                 }
    664.                 else if (cubeForwardLeft == red)
    665.                 {
    666.                     coloresR++;
    667.                 }
    668.                 else if (cubeForwardLeft == green)
    669.                 {
    670.                     coloresV++;
    671.                 }
    672.             }
    673.         }
    674.         if (Physics.Raycast(cubeRayBackRight, out hit, 2))
    675.         {
    676.             if (hit.collider.tag == "cube")
    677.             {
    678.                 cubeBackRight = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    679.                 if (cubeBackRight == dead)
    680.                 {
    681.                     colores0++;
    682.                 }
    683.                 else if (cubeBackRight == black)
    684.                 {
    685.                     coloresN++;
    686.                 }
    687.                 else if (cubeBackRight == red)
    688.                 {
    689.                     coloresR++;
    690.                 }
    691.                 else if (cubeBackRight == green)
    692.                 {
    693.                     coloresV++;
    694.                 }
    695.             }
    696.         }
    697.         if (Physics.Raycast(cubeRayBackLeft, out hit, 2))
    698.         {
    699.             if (hit.collider.tag == "cube")
    700.             {
    701.                 cubeBackLeft = hit.collider.gameObject.GetComponentInChildren<ConwayCube>().actualmaterial;
    702.                 if (cubeBackLeft == dead)
    703.                 {
    704.                     colores0++;
    705.                 }
    706.                 else if (cubeBackLeft == black)
    707.                 {
    708.                     coloresN++;
    709.                 }
    710.                 else if (cubeBackLeft == red)
    711.                 {
    712.                     coloresR++;
    713.                 }
    714.                 else if (cubeBackLeft == green)
    715.                 {
    716.                     coloresV++;
    717.                 }
    718.             }
    719.         }
    720.         int[] colores = new int[4];
    721.         colores[0] = colores0;
    722.         colores[1] = coloresN;
    723.         colores[2] = coloresV;
    724.         colores[3] = coloresR;
    725.         return colores;
    726.     }
    727.  
    728.     public void ChooseRandomColor()
    729.     {
    730.         if (UnityEngine.Random.Range(0, 24) == 3)
    731.         {
    732.             switch (UnityEngine.Random.Range(0, 3))
    733.             {
    734.                 case 0:
    735.                     EstaNegro();
    736.                     break;
    737.                 case 1:
    738.                     EstaVerde();
    739.                     break;
    740.                 case 2:
    741.                     EstaRojo();
    742.                     break;
    743.             }
    744.         }
    745.         else
    746.         {
    747.             EstaMuerto();
    748.         }
    749.  
    750.     }
    751.  
    752.     public override void OnEpisodeBegin()
    753.     {
    754.         ChooseRandomColor();
    755.         /*if (tipo==1)
    756.         {
    757.             EstaNegro();
    758.         }
    759.         else if (tipo==2)
    760.         {
    761.             EstaVerde();
    762.         }
    763.         else if (tipo==3)
    764.         {
    765.             EstaRojo();
    766.         }
    767.         else
    768.         {
    769.             EstaMuerto();
    770.         }*/
    771.     }
    772.  
    773.     public void FixedUpdate()
    774.     {
    775.         WaitTimeInference();
    776.         histograma = gameObject.GetComponentInParent<Histograma>();
    777.         int[] completo = histograma.getHistogramaCompleto();
    778.         int[] colores = CuentaColores();
    779.         colores0 = colores[0];
    780.         coloresN = colores[1];
    781.         coloresV = colores[2];
    782.         coloresR = colores[3];
    783.         coloresNT = completo[1];
    784.         coloresVT = completo[2];
    785.         coloresRT = completo[3];
    786.         entropiaC = getEntropyCompleta2(completo);
    787.         entropiaN = getEntropyVecinos(black);
    788.         entropiaV = getEntropyVecinos(green);
    789.         entropiaR = getEntropyVecinos(red);
    790.         //Debug.Log("EntropiaC: " + entropiaC + "EntropiaN: " + entropiaN+ "EntropiaV: " + entropiaV+"EntropiaR: " + entropiaR);
    791.     }
    792.  
    793.     void WaitTimeInference()
    794.     {
    795.         if (!Academy.Instance.IsCommunicatorOn)
    796.         {
    797.             RequestDecision();
    798.         }
    799.         else
    800.         {
    801.             if (m_TimeSinceDecision >= timeBetweenDecisionsAtInference)
    802.             {
    803.                 m_TimeSinceDecision = 0f;
    804.                 RequestDecision();
    805.             }
    806.             else
    807.             {
    808.                 m_TimeSinceDecision += Time.fixedDeltaTime;
    809.             }
    810.         }
    811.     }
    812.  
    813. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using MLAgentsExamples;
    4. using UnityEngine;
    5. using System.Linq;
    6. using TMPro;
    7.  
    8. public class Histograma : MonoBehaviour
    9. {
    10.  
    11.     public Material dead;
    12.     public Material black;
    13.     public Material green;
    14.     public Material red;
    15.     [Tooltip("The TextMeshPro text that shows the cumulative reward of the agent")]
    16.     public TextMeshPro cumulativeRewardText;
    17.  
    18.     public void Update()
    19.     {
    20.         float valor = 0;
    21.         ConwayCube[] lista = gameObject.GetComponentsInChildren<ConwayCube>();
    22.         foreach (ConwayCube cubo in lista)
    23.         {
    24.             valor += cubo.GetCumulativeReward();
    25.         }
    26.         valor /= 144;
    27.         cumulativeRewardText.text = valor.ToString("0.00");
    28.     }
    29.  
    30.     public List<int> getListaCompleto()
    31.     {
    32.         List<int> histograma = new List<int>();
    33.         ConwayCube[] lista = gameObject.GetComponentsInChildren<ConwayCube>();
    34.         foreach (ConwayCube cubo in lista)
    35.         {
    36.             if (cubo.actualmaterial == dead)
    37.             {
    38.                 histograma.Add(0);
    39.             }
    40.             else if (cubo.actualmaterial == black)
    41.             {
    42.                 histograma.Add(1);
    43.             }
    44.             else if (cubo.actualmaterial == green)
    45.             {
    46.                 histograma.Add(2);
    47.             }
    48.             else if (cubo.actualmaterial == red)
    49.             {
    50.                 histograma.Add(3);
    51.             }
    52.             else
    53.             {
    54.                 histograma.Add(4);
    55.             }
    56.         }
    57.         return histograma;
    58.     }
    59.     public int[] getHistogramaCompleto()
    60.     {
    61.         int[] histograma = getListaCompleto().ToArray();
    62.         int colores0 = 0, coloresR = 0, coloresV = 0, coloresN = 0;
    63.         foreach (int cubo in histograma)
    64.         {
    65.             switch (cubo)
    66.             {
    67.                 case 0: colores0++; break;
    68.                 case 1: coloresN++; break;
    69.                 case 2: coloresV++; break;
    70.                 case 3: coloresR++; break;
    71.                 case 4: break;
    72.             }
    73.         }
    74.         int[] mapa = new int[4];
    75.         mapa[0] = colores0;
    76.         mapa[1] = coloresN;
    77.         mapa[2] = coloresV;
    78.         mapa[3] = coloresR;
    79.         return mapa;
    80.     }
    81.     public int[] getHistogramaColor(Material color)
    82.     {
    83.         int colores0 = 0, coloresR = 0, coloresV = 0, coloresN = 0;
    84.         int[] histograma = new int[4];
    85.         ConwayCube[] lista = gameObject.GetComponentsInChildren<ConwayCube>();
    86.         foreach (ConwayCube cubo in lista)
    87.         {
    88.             if (cubo.actualmaterial == color)
    89.             {
    90.                 int[] colores = cubo.CuentaColores();
    91.                 colores0 += colores[0];
    92.                 coloresN += colores[1];
    93.                 coloresV += colores[2];
    94.                 coloresR += colores[3];
    95.             }
    96.         }
    97.         histograma[0] = colores0;
    98.         histograma[1] = coloresN;
    99.         histograma[2] = coloresV;
    100.         histograma[3] = coloresR;
    101.         return histograma;
    102.     }
    103.  
    104.     public ConwayCube[] getLista()
    105.     {
    106.         ConwayCube[] lista = gameObject.GetComponentsInChildren<ConwayCube>();
    107.         return lista;
    108.     }
    109.     public int getNumeroVecinos(Material color)
    110.     {
    111.         int[] histograma = getListaCompleto().ToArray();
    112.         int max = histograma.Length, num, valor = 0;
    113.         if (color == dead)
    114.         {
    115.             num = 0;
    116.         }
    117.         else if (color == black)
    118.         {
    119.             num = 1;
    120.         }
    121.         else if (color == green)
    122.         {
    123.             num = 2;
    124.         }
    125.         else if (color == red)
    126.         {
    127.             num = 3;
    128.         }
    129.         else
    130.         {
    131.             num = 4;
    132.         }
    133.         for (int i = 0; i < max; i++)
    134.         {
    135.             if (histograma[i] == num)
    136.             {
    137.                 valor++;
    138.             }
    139.         }
    140.         return valor;
    141.  
    142.     }
    143.     public float[] getHistogramaColorTrampas(Material color)
    144.     {
    145.         int colores0 = 0, coloresR = 0, coloresV = 0, coloresN = 0, num;
    146.         int[] histograma = getListaCompleto().ToArray();
    147.         int max = histograma.Length;
    148.         int[] contado = new int[max];
    149.         for (int i = 0; i < max; i++)
    150.         {
    151.             contado[i] = 0;
    152.         }
    153.         if (color == dead)
    154.         {
    155.             num = 0;
    156.         }
    157.         else if (color == black)
    158.         {
    159.             num = 1;
    160.         }
    161.         else if (color == green)
    162.         {
    163.             num = 2;
    164.         }
    165.         else if (color == red)
    166.         {
    167.             num = 3;
    168.         }
    169.         else
    170.         {
    171.             num = 4;
    172.         }
    173.         for (int i = 0; i < max; i++)
    174.         {
    175.             if (histograma[i] == num)
    176.             {
    177.                 if (i + 1 < max)
    178.                 {
    179.                     if (contado[i + 1] == 0)
    180.                     {
    181.                         contado[i + 1] = 1;
    182.                         switch (histograma[i + 1])
    183.                         {
    184.                             case 0: colores0++; break;
    185.                             case 1: coloresN++; break;
    186.                             case 2: coloresV++; break;
    187.                             case 3: coloresR++; break;
    188.                             case 4: break;
    189.                         }
    190.                     }
    191.                 }
    192.                 if (i + 11 < max)
    193.                 {
    194.                     if (i != 0 || i % 12 != 0)
    195.                     {
    196.                         if (contado[i + 11] == 0)
    197.                         {
    198.                             contado[i + 11] = 1;
    199.                             switch (histograma[i + 11])
    200.                             {
    201.                                 case 0: colores0++; break;
    202.                                 case 1: coloresN++; break;
    203.                                 case 2: coloresV++; break;
    204.                                 case 3: coloresR++; break;
    205.                                 case 4: break;
    206.                             }
    207.                         }
    208.                     }
    209.                 }
    210.                 if (i + 12 < max)
    211.                 {
    212.                     if (contado[i + 12] == 0)
    213.                     {
    214.                         contado[i + 12] = 1;
    215.                         switch (histograma[i + 12])
    216.                         {
    217.                             case 0: colores0++; break;
    218.                             case 1: coloresN++; break;
    219.                             case 2: coloresV++; break;
    220.                             case 3: coloresR++; break;
    221.                             case 4: break;
    222.                         }
    223.                     }
    224.                 }
    225.                 if (i + 13 < max)
    226.                 {
    227.                     if (i != 11 || (i + 1) % 12 != 0)
    228.                     {
    229.                         if (contado[i + 13] == 0)
    230.                         {
    231.                             contado[i + 13] = 1;
    232.                             switch (histograma[i + 13])
    233.                             {
    234.                                 case 0: colores0++; break;
    235.                                 case 1: coloresN++; break;
    236.                                 case 2: coloresV++; break;
    237.                                 case 3: coloresR++; break;
    238.                                 case 4: break;
    239.                             }
    240.                         }
    241.                     }
    242.                 }
    243.                 if (i - 1 >= 0)
    244.                 {
    245.                     if (contado[i - 1] == 0)
    246.                     {
    247.                         contado[i - 1] = 1;
    248.                         switch (histograma[i - 1])
    249.                         {
    250.                             case 0: colores0++; break;
    251.                             case 1: coloresN++; break;
    252.                             case 2: coloresV++; break;
    253.                             case 3: coloresR++; break;
    254.                             case 4: break;
    255.                         }
    256.                     }
    257.                 }
    258.                 if (i - 11 >= 0)
    259.                 {
    260.                     if (i != 11 || ((i + 1) % 12 != 0))
    261.                     {
    262.                         if (contado[i - 11] == 0)
    263.                         {
    264.                             contado[i - 11] = 1;
    265.                             switch (histograma[i - 11])
    266.                             {
    267.                                 case 0: colores0++; break;
    268.                                 case 1: coloresN++; break;
    269.                                 case 2: coloresV++; break;
    270.                                 case 3: coloresR++; break;
    271.                                 case 4: break;
    272.                             }
    273.                         }
    274.                     }
    275.                 }
    276.                 if (i - 12 >= 0)
    277.                 {
    278.                     if (contado[i - 12] == 0)
    279.                     {
    280.                         contado[i - 12] = 1;
    281.                         switch (histograma[i - 12])
    282.                         {
    283.                             case 0: colores0++; break;
    284.                             case 1: coloresN++; break;
    285.                             case 2: coloresV++; break;
    286.                             case 3: coloresR++; break;
    287.                             case 4: break;
    288.                         }
    289.                     }
    290.                 }
    291.                 if (i - 13 >= 0)
    292.                 {
    293.                     if (i != 0 || (i % 12 != 0))
    294.                     {
    295.  
    296.                         if (contado[i - 13] == 0)
    297.                         {
    298.                             contado[i - 13] = 1;
    299.                             switch (histograma[i - 13])
    300.                             {
    301.                                 case 0: colores0++; break;
    302.                                 case 1: coloresN++; break;
    303.                                 case 2: coloresV++; break;
    304.                                 case 3: coloresR++; break;
    305.                                 case 4: break;
    306.                             }
    307.                         }
    308.                     }
    309.                 }
    310.             }
    311.         }
    312.         float[] mapa = new float[4];
    313.         mapa[0] = colores0;
    314.         mapa[1] = coloresN;
    315.         mapa[2] = coloresV;
    316.         mapa[3] = coloresR;
    317.         return mapa;
    318.     }
    319.  
    320. }
     
    Last edited: Jun 6, 2020
  2. MrWetsnow

    MrWetsnow

    Joined:
    Jan 5, 2020
    Posts:
    60
    Certainly reenforcement learning is not limited to movement. I am not sure I understand completely what you are trying to achieve. What behavior do you want each agent to learn?

    The reward system you have is very complex. I think you should be able to start with +1 if alive, and -1 if dead. Or perhaps even just -1 if dead and 0 if alive. The placement of neighbors and their colors (and the optimal color to stay alive) is something the agents should learn on their own. You shouldn't have to spell that out.

    Also, are you using Discrete Space Type?

    var color = (int)vectorAction[0];

    If you are using Continuous Space Type (which is the default), the input into OnActionReceived() is in the range of -1 to 1. Which is probably not what you want.
     
  3. mateolopezareal

    mateolopezareal

    Joined:
    Jun 4, 2020
    Posts:
    54
    I want that the agent know his environment, and the information about the cubes with the same race. I want to achieve a replica of how will each race respond to the environment (if they are going to maintain as a group or maybe go bigger), for reaching this I will have in a future to play with the rewards. But for now I just want to know if my agents can learn from the environment. (using an agent to each cube instead of making the whole graphic an agent).

    I have already done some runs with simple values and the graphs looks good, the agent learns to stay in a color (meaning not dead).
    Screenshot 2020-06-05 at 00.50.59.png

    The vector action is discrete. I think that for this project it is more simple to use the discrete Space Type, right?

    I am also doing all the reward things to try to get together as much of the same race as possible. I will like to have three typer os rewards, the one of the agent, that makes it to not be dead and to gather cubes with the same race; the one of the environment that looks to have as much distribution of races as possible (I mean NO only one race alive; and the one of the race, that has its personal politics (this one is not implemented yet, and I am in doubt about it).


    Also, I am doing the training now adding the entropy histogram as a reward, and there is something that there is something that bothers me. In the training there is a point where it finds a maximum reward but then as the training continues the reward decreases a and then stays at that value.
    The maximum value is when it makes the entropy almost 1, so there are all the races alive and with almost the same amount. But then even though it has less reward it learns to be all of the same colour and it stucks with that. This kind of graph (not exactly this one):
    Screenshot 2020-06-05 at 01.08.07.png


    I hope someone can help me.

    P.S.: In my last post I did say: "If I put the entropy thing, and give as observation the color (the number) all the cubes in the matrix. my reward does not increase, it stays linear." I just solve it It was just a that dumb thing.

     

    Attached Files:

  4. MrWetsnow

    MrWetsnow

    Joined:
    Jan 5, 2020
    Posts:
    60
    In all honesty it sounds like what you are implementing, to my understanding, doesn't require reenforcement learning. Are you trying to mimic something like the Conway game of life (based on the names of your variables)?

    For learning, it helps to have a specific goal that your agents need to achieve. It's not clear (to me at least) what the goal that each of your agents are trying to achieve. From your description you seem to want to implement automata.

    Can you clearly state what your agent should learn how to do? Some example of that are:

    "Learn how to throw a ball into a basket"
    "Learn how to keep away from dangerous areas"
    "Learn how to catch another agent"

    You say you have many agents, but you are wanting some sort of an emergent behavior based on simple rules that sound very much like automata.
     
  5. mateolopezareal

    mateolopezareal

    Joined:
    Jun 4, 2020
    Posts:
    54
    The first idea was to make like a Conway game of life, but with multiple race and each race will have a different goal (one prefer to invade, one prefer to survive as much as possible). But right now, has nothing to do.

    Learn how to survive in the environment. Thats it. But I do not want just a +1 if alive, -1 if dead; I want to see interactions between races. The main goal to achieve is to see that by setting some parameters to each race, how each race interacts with the environment.
    So right now, the state will go more to a "Learn how to survive in the environment, by grouping all together (but not letting only one race alive". (that is what I am implementing with the rewards I think)
    I do not see this exercise as automata, just because the way it will have to make decisions is not even similar. There is only one rule, the other rules are not implemented, the agent has to learn it itself.