Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Agriterix
simulator
Commits
d1f67ce0
Commit
d1f67ce0
authored
Jul 27, 2021
by
Dumoulin Nicolas
Browse files
NEW Population dynamics implementation with initialization in Generator
parent
ae32b4f5
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/main/java/fr/inrae/agriterix/generator/Generator.java
View file @
d1f67ce0
package
fr.inrae.agriterix.generator
;
import
com.thoughtworks.xstream.XStream
;
import
fr.inrae.agriterix.simulator.CulturalPractice
;
import
fr.inrae.agriterix.simulator.Farm
;
import
fr.inrae.agriterix.simulator.Farmer
;
...
...
@@ -16,18 +17,19 @@ import fr.inrae.agriterix.simulator.Unit;
import
fr.inrae.agriterix.simulator.dynamics.Dynamics
;
import
fr.inrae.agriterix.simulator.dynamics.FlowDynamics
;
import
fr.inrae.agriterix.simulator.dynamics.MarketDynamics
;
import
fr.inrae.agriterix.simulator.dynamics.PopulationDynamics
;
import
fr.inrae.agriterix.simulator.dynamics.PopulationDynamics
ByAgeClass
;
import
fr.inrae.agriterix.simulator.dynamics.ProductionDynamics
;
import
fr.inrae.agriterix.simulator.dynamics.transmission.TransmissionTendancy
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
org.geotools.data.FileDataStore
;
import
org.geotools.data.FileDataStoreFinder
;
import
org.geotools.data.simple.SimpleFeatureCollection
;
...
...
@@ -38,50 +40,54 @@ import umontreal.ssj.rng.MRG32k3a;
import
umontreal.ssj.rng.RandomStreamBase
;
public
class
Generator
{
/**
* Build a list of farmers with given initial distribution of ages (starting from 18 yo).
* Build a list of farmers with given initial distribution of ages (starting
* from 18 yo).
*
* @ages array of effectives for each ages
* @area the GeoArea instance for initializing the farmers
* @popTotal the total number of farmers to build.
*/
private
static
List
<
Farmer
>
generate_farmers
(
int
[]
ages
,
GeoArea
area
,
int
popTotal
)
{
int
sum
=
Arrays
.
stream
(
ages
).
sum
();
double
[]
probas
=
Arrays
.
stream
(
ages
).
asDoubleStream
().
map
(
i
->
i
/
sum
).
toArray
();
int
[]
population
=
Arrays
.
stream
(
probas
).
mapToInt
(
i
->
(
int
)
Math
.
round
(
i
*
popTotal
)).
toArray
();
double
[]
probas
=
Arrays
.
stream
(
ages
).
asDoubleStream
().
map
(
i
->
i
/
sum
).
toArray
();
int
[]
population
=
Arrays
.
stream
(
probas
).
mapToInt
(
i
->
(
int
)
Math
.
round
(
i
*
popTotal
)).
toArray
();
List
<
Farmer
>
farmers
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
population
.
length
;
i
++)
{
for
(
int
j
=
0
;
j
<
population
[
i
];
j
++)
{
Farm
farm
=
new
Farm
(
area
);
farmers
.
add
(
new
Farmer
(
i
+
18
,
farm
,
i
));
farmers
.
add
(
new
Farmer
(
i
+
18
,
farm
,
i
));
}
}
return
farmers
;
}
/**
* Randomly pick and remove a farmer in the given list
*
* @param rng the RNG to use
* @param farmers the initial list of farmers
* @param id_expl the ID to set to the picked farmer.
* @return The farmer
*/
private
static
Farmer
pickFarmer
(
RandomStreamBase
rng
,
List
<
Farmer
>
farmers
,
int
id_expl
)
{
Farmer
farmer
=
farmers
.
remove
(
rng
.
nextInt
(
0
,
farmers
.
size
()
-
1
));
Farmer
farmer
=
farmers
.
remove
(
rng
.
nextInt
(
0
,
farmers
.
size
()
-
1
));
farmer
.
setId
(
id_expl
);
return
farmer
;
}
/**
* Generates patches in the given geo area.
*
* @param rng The RNG used for picking the farmer
* @param shapefile The shapefile containing the patches
* @param area The initial area where put the patches
* @param farmers The list of farmers to assign on the patches (unmodified)
* @return the list of products produced by the patches
* @throws IOException
* @throws IOException
*/
public
static
List
<
Product
>
generate_patches
(
RandomStreamBase
rng
,
String
shapefile
,
GeoArea
area
,
List
<
Farmer
>
farmers
)
throws
IOException
{
public
static
List
<
Product
>
generate_patches
(
RandomStreamBase
rng
,
String
shapefile
,
GeoArea
area
,
List
<
Farmer
>
farmers
)
throws
IOException
{
Map
<
String
,
Product
>
products
=
new
HashMap
<>();
Map
<
Integer
,
Farmer
>
farmersID
=
new
HashMap
<>();
List
<
Patch
>
patches
=
new
ArrayList
<>();
...
...
@@ -128,9 +134,10 @@ public class Generator {
/**
* Creates a dummy flow for a given product
*
* @param product
* @param maximum
* @return
* @return
*/
private
static
Flow
createFlow
(
Product
product
,
float
maximum
)
{
Stocks
quantities1
=
new
Stocks
();
...
...
@@ -146,6 +153,25 @@ public class Generator {
return
new
Flow
(
inputs1
,
quantities1
,
outputs1
,
ratio1
,
"Commerce"
);
}
public
static
Map
<
String
,
Map
<
String
,
Double
>>
createTransMatrix
(
List
<
Product
>
products
)
throws
IOException
{
// for test minimal
XStream
xStream
=
new
XStream
();
XStream
.
setupDefaultSecurity
(
xStream
);
xStream
.
allowTypesByRegExp
(
new
String
[]{
".*"
});
Map
<
String
,
Map
<
String
,
Double
>>
transitions
=
new
ConcurrentHashMap
<>();
for
(
int
i
=
0
;
i
<
products
.
size
();
i
++)
{
Map
<
String
,
Double
>
transitionsP
=
new
ConcurrentHashMap
<>();
for
(
int
j
=
0
;
j
<
products
.
size
();
j
++)
{
transitionsP
.
put
(
products
.
get
(
j
).
getLabel
(),
i
==
j
?
0.9
:
0.1
/
(
products
.
size
()
-
1
));
}
transitions
.
put
(
products
.
get
(
i
).
getLabel
(),
transitionsP
);
}
return
transitions
;
}
public
static
void
main
(
String
[]
args
)
throws
IOException
{
// farmers ages from MSA for France, starting at 18 year old
int
[]
ages_2018
=
{
1
,
76
,
268
,
579
,
1079
,
1493
,
1973
,
2432
,
3059
,
3592
,
4236
,
4717
,
5440
,
5904
,
6419
,
6945
,
7574
,
7847
,
8414
,
8704
,
8992
,
8782
,
8821
,
9069
,
9236
,
9741
,
10569
,
11458
,
12058
,
12623
,
12927
,
13351
,
13637
,
14446
,
15461
,
16145
,
17113
,
17017
,
17163
,
17660
,
17350
,
17190
,
16147
,
12294
,
10037
,
6746
,
5509
,
4670
,
3720
,
2830
,
2401
,
2181
,
1856
,
1584
,
1209
,
790
,
665
,
595
,
496
,
390
,
333
,
346
,
303
,
246
,
238
,
205
,
201
,
175
,
146
,
125
,
92
,
82
,
75
,
55
,
50
,
36
,
36
,
26
,
25
,
18
,
13
,
10
,
11
};
...
...
@@ -157,7 +183,10 @@ public class Generator {
geoarea
.
getFlows
().
add
(
createFlow
(
product
,
100
.
f
));
}
List
<
Dynamics
>
dynamics
=
new
ArrayList
<>();
//dynamics.add(new PopulationDynamics());
dynamics
.
add
(
new
PopulationDynamicsByAgeClass
(
5.31966309
e
-
04
,
3.02391767
e
+
01
,
3.89377418
e
-
01
,
7.46514412
e
+
00
,
4.27098464
e
+
01
,
1.58988450
e
-
01
,
new
TransmissionTendancy
(
0.5
,
0.5
,
3
,
createTransMatrix
(
products
))
));
dynamics
.
add
(
new
ProductionDynamics
());
dynamics
.
add
(
new
MarketDynamics
());
dynamics
.
add
(
new
FlowDynamics
());
...
...
src/main/java/fr/inrae/agriterix/simulator/Patch.java
View file @
d1f67ce0
...
...
@@ -76,6 +76,10 @@ public class Patch {
return
production
;
}
public
void
setProduction
(
Production
production
)
{
this
.
production
=
production
;
}
/**
* Set the farm where this patch and add the patch into the farm.
*
...
...
src/main/java/fr/inrae/agriterix/simulator/SimulationContext.java
View file @
d1f67ce0
...
...
@@ -115,4 +115,38 @@ public class SimulationContext {
return
NormalGen
.
nextDouble
(
randomStream
,
m
,
std
);
}
/**
* Picks out randomly an object in the given list.
*
* @param <T>
* @param objects
* @return
*/
public
<
T
>
T
nextObject
(
List
<
T
>
objects
)
{
return
nextObject
(
objects
,
false
);
}
/**
* Picks out randomly an object in the given list.
*
* @param <T>
* @param objects
* @param remove if true, the returned object is removed from the list
* @return null if the list is null or empty.
*/
public
<
T
>
T
nextObject
(
List
<
T
>
objects
,
boolean
remove
)
{
if
(
objects
==
null
||
objects
.
isEmpty
())
{
return
null
;
}
if
(
remove
)
{
return
objects
.
remove
(
nextInt
(
0
,
objects
.
size
()
-
1
));
}
else
{
return
objects
.
get
(
nextInt
(
0
,
objects
.
size
()
-
1
));
}
}
public
boolean
nextBoolean
()
{
return
nextDouble
()
<
0.5
;
}
}
src/main/java/fr/inrae/agriterix/simulator/dynamics/PopulationDynamicsByAgeClass.java
View file @
d1f67ce0
package
fr.inrae.agriterix.simulator.dynamics
;
import
fr.inrae.agriterix.simulator.*
;
import
fr.inrae.agriterix.simulator.dynamics.transmission.TransmissionStrategy
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
...
...
@@ -8,11 +10,24 @@ import java.util.stream.IntStream;
import
umontreal.ssj.probdist.BetaDist
;
@Deprecated
public
class
PopulationDynamicsByAgeClass
extends
Dynamics
{
private
double
amplitude
,
drop_x
,
mu
,
v
,
r_threshold
,
r_factor
;
private
TransmissionStrategy
transmission
;
public
PopulationDynamicsByAgeClass
()
{
}
public
PopulationDynamicsByAgeClass
(
double
amplitude
,
double
drop_x
,
double
mu
,
double
v
,
double
r_threshold
,
double
r_factor
,
TransmissionStrategy
transmission
)
{
this
.
amplitude
=
amplitude
;
this
.
drop_x
=
drop_x
;
this
.
mu
=
mu
;
this
.
v
=
v
;
this
.
r_threshold
=
r_threshold
;
this
.
r_factor
=
r_factor
;
this
.
transmission
=
transmission
;
}
@Override
public
void
process
(
SimulationContext
context
,
List
<
GeoArea
>
geoAreas
,
List
<
Farmer
>
farmers
,
Flow
global
,
Parameters
parameters
,
TimeUnit
timeUnit
)
{
...
...
@@ -24,18 +39,27 @@ public class PopulationDynamicsByAgeClass extends Dynamics {
int
popSum
=
IntStream
.
of
(
ageclasses
).
sum
();
double
alpha
=
mu
*
v
;
double
beta
=
(
1
-
mu
)
*
v
;
int
i
=
0
;
int
[]
installations
=
IntStream
.
range
(
0
,
ageclasses
.
length
).
map
(
idx
->
(
int
)
Math
.
round
(
ageclasses
[
idx
]
*
popSum
*
amplitude
*
BetaDist
.
density
(
alpha
,
beta
,
idx
/
drop_x
))
).
toArray
();
List
<
Integer
>
installationsAges
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
installations
.
length
;
i
++)
{
for
(
int
j
=
0
;
j
<
installations
[
i
];
j
++)
{
installationsAges
.
add
(
getAge
(
i
));
}
}
int
[]
retirements
=
IntStream
.
range
(
0
,
ageclasses
.
length
).
map
(
idx
->
idx
>=
r_threshold
?
(
int
)
Math
.
round
(
r_factor
*
ageclasses
[
idx
])
:
0
).
toArray
();
// TODO apply installations and retirements
throw
new
UnsupportedOperationException
(
"Not supported yet."
);
//To change body of generated methods, choose Tools | Templates.
}
transmission
.
process
(
context
,
geoAreas
,
farmers
,
installationsAges
,
retirements
);
}
private
int
getAge
(
int
ageclass
)
{
return
ageclass
+
18
;
}
@Override
public
void
initLogger
()
{
logger
=
new
DynamicsLogger
(
this
.
getClass
().
getSimpleName
(),
super
.
timeStamp
);
...
...
src/main/java/fr/inrae/agriterix/simulator/dynamics/transmission/TransmissionStrategy.java
0 → 100644
View file @
d1f67ce0
package
fr.inrae.agriterix.simulator.dynamics.transmission
;
import
fr.inrae.agriterix.simulator.Farmer
;
import
fr.inrae.agriterix.simulator.GeoArea
;
import
fr.inrae.agriterix.simulator.SimulationContext
;
import
java.util.List
;
public
interface
TransmissionStrategy
{
public
void
process
(
SimulationContext
context
,
List
<
GeoArea
>
geoAreas
,
List
<
Farmer
>
farmers
,
List
<
Integer
>
installationsAges
,
int
[]
retirements
);
}
src/main/java/fr/inrae/agriterix/simulator/dynamics/transmission/TransmissionTendancy.java
0 → 100644
View file @
d1f67ce0
package
fr.inrae.agriterix.simulator.dynamics.transmission
;
import
fr.inrae.agriterix.simulator.Farmer
;
import
fr.inrae.agriterix.simulator.GeoArea
;
import
fr.inrae.agriterix.simulator.Patch
;
import
fr.inrae.agriterix.simulator.Product
;
import
fr.inrae.agriterix.simulator.SimulationContext
;
import
fr.inrae.agriterix.simulator.Unit
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
public
class
TransmissionTendancy
implements
TransmissionStrategy
{
// Is the transmission realized with only one successor?
// TODO better with a distribution on number of successors
private
double
singleSuccessorProba
;
// Is the transmission realized with an existant farmer (instead of a new)
private
double
existantSuccessorProba
;
private
int
maxSuccessors
;
private
Map
<
String
,
Map
<
String
,
Double
>>
transitionMatrix
;
public
TransmissionTendancy
()
{
}
public
TransmissionTendancy
(
double
singleSuccessorProba
,
double
existantSuccessorProba
,
int
maxSuccessors
,
Map
<
String
,
Map
<
String
,
Double
>>
transitionMatrix
)
{
this
.
singleSuccessorProba
=
singleSuccessorProba
;
this
.
existantSuccessorProba
=
existantSuccessorProba
;
this
.
maxSuccessors
=
maxSuccessors
;
this
.
transitionMatrix
=
transitionMatrix
;
}
@Override
public
void
process
(
SimulationContext
context
,
List
<
GeoArea
>
geoAreas
,
List
<
Farmer
>
farmers
,
List
<
Integer
>
installationsAges
,
int
[]
retirements
)
{
// retrieving farmers that will retire
List
<
Farmer
>
retiredFarmers
=
new
ArrayList
<>();
// TODO useless?
for
(
int
i
=
0
;
i
<
retirements
.
length
;
i
++)
{
int
nbRetired
=
retirements
[
i
];
final
int
age
=
i
;
List
<
Farmer
>
ageIFarmers
=
farmers
.
stream
().
filter
(
f
->
f
.
getAge
()
==
age
).
collect
(
Collectors
.
toList
());
for
(
int
j
=
0
;
j
<
nbRetired
;
j
++)
{
final
Farmer
retiredFarmer
=
context
.
nextObject
(
ageIFarmers
,
true
);
farmers
.
remove
(
retiredFarmer
);
retiredFarmers
.
add
(
retiredFarmer
);
if
(
context
.
nextDouble
()
<=
singleSuccessorProba
)
{
processSuccessor
(
installationsAges
,
context
,
farmers
,
retiredFarmer
);
}
else
{
// multiple successors
List
<
Farmer
>
successors
=
new
ArrayList
<>();
for
(
int
k
=
0
;
k
<
context
.
nextInt
(
2
,
maxSuccessors
);
k
++)
{
//successors.add(context.nextObject(farmers));
Farmer
existingFarmer
=
context
.
nextObject
(
successors
,
false
);
existingFarmer
=
context
.
nextObject
(
successors
,
false
);
processSuccessor
(
installationsAges
,
context
,
farmers
,
retiredFarmer
);
// new farmer
}
}
}
}
}
private
void
processSuccessor
(
List
<
Integer
>
installationsAges
,
SimulationContext
context
,
List
<
Farmer
>
farmers
,
final
Farmer
retiredFarmer
)
{
// single successor
if
(
installationsAges
.
isEmpty
()
||
context
.
nextDouble
()
<=
existantSuccessorProba
)
{
// existant farmer
Farmer
successor
=
context
.
nextObject
(
farmers
,
false
);
patchTransition
(
retiredFarmer
,
successor
,
context
);
}
else
{
// new farmer
Farmer
newFarmer
=
new
Farmer
(
context
.
nextObject
(
installationsAges
,
true
),
retiredFarmer
.
getFarm
(),
context
.
setIdFarmer
());
patchTransition
(
retiredFarmer
,
newFarmer
,
context
);
}
}
private
void
patchTransition
(
final
Farmer
retiredFarmer
,
Farmer
successor
,
SimulationContext
context
)
{
for
(
Patch
patch
:
retiredFarmer
.
getFarm
().
getPatches
())
{
if
(
retiredFarmer
.
getFarm
()
!=
successor
.
getFarm
())
{
patch
.
setFarm
(
successor
.
getFarm
());
}
String
product
=
context
.
nextMapObjectWithDistributionInKeysBis
(
transitionMatrix
.
get
(
patch
.
getProduction
().
getProduct
().
getLabel
())
);
if
(!
product
.
equals
(
patch
.
getProduction
().
getProduct
().
getLabel
()))
{
// TODO correctly fetch existing product or good initialization
patch
.
setProduction
(
new
Patch
.
Production
(
new
Product
(
product
,
Unit
.
Kg
),
0
.
f
));
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment