Skip to content
Snippets Groups Projects
Commit c7d189cf authored by Jana Eltayeb El Rafei's avatar Jana Eltayeb El Rafei
Browse files

ajout_UsagerLambda

parent 7758dfdd
No related branches found
No related tags found
1 merge request!14Merge v2
......@@ -10,7 +10,7 @@ import (
)
func main() {
s := simulation.NewSimulation(1, -1, 600*time.Second)
s := simulation.NewSimulation(6, -1, 600*time.Second)
//go simulation.StartAPI(s)
go func() {
for {
......
......@@ -11,10 +11,8 @@ import (
//"log"
"math/rand"
"math"
alg "metrosim/internal/algorithms"
"time"
"sort"
)
type Action int64
......@@ -570,88 +568,7 @@ func (ag *Agent) findNearestExit() (alg.Coord){
return nearest
}
func (ag *Agent) findNearestGates(gates []alg.Coord) []Gate {
var gateDistances []Gate
// Calcul de la distance pour chaque porte
for _, gate := range gates {
dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
gateDistances = append(gateDistances, Gate{Position: gate, Distance: float64(dist)})
}
// Tri des Coords par distance
sort.Slice(gateDistances, func(i, j int) bool {
return gateDistances[i].Distance < gateDistances[j].Distance
})
return gateDistances
}
// Normalise les valeurs d'un ensemble de portes
func normalizeGates(gates []Gate) ([]Gate, float64, float64) {
var minAgents, maxAgents float64 = math.MaxFloat64, 0
var minDistance, maxDistance float64 = math.MaxFloat64, 0
// Trouver les valeurs max et min pour la normalisation
for _, gate := range gates {
if gate.NbAgents > maxAgents {
maxAgents = gate.NbAgents
}
if gate.NbAgents < minAgents {
minAgents = gate.NbAgents
}
if gate.Distance > maxDistance {
maxDistance = gate.Distance
}
if gate.Distance < minDistance {
minDistance = gate.Distance
}
}
// Normaliser les valeurs
d_agt := (maxAgents - minAgents)
if d_agt == 0 {
d_agt = 1.0
}
d_dist := (maxDistance - minDistance)
if d_dist == 0 {
d_dist = 1.0
}
fmt.Println("[normalizeGates] d_dist : ",d_dist)
for i := range gates {
gates[i].NbAgents = (gates[i].NbAgents - minAgents) / d_agt
//fmt.Println("[normalizeGates] gates[i].Distance : ",gates[i].Distance)
//fmt.Println("[normalizeGates] minDistance : ",minDistance)
//fmt.Println("[normalizeGates] d_dist : ",d_dist)
gates[i].Distance = (gates[i].Distance - minDistance) / d_dist
}
return gates, float64(maxAgents - minAgents), maxDistance - minDistance
}
func (ag *Agent) findBestGate(gates []alg.Coord) alg.Coord {
gatesDistances := make([]Gate, len(gates))
for i, gate := range gates {
dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
nbAgents := float64(ag.env.getNbAgentsAround(gate))
gatesDistances[i] = Gate{Position: gate, Distance: float64(dist), NbAgents: nbAgents}
}
fmt.Println("[findBestGate] gates non normalisé : ",gatesDistances)
normalizedGates, _, _ := normalizeGates(gatesDistances)
fmt.Println("[findBestGate] gates normalisé : ",normalizedGates)
var bestGate Gate
lowestScore := 2.0 // Puisque la somme des scores normalisés ne peut pas dépasser 2
for _, gate := range normalizedGates {
score := float64(gate.NbAgents) + gate.Distance
if score < lowestScore {
lowestScore = score
bestGate = gate
}
}
return bestGate.Position
}
func findMetro(env *Environment, gateToFind *alg.Coord) *Metro {
......
package simulation
//ajouter liste des agents déjà controllés
/*
Le controleur se déplace aléatoirement dans la station pendant un certain temps
et controle les agents qui se trouvent devant lui si ils ne sont pas déjà controllés par un autre controleur,
si l'agent est un fraudeur alors il est expulsé, sinon il est arreté pendant un certain temps
*/
import (
"fmt"
......@@ -10,13 +14,6 @@ import (
alg "metrosim/internal/algorithms"
)
/*
Je suppose que l'id du controleur est de format "Cont + un chiffre"
Exemple : "Cont1"
et l'id du l'agent est de format "Agent + un chiffre"
Exemple : "Agent1"
*/
type Controleur struct {
req *Request // requete reçue par le controleur
faceCase string // chaine de caractère qui contient l'id de l'agent qui se trouve devant le controleur, exemple : "Agent1", "Fraudeur1", "X" ,etc.
......@@ -24,14 +21,12 @@ type Controleur struct {
isExpired bool // true si le controleur est expiré, false sinon
}
func (c *Controleur) Percept(ag *Agent) {
//initialiser le faceCase en fonction de la direction de l'agent
c.faceCase = ag.getFaceCase()
switch {
// comportement par défaut (comportement agent Lambda)
case ag.request != nil: //verifier si l'agent est communiqué par un autre agent (A VOIR SI IL EXISTE DEJA UN AGENT QUI COMMUNIQUE AVEC LE CONTROLEUR)
case ag.request != nil: //verifier si l'agent est communiqué par un autre agent
//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
c.req = ag.request
default:
......@@ -46,29 +41,29 @@ func (c *Controleur) Percept(ag *Agent) {
func (c *Controleur) Deliberate(ag *Agent) {
// Verifier si la case devant lui contient un agent ou un fraudeur
// Créer l'expression régulière
regexAgent := `^Agent\d+$` // \d+ correspond à un ou plusieurs chiffres
//regexAgent := `^Agent\d+$` // \d+ correspond à un ou plusieurs chiffres
regexFraudeur := `^Fraudeur\d+$`
existAgt := existAgent(c.faceCase) // true si l'agent existe dans la case en face , false sinon
// Vérifier si la valeur de faceCase ne correspond pas au motif
matchedAgt, err1 := regexp.MatchString(regexAgent, c.faceCase)
matchedFraud, err2 := regexp.MatchString(regexFraudeur, c.faceCase)
//matchedAgt, err1 := regexp.MatchString(regexAgent, c.faceCase)
matchedFraud, err := regexp.MatchString(regexFraudeur, c.faceCase)
//fmt.Println("faceCase : ", c.faceCase)
//fmt.Println("matchedAgt : ", matchedAgt)
if err1 != nil || err2 != nil {
fmt.Println("Erreur lors de l'analyse de la regex :", err1, err2)
if err!= nil {
fmt.Println("Erreur lors de l'analyse de la regex :",err)
return
} else {
if matchedAgt && ag.env.controlledAgents[AgentID(c.faceCase)] == false { // si l'agent devant le controleur est un agent et qu'il n'a pas encore été controlé
//fmt.Println("L'agent ", c.face, " a été détecté par le controleur")
ag.decision = Stop // arreter l'agent devant lui
} else if matchedFraud && !ag.env.controlledAgents[AgentID(c.faceCase)] {
if matchedFraud && !ag.env.controlledAgents[AgentID(c.faceCase)] {
ag.decision = Expel // virer l'agent devant lui
//sinon comportement par défaut (comportement de l'usager lambda)
}else if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si l'agent est arrivé à sa destination et qu'il est sur une sortie
}else if existAgt && !ag.env.controlledAgents[AgentID(c.faceCase)] { // si l'agent devant le controleur est un agent et qu'il n'a pas encore été controlé
//fmt.Println("L'agent ", c.face, " a été détecté par le controleur")
ag.decision = Stop // arreter l'agent
}else if ag.position == ag.destination && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si le controleur est arrivé à sa destination et qu'il est sur une sortie
//fmt.Println(ag.id, "disappear")
ag.decision = Disappear
} else if ag.stuck{ // si l'agent est bloqué
} else if ag.stuck{ // si le controleur est bloqué
ag.decision = Wait
}else {
ag.decision = Move
......@@ -97,7 +92,7 @@ func (c *Controleur) Act(ag *Agent) {
case Disappear:
RemoveAgent(&ag.env.station, ag)
default : //Expel ou Wait
case Expel, Stop : //Expel ou Stop
agt_face_id := AgentID(c.faceCase) //id de l'agent qui se trouve devant le controleur
//fmt.Print("L'agent ", agt_face_id, " a été expulsé\n")
ag.env.agentsChan[agt_face_id] <- *NewRequest(ag.env.agentsChan[ag.id], ag.decision) // envoie la decision du controleur à l'agent qui se trouve devant lui
......@@ -106,11 +101,11 @@ func (c *Controleur) Act(ag *Agent) {
func (c *Controleur) randomDestination(ag *Agent) alg.Coord {
rand.Seed(time.Now().UnixNano()) // le générateur de nombres aléatoires
randomRow := rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
randomCol := rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
randomRow := rand.Intn(len(ag.env.station[0])) // Génère un entier aléatoire entre 0 et 19
randomCol := rand.Intn(len(ag.env.station[1])) // Génère un entier aléatoire entre 0 et 19
for ag.env.station[randomRow][randomCol] != "_" {
randomRow = rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
randomCol = rand.Intn(20) // Génère un entier aléatoire entre 0 et 19
randomRow = rand.Intn(len(ag.env.station[0])) // Génère un entier aléatoire entre 0 et 19
randomCol = rand.Intn(len(ag.env.station[1])) // Génère un entier aléatoire entre 0 et 19
}
return alg.Coord{randomRow, randomCol}
}
......
......@@ -47,7 +47,7 @@ func (metro *Metro) Start() {
metro.printMetro()
}
if refTime.Add(metro.frequency).Before(time.Now()) {
metro.dropUsers()
//metro.dropUsers()
metro.way.openGates()
metro.pickUpUsers()
metro.way.closeGates()
......
package simulation
/*
L'agent à Mobilité Reduite cherche la porte du metro la plus proche de lui
*/
import (
"fmt"
......@@ -6,6 +9,7 @@ import (
"math/rand"
"time"
alg "metrosim/internal/algorithms"
"sort"
)
......@@ -16,7 +20,7 @@ type MobiliteReduite struct {
func (mr *MobiliteReduite) Percept(ag *Agent) {
mr.once.Do(func(){mr.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
mr.once.Do(func(){mr.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel à la fonction Percept()
switch {
case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
fmt.Printf("Requete recue par l'agent mR : %d \n", ag.request.decision)
......@@ -101,7 +105,24 @@ func (mr *MobiliteReduite) Act(ag *Agent) {
*/
func (mr *MobiliteReduite)setUpDestination(ag *Agent){
choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
dest_porte := (ag.findNearestGates(ag.env.metros[choix_voie].way.gates))
dest_porte := (mr.findNearestGates(ag, ag.env.metros[choix_voie].way.gates))
//fmt.Println("[MobiliteReduite, setUpDestination] dest_porte = ",dest_porte)
ag.destination = dest_porte[0].Position
}
func (mr *MobiliteReduite) findNearestGates(ag *Agent, gates []alg.Coord) []Gate {
var gateDistances []Gate
// Calcul de la distance pour chaque porte
for _, gate := range gates {
dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
gateDistances = append(gateDistances, Gate{Position: gate, Distance: float64(dist)})
}
// Tri des Coords par distance
sort.Slice(gateDistances, func(i, j int) bool {
return gateDistances[i].Distance < gateDistances[j].Distance
})
return gateDistances
}
\ No newline at end of file
......@@ -140,17 +140,25 @@ func NewSimulation(agentCount int, maxStep int, maxDuration time.Duration) (simu
// création de l'agent
syncChan := make(chan int)
ag := &Agent{}
//ag := NewAgent(id, &simu.env, syncChan, time.Duration(time.Second), 0, true, Coord{0, 8 + i%2}, Coord{0, 8 + i%2}, &UsagerLambda{}, Coord{0, 8 + i%2}, Coord{12 - 4*(i%2), 18 - 15*(i%2)})
//ag := NewAgent(id, &simu.env, syncChan, 1000, 0, true, &UsagerLambda{}, Coord{18, 4}, Coord{0, 8}, 2, 1)
//ag := &Agent{}
/*
id := fmt.Sprintf("Agent%d", i)
ag := NewAgent(id, &simu.env, syncChan, 400, 0, true, &UsagerLambda{}, alg.Coord{0, 28}, alg.Coord{8, 5}, 1, 1)
*/
id := fmt.Sprintf("Cont%d", i)
//NewAgent(id string, env *Environment, syncChan chan int, vitesse time.Duration, force int, politesse bool, behavior Behavior, departure, destination Coord, width, height int)
ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &Controleur{}, alg.Coord{0, 28}, alg.Coord{0, 9}, 1, 1)
/*
if i%2 == 0 { //Type Agent
id := fmt.Sprintf("MR%d", i)
id := fmt.Sprintf("Cont%d", i)
//NewAgent(id string, env *Environment, syncChan chan int, vitesse time.Duration, force int, politesse bool, behavior Behavior, departure, destination Coord, width, height int)
ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &UsagerLambda{}, alg.Coord{49, 32}, alg.Coord{0, 9}, 2, 1)
ag = NewAgent(id, &simu.env, syncChan, 200, 0, true, &Controleur{}, alg.Coord{0, 28}, alg.Coord{0, 9}, 2, 1)
} else { // Type Controleur
//id := fmt.Sprintf("Controleur%d", i)
id := fmt.Sprintf("Agent%d", i)
......@@ -256,11 +264,13 @@ func (simu *Simulation) Print() {
for i := 0; i < 20; i++ {
for j := 0; j < 50; j++ {
element := simu.env.station[i][j]
if len(element) > 1 {
fmt.Print(element[len(element)-1:] + " ") // Afficher le premier caractère si la longueur est supérieure à 1
} else {
fmt.Print(element + " ")
}
//fmt.Print(element[len(element)-1:] + " ") // Afficher le premier caractère si la longueur est supérieure à 1
fmt.Print(element[0:1] + " ")
} else {
fmt.Print(element + " ")
}
}
fmt.Println()
}
......
......@@ -15,7 +15,7 @@ type UsagerLambda struct {
}
func (ul *UsagerLambda) Percept(ag *Agent) {
ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
//ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
switch {
case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
......@@ -84,9 +84,3 @@ func (ul *UsagerLambda) Act(ag *Agent) {
}
}
func (ul *UsagerLambda)setUpDestination(ag *Agent){
choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
dest_porte := (ag.findBestGate(ag.env.metros[choix_voie].way.gates))
ag.destination = dest_porte
}
\ No newline at end of file
package simulation
/*
Agent qui se dirige vers la porte la plus proche sans trop de monde (bon rapport monde/proximité )
*/
import (
"fmt"
"math/rand"
alg "metrosim/internal/algorithms"
"time"
"sync"
"math"
)
type UsagerNormal struct {
req *Request // requete recue par l'agent lambda
once sync.Once
}
func (ul *UsagerNormal) Percept(ag *Agent) {
ul.once.Do(func(){ul.setUpDestination(ag)}) // la fonction setUp est executé à la premiere appel de la fonction Percept()
switch {
case ag.request != nil: //verifier si l'agent est communiqué par un autre agent, par exemple un controleur lui a demandé de s'arreter
//print("Requete recue par l'agent lambda : ", ag.request.decision, "\n")
ul.req = ag.request
default:
ag.stuck = ag.isStuck()
if ag.stuck {
return
}
}
}
func (ul *UsagerNormal) Deliberate(ag *Agent) {
//fmt.Println("[AgentLambda Deliberate] decision :", ul.req.decision)
if (ul.req != nil ) {
if ul.req.decision == Stop{
ag.decision = Wait
ul.req = nil //demande traitée
return
} else if ul.req.decision == Expel { // cette condition est inutile car l'usager lambda ne peut pas etre expulsé , elle est nécessaire pour les agents fraudeurs
//fmt.Println("[AgentLambda, Deliberate] Expel")
ag.decision = Expel
ul.req = nil //demande traitée
return
}else if ul.req.decision == Disappear {
ag.decision = Disappear
return
}else if ul.req.decision == Wait {
ag.decision = Wait
}else if ul.req.decision == EnterMetro {
ag.decision = EnterMetro
}
}else if (ag.position != ag.departure && ag.position == ag.destination) && (ag.isOn[ag.position] == "W" || ag.isOn[ag.position] == "S") { // si l'agent est arrivé à sa destination et qu'il est sur une sortie
//fmt.Println(ag.id, "disappear")
ag.decision = Disappear
} else if ag.stuck{ // si l'agent est bloqué
ag.decision = Wait
}else {
ag.decision = Move
}
}
func (ul *UsagerNormal) Act(ag *Agent) {
//fmt.Println("[AgentLambda Act] decision :",ag.decision)
if ag.decision == Move {
ag.MoveAgent()
} else if ag.decision == Wait {
n := rand.Intn(2) // temps d'attente aléatoire
time.Sleep(time.Duration(n) * time.Second)
} else if ag.decision == Disappear {
RemoveAgent(&ag.env.station, ag)
} else if ag.decision == EnterMetro {
fmt.Println("[UsagerNormal, Act] EnterMetro")
RemoveAgent(&ag.env.station, ag)
ul.req.demandeur <- *NewRequest(ag.env.agentsChan[ag.id], ACK)
} else if ag.decision == Expel {
//fmt.Println("[AgentLambda, Act] Expel")
ag.destination = ag.findNearestExit()
//fmt.Println("[AgentLambda, Act] destination = ",ag.destination)
ag.env.controlledAgents[ag.id] = true
ag.path = make([]alg.Node, 0)
ag.MoveAgent()
} else {
// nothing to do
}
}
func (ul *UsagerNormal)setUpDestination(ag *Agent){
choix_voie := rand.Intn(2) // choix de la voie de métro aléatoire
dest_porte := (ul.findBestGate(ag, ag.env.metros[choix_voie].way.gates))
ag.destination = dest_porte
}
func (ul *UsagerNormal) findBestGate(ag *Agent, gates []alg.Coord) alg.Coord {
gatesDistances := make([]Gate, len(gates))
for i, gate := range gates {
dist := alg.Abs(ag.position[0]-gate[0]) + alg.Abs(ag.position[1]-gate[1])
nbAgents := float64(ag.env.getNbAgentsAround(gate))
gatesDistances[i] = Gate{Position: gate, Distance: float64(dist), NbAgents: nbAgents}
}
fmt.Println("[findBestGate] gates non normalisé : ",gatesDistances)
normalizedGates, _, _ := normalizeGates(gatesDistances)
fmt.Println("[findBestGate] gates normalisé : ",normalizedGates)
var bestGate Gate
lowestScore := 2.0 // Puisque la somme des scores normalisés ne peut pas dépasser 2
for _, gate := range normalizedGates {
score := float64(gate.NbAgents) + gate.Distance
if score < lowestScore {
lowestScore = score
bestGate = gate
}
}
return bestGate.Position
}
// Normalise les valeurs d'un ensemble de portes
func normalizeGates(gates []Gate) ([]Gate, float64, float64) {
var minAgents, maxAgents float64 = math.MaxFloat64, 0
var minDistance, maxDistance float64 = math.MaxFloat64, 0
// Trouver les valeurs max et min pour la normalisation
for _, gate := range gates {
if gate.NbAgents > maxAgents {
maxAgents = gate.NbAgents
}
if gate.NbAgents < minAgents {
minAgents = gate.NbAgents
}
if gate.Distance > maxDistance {
maxDistance = gate.Distance
}
if gate.Distance < minDistance {
minDistance = gate.Distance
}
}
// Normaliser les valeurs
d_agt := (maxAgents - minAgents)
if d_agt == 0 {
d_agt = 1.0
}
d_dist := (maxDistance - minDistance)
if d_dist == 0 {
d_dist = 1.0
}
fmt.Println("[normalizeGates] d_dist : ",d_dist)
for i := range gates {
gates[i].NbAgents = (gates[i].NbAgents - minAgents) / d_agt
//fmt.Println("[normalizeGates] gates[i].Distance : ",gates[i].Distance)
//fmt.Println("[normalizeGates] minDistance : ",minDistance)
//fmt.Println("[normalizeGates] d_dist : ",d_dist)
gates[i].Distance = (gates[i].Distance - minDistance) / d_dist
}
return gates, float64(maxAgents - minAgents), maxDistance - minDistance
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment