1
0
forked from s425077/PotatoPlan

working ML, RC0.1

This commit is contained in:
BOTLester 2020-05-10 01:38:08 +02:00
parent f475f5bab5
commit 34a0e8bd3a
18 changed files with 603 additions and 281 deletions

View File

@ -88,7 +88,10 @@
<Compile Include="Sources\Crops\CropType.cs" />
<Compile Include="Sources\Crops\CropTypesHolder.cs" />
<Compile Include="Sources\Crops\SoilProperties.cs" />
<Compile Include="Sources\ML\Engine.cs" />
<Compile Include="Sources\Objects\DayNightCycle.cs" />
<Compile Include="Sources\Objects\Fertilizer.cs" />
<Compile Include="Sources\Objects\FertilizerHolder.cs" />
<Compile Include="Sources\Objects\HandleRotation.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>

View File

@ -11,6 +11,7 @@ class CropTypes
public string[] soilType = new string[3];
public int[] Times = new int[3];
public string CropName;
public float Temparature;
public float Humidity;
public float Moisture;

View File

@ -16,6 +16,7 @@ class CropTypesHolder
cropTypes[0].soilType[0] = "None";
cropTypes[0].soilType[1] = null;
cropTypes[0].soilType[2] = null;
cropTypes[0].CropName = "None";
cropTypes[0].Temparature = 0f;
cropTypes[0].Humidity = 0f;
cropTypes[0].Moisture = 0f;
@ -28,12 +29,13 @@ class CropTypesHolder
cropTypes[1].soilType[0] = "Sandy";
cropTypes[1].soilType[1] = null;
cropTypes[1].soilType[2] = null;
cropTypes[1].CropName = "Barley";
cropTypes[1].Temparature = 30.1f;
cropTypes[1].Humidity = 59.0f;
cropTypes[1].Moisture = 41.7f;
cropTypes[1].Nitrogen = 25 + 12.6f;
cropTypes[1].Potassium = 14 + 5.3f;
cropTypes[1].Phosphorous = 30 + 26.0f;
cropTypes[1].Nitrogen = 35 + 12.6f;
cropTypes[1].Potassium = 20 + 5.3f;
cropTypes[1].Phosphorous = 32 + 26.0f;
// Cotton
@ -44,24 +46,26 @@ class CropTypesHolder
cropTypes[2].Times[1] = 4;
cropTypes[2].soilType[2] = "Loamy";
cropTypes[2].Times[2] = 3;
cropTypes[2].CropName = "Cotton";
cropTypes[2].Temparature = 30.4f;
cropTypes[2].Humidity = 59.6f;
cropTypes[2].Moisture = 63.2f;
cropTypes[2].Nitrogen = 25 + 16.4f;
cropTypes[2].Potassium = 14 + 3.3f;
cropTypes[2].Phosphorous = 30 + 23.8f;
cropTypes[2].Nitrogen = 35 + 16.4f;
cropTypes[2].Potassium = 20 + 3.3f;
cropTypes[2].Phosphorous = 32 + 23.8f;
// Ground Nuts
cropTypes[3] = new CropTypes();
cropTypes[3].soilType[0] = "Red";
cropTypes[3].soilType[1] = null;
cropTypes[3].soilType[2] = null;
cropTypes[3].CropName = "Ground Nuts";
cropTypes[3].Temparature = 30.1f;
cropTypes[3].Humidity = 59.1f;
cropTypes[3].Moisture = 33.1f;
cropTypes[3].Nitrogen = 25 + 23.3f;
cropTypes[3].Potassium = 14 + 2.0f;
cropTypes[3].Phosphorous = 30 + 21.6f;
cropTypes[3].Nitrogen = 35 + 23.3f;
cropTypes[3].Potassium = 20 + 2.0f;
cropTypes[3].Phosphorous = 32 + 21.6f;
// Maize
@ -69,12 +73,13 @@ class CropTypesHolder
cropTypes[4].soilType[0] = "Sandy";
cropTypes[4].soilType[1] = null;
cropTypes[4].soilType[2] = null;
cropTypes[4].CropName = "Maize";
cropTypes[4].Temparature = 29.0f;
cropTypes[4].Humidity = 57.3f;
cropTypes[4].Moisture = 42.2f;
cropTypes[4].Nitrogen = 25 + 18.3f;
cropTypes[4].Potassium = 14 + 5.7f;
cropTypes[4].Phosphorous = 30 + 18.7f;
cropTypes[4].Nitrogen = 35 + 18.3f;
cropTypes[4].Potassium = 20 + 5.7f;
cropTypes[4].Phosphorous = 32 + 18.7f;
// Millets
cropTypes[5] = new CropTypes();
@ -83,48 +88,52 @@ class CropTypesHolder
cropTypes[5].soilType[1] = "Black";
cropTypes[5].Times[0] = 4;
cropTypes[5].soilType[2] = null;
cropTypes[5].CropName = "Millets";
cropTypes[5].Temparature = 29.5f;
cropTypes[5].Humidity = 57.3f;
cropTypes[5].Moisture = 38.5f;
cropTypes[5].Nitrogen = 25 + 23.2f;
cropTypes[5].Potassium = 14 + 0.1f;
cropTypes[5].Phosphorous = 30 + 14.4f;
cropTypes[5].Nitrogen = 35 + 23.2f;
cropTypes[5].Potassium = 20 + 0.1f;
cropTypes[5].Phosphorous = 32 + 14.4f;
//Oil Seeds
cropTypes[6] = new CropTypes();
cropTypes[6].soilType[0] = "Black";
cropTypes[6].soilType[1] = null;
cropTypes[6].soilType[2] = null;
cropTypes[6].CropName = "Oil Seeds";
cropTypes[6].Temparature = 30.3f;
cropTypes[6].Humidity = 59.1f;
cropTypes[6].Moisture = 32.1f;
cropTypes[6].Nitrogen = 25 + 19.0f;
cropTypes[6].Potassium = 14 + 2.3f;
cropTypes[6].Phosphorous = 30 + 17.3f;
cropTypes[6].Nitrogen = 35 + 19.0f;
cropTypes[6].Potassium = 20 + 2.3f;
cropTypes[6].Phosphorous = 32 + 17.3f;
//Paddys
cropTypes[7] = new CropTypes();
cropTypes[7].soilType[0] = "Clayey";
cropTypes[7].soilType[1] = null;
cropTypes[7].soilType[2] = null;
cropTypes[7].CropName = "Paddys";
cropTypes[7].Temparature = 31.2f;
cropTypes[7].Humidity = 60.4f;
cropTypes[7].Moisture = 41.5f;
cropTypes[7].Nitrogen = 25 + 20.8f;
cropTypes[7].Potassium = 14 + 3.7f;
cropTypes[7].Phosphorous = 30 + 16.3f;
cropTypes[7].Nitrogen = 35 + 20.8f;
cropTypes[7].Potassium = 20 + 3.7f;
cropTypes[7].Phosphorous = 32 + 16.3f;
//Pulses
cropTypes[8] = new CropTypes();
cropTypes[8].soilType[0] = "Clayey";
cropTypes[8].soilType[1] = null;
cropTypes[8].soilType[2] = null;
cropTypes[8].CropName = "Pulses";
cropTypes[8].Temparature = 27.8f;
cropTypes[8].Humidity = 54.9f;
cropTypes[8].Moisture = 34.1f;
cropTypes[8].Nitrogen = 25 + 18.4f;
cropTypes[8].Potassium = 14 + 4.2f;
cropTypes[8].Phosphorous = 30 + 17.5f;
cropTypes[8].Nitrogen = 35 + 18.4f;
cropTypes[8].Potassium = 20 + 4.2f;
cropTypes[8].Phosphorous = 32 + 17.5f;
//Sugarcane
cropTypes[9] = new CropTypes();
@ -133,12 +142,13 @@ class CropTypesHolder
cropTypes[9].soilType[1] = "Black";
cropTypes[9].Times[0] = 4;
cropTypes[9].soilType[2] = null;
cropTypes[9].CropName = "Sugarcane";
cropTypes[9].Temparature = 30.0f;
cropTypes[9].Humidity = 58.6f;
cropTypes[9].Moisture = 51.2f;
cropTypes[9].Nitrogen = 25 + 14.6f;
cropTypes[9].Potassium = 14 + 4.2f;
cropTypes[9].Phosphorous = 30 + 17.6f;
cropTypes[9].Nitrogen = 35 + 14.6f;
cropTypes[9].Potassium = 20 + 4.2f;
cropTypes[9].Phosphorous = 32 + 17.6f;
//Tobacco
@ -146,12 +156,13 @@ class CropTypesHolder
cropTypes[10].soilType[0] = "Red";
cropTypes[10].soilType[1] = null;
cropTypes[10].soilType[2] = null;
cropTypes[10].CropName = "Tobacco";
cropTypes[10].Temparature = 31.9f;
cropTypes[10].Humidity = 62.4f;
cropTypes[10].Moisture = 31.6f;
cropTypes[10].Nitrogen = 25 + 19.1f;
cropTypes[10].Potassium = 14 + 4.9f;
cropTypes[10].Phosphorous = 30 + 19.3f;
cropTypes[10].Nitrogen = 35 + 19.1f;
cropTypes[10].Potassium = 20 + 4.9f;
cropTypes[10].Phosphorous = 32 + 19.3f;
//Wheat
@ -159,12 +170,13 @@ class CropTypesHolder
cropTypes[11].soilType[0] = "Loamy";
cropTypes[11].soilType[1] = null;
cropTypes[11].soilType[2] = null;
cropTypes[11].CropName = "Wheat";
cropTypes[11].Temparature = 33.1f;
cropTypes[11].Humidity = 63.8f;
cropTypes[11].Moisture = 50.0f;
cropTypes[11].Nitrogen = 25 + 23.3f;
cropTypes[11].Potassium = 14 + 2.9f;
cropTypes[11].Phosphorous = 30 + 14.4f;
cropTypes[11].Nitrogen = 35 + 23.3f;
cropTypes[11].Potassium = 20 + 2.9f;
cropTypes[11].Phosphorous = 32 + 14.4f;
}

View File

@ -50,6 +50,22 @@ class Crops
return soilProperties;
}
public void Fertilize(Fertilizer fertilizer)
{
soilProperties.Nitrogen += fertilizer.Nitrogen;
soilProperties.Phosphorous += fertilizer.Phosphorus;
soilProperties.Potassium += fertilizer.Potassium;
}
public bool isSaturated()
{
if (soilProperties.Nitrogen > 52 && (soilProperties.Phosphorous > 57 || soilProperties.Potassium > 25))
return true;
if (soilProperties.Phosphorous > 57 && soilProperties.Potassium > 25)
return true;
return false;
}
public float getCropTimer()
{
return Timer;
@ -194,6 +210,11 @@ class Crops
return housePos;
}
public bool belowCapacity()
{
return ((int)(soilProperties.Nitrogen + soilProperties.Potassium + soilProperties.Phosphorous)) < soilProperties.Capacity;
}
public float getProductionRate(CropTypes Sample)
{
ProductionRate = 1;
@ -205,9 +226,6 @@ class Crops
ProductionRate = ProductionRate + (ProductionRate * compareToDatset(soilProperties.Humidity, Sample.Humidity));
min = Math.Min(compareToDatset(soilProperties.Phosphorous, Sample.Phosphorous), Math.Min(compareToDatset(soilProperties.Potassium, Sample.Potassium), compareToDatset(soilProperties.Nitrogen, Sample.Nitrogen)));
ProductionRate = ProductionRate + (ProductionRate * min);
//ProductionRate = ProductionRate + (ProductionRate * compareToDatset(soilProperties.Phosphorous, Sample.Phosphorous));
//ProductionRate = ProductionRate + (ProductionRate * compareToDatset(soilProperties.Potassium, Sample.Potassium));
//ProductionRate = ProductionRate + (ProductionRate * compareToDatset(soilProperties.Nitrogen, Sample.Nitrogen));
if (ProductionRate < 0)
{
ProductionRate = 0;

View File

@ -76,6 +76,7 @@ class Farm
}
else if (crops[x, y].getStatus() == 2)
{
crops[x, y].setStatus(3);
crops[x, y].setCropTimer();
}

View File

@ -20,6 +20,7 @@ class SoilProperties
public float NitrogenDegradeRate = 1.0f - (1.0f/55 * 40);
public float PotassiumDegradeRate = 1.0f - (1.0f/28 * 23);
public float PhosphorousDegradeRate = 1.0f - (1.0f/60 * 37);
public int Capacity = 150;
public void setSoilProperties()
{

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ML;
static class Engine
{
private static MLContext mlContext = new MLContext(seed: 1);
private static PredictionEngine<ModelInput, ModelOutput> PredictionEngine = MLModel.CreateEngine();
public static string PredictFertilizer(Crops crop, CropTypes cropTypes)
{
ModelInput modelInput = new ModelInput
{
Temperature = crop.getSoilProperties().Temperature,
Humidity = crop.getSoilProperties().Humidity,
Moisture = crop.getSoilProperties().Moisture,
Soil_Type = crop.getSoilProperties().soilType,
Crop_Type = cropTypes.CropName,
Nitrogen = crop.getSoilProperties().Nitrogen,
Potassium = crop.getSoilProperties().Potassium,
Phosporous = crop.getSoilProperties().Phosphorous
};
return PredictionEngine.Predict(modelInput).Prediction;
}
}

View File

@ -5,39 +5,38 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.ML.Data;
namespace Game1.Sources.ML
class BigModelInput
{
class BigModelInput
{
[ColumnName("Ca"), LoadColumn(0)]
public float Ca { get; set; }
[ColumnName("Ca"), LoadColumn(0)]
public float Ca { get; set; }
[ColumnName("Mg"), LoadColumn(1)]
public float Mg { get; set; }
[ColumnName("Mg"), LoadColumn(1)]
public float Mg { get; set; }
[ColumnName("K"), LoadColumn(2)]
public float K { get; set; }
[ColumnName("K"), LoadColumn(2)]
public float K { get; set; }
[ColumnName("S"), LoadColumn(3)]
public float S { get; set; }
[ColumnName("S"), LoadColumn(3)]
public float S { get; set; }
[ColumnName("N"), LoadColumn(4)]
public float N { get; set; }
[ColumnName("N"), LoadColumn(4)]
public float N { get; set; }
[ColumnName("Lime"), LoadColumn(5)]
public float Lime { get; set; }
[ColumnName("Lime"), LoadColumn(5)]
public float Lime { get; set; }
[ColumnName("C"), LoadColumn(6)]
public float C { get; set; }
[ColumnName("C"), LoadColumn(6)]
public float C { get; set; }
[ColumnName("P"), LoadColumn(7)]
public float P { get; set; }
[ColumnName("P"), LoadColumn(7)]
public float P { get; set; }
[ColumnName("Moisture"), LoadColumn(8)]
public float Moisture { get; set; }
[ColumnName("Moisture"), LoadColumn(8)]
public float Moisture { get; set; }
[ColumnName("Class"), LoadColumn(9)]
public float Class { get; set; }
[ColumnName("Class"), LoadColumn(9)]
public float Class { get; set; }
}
}

View File

@ -5,11 +5,9 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.ML.Data;
namespace Game1.Sources.ML
class BigModelOutput
{
class BigModelOutput
{
[ColumnName("PredictedLabel")]
public float Prediction { get; set; }
}
[ColumnName("PredictedLabel")]
public float Prediction { get; set; }
}

View File

@ -6,35 +6,34 @@ using System.Threading.Tasks;
using Microsoft.ML;
using Microsoft.ML.Data;
namespace Game1.Sources.ML
class ModelInput
{
class ModelInput
{
[ColumnName("Temperature"), LoadColumn(0)]
public float Temperature { get; set; }
[ColumnName("Temperature"), LoadColumn(0)]
public float Temperature { get; set; }
[ColumnName("Humidity"), LoadColumn(1)]
public float Humidity { get; set; }
[ColumnName("Humidity"), LoadColumn(1)]
public float Humidity { get; set; }
[ColumnName("Moisture"), LoadColumn(2)]
public float Moisture { get; set; }
[ColumnName("Moisture"), LoadColumn(2)]
public float Moisture { get; set; }
[ColumnName("Soil_Type"), LoadColumn(3)]
public String Soil_Type { get; set; }
[ColumnName("Soil_Type"), LoadColumn(3)]
public String Soil_Type { get; set; }
[ColumnName("Crop_Type"), LoadColumn(4)]
public String Crop_Type { get; set; }
[ColumnName("Crop_Type"), LoadColumn(4)]
public String Crop_Type { get; set; }
[ColumnName("Nitrogen"), LoadColumn(5)]
public float Nitrogen { get; set; }
[ColumnName("Nitrogen"), LoadColumn(5)]
public float Nitrogen { get; set; }
[ColumnName("Potassium"), LoadColumn(6)]
public float Potassium { get; set; }
[ColumnName("Potassium"), LoadColumn(6)]
public float Potassium { get; set; }
[ColumnName("Phosphorous"), LoadColumn(7)]
public float Phosporous { get; set; }
[ColumnName("Phosphorous"), LoadColumn(7)]
public float Phosporous { get; set; }
[ColumnName("Fertilizer_Name"), LoadColumn(8)]
public String Fertilizer_Name { get; set; }
}
[ColumnName("Fertilizer_Name"), LoadColumn(8)]
public String Fertilizer_Name { get; set; }
}

View File

@ -5,13 +5,11 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.ML.Data;
namespace Game1.Sources.ML
class ModelOutput
{
class ModelOutput
{
[ColumnName("PredictedLabel")]
public String Prediction { get; set; }
//public float[] Score { get; set; }
}
[ColumnName("PredictedLabel")]
public String Prediction { get; set; }
//public float[] Score { get; set; }
}

View File

@ -7,163 +7,162 @@ using Microsoft.ML;
using Microsoft.ML.Data;
using Microsoft.ML.Trainers.LightGbm;
namespace Game1.Sources.ML
class MLModel
{
class MLModel
private static MLContext mlContext = new MLContext(seed: 1);
private static string path = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/Fertilizer_Prediction.csv";
private static string modelpath = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/MLmodel";
private static string report = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/report";
private static string pathBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/BigFertPredict.csv";
private static string modelpathBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/MLmodelBig";
private static string reportBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/report_BigModel";
// Loading data, creatin and saving ML model for smaller dataset (100)
public static void CreateModel()
{
private static MLContext mlContext = new MLContext(seed: 1);
private static string path = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/Fertilizer_Prediction.csv";
private static string modelpath = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/MLmodel";
private static string report = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/report";
private static string pathBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/BigFertPredict.csv";
private static string modelpathBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/MLmodelBig";
private static string reportBig = "C:/Users/Oskar/source/repos/PotatoPlanFinal/Game1/Content/ML/report_BigModel";
// Loading data, creatin and saving ML model for smaller dataset (100)
public static void CreateModel()
{
IDataView trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
path: path,
hasHeader: true,
separatorChar: ',',
allowQuoting: true,
allowSparse: false);
ModelInput sample = mlContext.Data.CreateEnumerable<ModelInput>(trainingDataView, false).ElementAt(0);
ITransformer MLModel = BuildAndTrain(mlContext, trainingDataView, sample, report);
SaveModel(mlContext, MLModel, modelpath, trainingDataView.Schema);
}
// ... for bigger dataset (1600)
public static void CreateBigModel()
{
IDataView trainingDataView = mlContext.Data.LoadFromTextFile<BigModelInput>(
path: pathBig,
hasHeader: true,
separatorChar: ',',
allowQuoting: true,
allowSparse: false);
BigModelInput sample = mlContext.Data.CreateEnumerable<BigModelInput>(trainingDataView, false).ElementAt(0);
ITransformer MLModel = BuildAndTrain(mlContext, trainingDataView, sample, reportBig);
SaveModel(mlContext, MLModel, modelpathBig, trainingDataView.Schema);
}
// Building and training ML model, very small dataset (100 entries)
public static ITransformer BuildAndTrain(MLContext mLContext, IDataView trainingDataView, ModelInput sample, string reportPath)
{
var options = new LightGbmMulticlassTrainer.Options
{
MaximumBinCountPerFeature = 8,
LearningRate = 0.00025,
NumberOfIterations = 40000,
NumberOfLeaves = 10,
LabelColumnName = "Fertilizer_NameF",
FeatureColumnName = "Features",
Booster = new DartBooster.Options()
{
MaximumTreeDepth = 10
}
};
var pipeline = mlContext.Transforms
.Text.FeaturizeText("Soil_TypeF", "Soil_Type")
.Append(mlContext.Transforms.Text.FeaturizeText("Crop_TypeF", "Crop_Type"))
.Append(mlContext.Transforms.Concatenate("Features", "Temperature", "Humidity", "Moisture", "Soil_TypeF", "Crop_TypeF", "Nitrogen", "Potassium", "Phosphorous"))
.Append(mLContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Conversion.MapValueToKey("Fertilizer_NameF", "Fertilizer_Name"), TransformerScope.TrainTest)
.AppendCacheCheckpoint(mLContext)
.Append(mLContext.MulticlassClassification.Trainers.LightGbm(options))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
Evaluate(mlContext, trainingDataView, pipeline, 10, reportPath, "Fertilizer_NameF");
ITransformer MLModel = pipeline.Fit(trainingDataView);
return MLModel;
}
//Building and training ML model, moderate size dataset (1600 entries)
public static ITransformer BuildAndTrain(MLContext mLContext, IDataView trainingDataView, BigModelInput sample, string reportPath)
{
var options = new LightGbmMulticlassTrainer.Options
{
MaximumBinCountPerFeature = 10,
LearningRate = 0.001,
NumberOfIterations = 10000,
NumberOfLeaves = 12,
LabelColumnName = "ClassF",
FeatureColumnName = "Features",
Booster = new DartBooster.Options()
{
MaximumTreeDepth = 12
}
};
var pipeline = mlContext.Transforms
.Concatenate("Features", "Ca", "Mg", "K", "S", "N", "Lime", "C", "P", "Moisture")
.Append(mLContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Conversion.MapValueToKey("ClassF", "Class"), TransformerScope.TrainTest)
.AppendCacheCheckpoint(mLContext)
.Append(mLContext.MulticlassClassification.Trainers.LightGbm(options))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
Evaluate(mlContext, trainingDataView, pipeline, 8, reportPath, "ClassF");
ITransformer MLModel = pipeline.Fit(trainingDataView);
return MLModel;
}
public static ITransformer TrainModel(MLContext mlContext, IDataView trainingDataView, IEstimator<ITransformer> trainingPipeline)
{
ITransformer model = trainingPipeline.Fit(trainingDataView);
return model;
}
// Evaluate and save results to a text file
public static void Evaluate(MLContext mlContext, IDataView trainingDataView, IEstimator<ITransformer> trainingPipeline, int folds, string reportPath, string labelColumnName)
{
var crossVal = mlContext.MulticlassClassification.CrossValidate(trainingDataView, trainingPipeline, numberOfFolds: folds, labelColumnName: labelColumnName);
var metricsInMultipleFolds = crossVal.Select(r => r.Metrics);
var MicroAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy);
var LogLossValues = metricsInMultipleFolds.Select(m => m.LogLoss);
var LogLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction);
string MicroAccuracyAverage = MicroAccuracyValues.Average().ToString("0.######");
string LogLossAvg = LogLossValues.Average().ToString("0.######");
string LogLossReductionAvg = LogLossReductionValues.Average().ToString("0.######");
var report = File.CreateText(reportPath);
report.Write("Micro Accuracy: " + MicroAccuracyAverage +'\n'+ "LogLoss Average: " + LogLossAvg +'\n'+ "LogLoss Reduction: " + LogLossReductionAvg, 0, 0);
report.Flush();
report.Close();
}
public static void SaveModel(MLContext mlContext, ITransformer Model, string modelPath, DataViewSchema modelInputSchema)
{
mlContext.Model.Save(Model, modelInputSchema, modelPath);
}
public static ITransformer LoadModel(bool isBig)
{
if (isBig)
return mlContext.Model.Load(modelpathBig, out DataViewSchema inputSchema);
else
return mlContext.Model.Load(modelpath, out DataViewSchema inputSchema);
}
public static Microsoft.ML.PredictionEngine<ModelInput, ModelOutput> CreateEngine()
{
ITransformer mlModel = LoadModel(false);
return mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
}
IDataView trainingDataView = mlContext.Data.LoadFromTextFile<ModelInput>(
path: path,
hasHeader: true,
separatorChar: ',',
allowQuoting: true,
allowSparse: false);
ModelInput sample = mlContext.Data.CreateEnumerable<ModelInput>(trainingDataView, false).ElementAt(0);
ITransformer MLModel = BuildAndTrain(mlContext, trainingDataView, sample, report);
SaveModel(mlContext, MLModel, modelpath, trainingDataView.Schema);
}
// ... for bigger dataset (1600)
public static void CreateBigModel()
{
IDataView trainingDataView = mlContext.Data.LoadFromTextFile<BigModelInput>(
path: pathBig,
hasHeader: true,
separatorChar: ',',
allowQuoting: true,
allowSparse: false);
BigModelInput sample = mlContext.Data.CreateEnumerable<BigModelInput>(trainingDataView, false).ElementAt(0);
ITransformer MLModel = BuildAndTrain(mlContext, trainingDataView, sample, reportBig);
SaveModel(mlContext, MLModel, modelpathBig, trainingDataView.Schema);
}
// Building and training ML model, very small dataset (100 entries)
public static ITransformer BuildAndTrain(MLContext mLContext, IDataView trainingDataView, ModelInput sample, string reportPath)
{
var options = new LightGbmMulticlassTrainer.Options
{
MaximumBinCountPerFeature = 8,
LearningRate = 0.00025,
NumberOfIterations = 40000,
NumberOfLeaves = 10,
LabelColumnName = "Fertilizer_NameF",
FeatureColumnName = "Features",
Booster = new DartBooster.Options()
{
MaximumTreeDepth = 10
}
};
var pipeline = mlContext.Transforms
.Text.FeaturizeText("Soil_TypeF", "Soil_Type")
.Append(mlContext.Transforms.Text.FeaturizeText("Crop_TypeF", "Crop_Type"))
.Append(mlContext.Transforms.Concatenate("Features", "Temperature", "Humidity", "Moisture", "Soil_TypeF", "Crop_TypeF", "Nitrogen", "Potassium", "Phosphorous"))
.Append(mLContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Conversion.MapValueToKey("Fertilizer_NameF", "Fertilizer_Name"), TransformerScope.TrainTest)
.AppendCacheCheckpoint(mLContext)
.Append(mLContext.MulticlassClassification.Trainers.LightGbm(options))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
Evaluate(mlContext, trainingDataView, pipeline, 10, reportPath, "Fertilizer_NameF");
ITransformer MLModel = pipeline.Fit(trainingDataView);
return MLModel;
}
//Building and training ML model, moderate size dataset (1600 entries)
public static ITransformer BuildAndTrain(MLContext mLContext, IDataView trainingDataView, BigModelInput sample, string reportPath)
{
var options = new LightGbmMulticlassTrainer.Options
{
MaximumBinCountPerFeature = 10,
LearningRate = 0.001,
NumberOfIterations = 10000,
NumberOfLeaves = 12,
LabelColumnName = "ClassF",
FeatureColumnName = "Features",
Booster = new DartBooster.Options()
{
MaximumTreeDepth = 12
}
};
var pipeline = mlContext.Transforms
.Concatenate("Features", "Ca", "Mg", "K", "S", "N", "Lime", "C", "P", "Moisture")
.Append(mLContext.Transforms.NormalizeMinMax("Features"))
.Append(mlContext.Transforms.Conversion.MapValueToKey("ClassF", "Class"), TransformerScope.TrainTest)
.AppendCacheCheckpoint(mLContext)
.Append(mLContext.MulticlassClassification.Trainers.LightGbm(options))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel", "PredictedLabel"));
Evaluate(mlContext, trainingDataView, pipeline, 8, reportPath, "ClassF");
ITransformer MLModel = pipeline.Fit(trainingDataView);
return MLModel;
}
public static ITransformer TrainModel(MLContext mlContext, IDataView trainingDataView, IEstimator<ITransformer> trainingPipeline)
{
ITransformer model = trainingPipeline.Fit(trainingDataView);
return model;
}
// Evaluate and save results to a text file
public static void Evaluate(MLContext mlContext, IDataView trainingDataView, IEstimator<ITransformer> trainingPipeline, int folds, string reportPath, string labelColumnName)
{
var crossVal = mlContext.MulticlassClassification.CrossValidate(trainingDataView, trainingPipeline, numberOfFolds: folds, labelColumnName: labelColumnName);
var metricsInMultipleFolds = crossVal.Select(r => r.Metrics);
var MicroAccuracyValues = metricsInMultipleFolds.Select(m => m.MicroAccuracy);
var LogLossValues = metricsInMultipleFolds.Select(m => m.LogLoss);
var LogLossReductionValues = metricsInMultipleFolds.Select(m => m.LogLossReduction);
string MicroAccuracyAverage = MicroAccuracyValues.Average().ToString("0.######");
string LogLossAvg = LogLossValues.Average().ToString("0.######");
string LogLossReductionAvg = LogLossReductionValues.Average().ToString("0.######");
var report = File.CreateText(reportPath);
report.Write("Micro Accuracy: " + MicroAccuracyAverage +'\n'+ "LogLoss Average: " + LogLossAvg +'\n'+ "LogLoss Reduction: " + LogLossReductionAvg, 0, 0);
report.Flush();
report.Close();
}
public static void SaveModel(MLContext mlContext, ITransformer Model, string modelPath, DataViewSchema modelInputSchema)
{
mlContext.Model.Save(Model, modelInputSchema, modelPath);
}
public static ITransformer LoadModel(bool isBig)
{
if (isBig)
return mlContext.Model.Load(modelpathBig, out DataViewSchema inputSchema);
else
return mlContext.Model.Load(modelpath, out DataViewSchema inputSchema);
}
public static Microsoft.ML.PredictionEngine<ModelInput, ModelOutput> CreateEngine()
{
ITransformer mlModel = LoadModel(false);
return mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel);
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Fertilizer
{
public int ID { get; set; }
public string Name { get; set; }
public float Nitrogen { get; set; }
public float Phosphorus { get; set; }
public float Potassium { get; set; }
}

View File

@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class FertilizerHolder
{
private Fertilizer[] FertilizerType = new Fertilizer[8];
public void init()
{
/*
FertilizerType[0] = new Fertilizer
{
ID = 999,
Name = "None",
Nitrogen = 0.0f / 5,
Phosphorus = 0 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
FertilizerType[1] = new Fertilizer
{
ID = 0,
Name = "10-26-26",
Nitrogen = 10.0f / 5,
Phosphorus = 26 * 0.436f / 5,
Potassium = 26 * 0.83f / 5
};
FertilizerType[2] = new Fertilizer
{
ID = 1,
Name = "14-35-14",
Nitrogen = 14.0f / 5,
Phosphorus = 35 * 0.436f / 5,
Potassium = 14 * 0.83f / 5
};
FertilizerType[3] = new Fertilizer
{
ID = 2,
Name = "17-17-17",
Nitrogen = 17.0f / 5,
Phosphorus = 17 * 0.436f / 5,
Potassium = 17 * 0.83f / 5
};
FertilizerType[4] = new Fertilizer
{
ID = 3,
Name = "20-20",
Nitrogen = 20.0f / 5,
Phosphorus = 20 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
FertilizerType[5] = new Fertilizer
{
ID = 4,
Name = "28-28",
Nitrogen = 28.0f / 5,
Phosphorus = 28 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
FertilizerType[6] = new Fertilizer
{
ID = 5,
Name = "DAP",
Nitrogen = 18.0f / 5,
Phosphorus = 46 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
FertilizerType[7] = new Fertilizer
{
ID = 6,
Name = "Urea",
Nitrogen = 46.0f / 5,
Phosphorus = 0 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
}
*/
FertilizerType[0] = new Fertilizer
{
ID = 999,
Name = "None",
Nitrogen = 0.0f / 5,
Phosphorus = 0 * 0.436f / 5,
Potassium = 0 * 0.83f / 5
};
FertilizerType[1] = new Fertilizer
{
ID = 0,
Name = "10-26-26",
Nitrogen = 26.0f / 5,
Phosphorus = 30 * 0.436f / 5,
Potassium = 6 * 0.83f / 5
};
FertilizerType[2] = new Fertilizer
{
ID = 1,
Name = "14-35-14",
Nitrogen = 24.0f / 5,
Phosphorus = 17 * 0.436f / 5,
Potassium = 22 * 0.83f / 5
};
FertilizerType[3] = new Fertilizer
{
ID = 2,
Name = "17-17-17",
Nitrogen = 17.0f / 5,
Phosphorus = 17 * 0.436f / 5,
Potassium = 17 * 0.83f / 5
};
FertilizerType[4] = new Fertilizer
{
ID = 3,
Name = "20-20",
Nitrogen = 10.0f / 5,
Phosphorus = 10 * 0.436f / 5,
Potassium = 20 * 0.83f / 5
};
FertilizerType[5] = new Fertilizer
{
ID = 4,
Name = "28-28",
Nitrogen = 14.0f / 5,
Phosphorus = 14 * 0.436f / 5,
Potassium = 28 * 0.83f / 5
};
FertilizerType[6] = new Fertilizer
{
ID = 5,
Name = "DAP",
Nitrogen = 12.0f / 5,
Phosphorus = 18 * 0.436f / 5,
Potassium = 34 * 0.83f / 5
};
FertilizerType[7] = new Fertilizer
{
ID = 6,
Name = "Urea",
Nitrogen = 0.0f / 5,
Phosphorus = 23 * 0.436f / 5,
Potassium = 23 * 0.83f / 5
};
}
public int GetFertilizerID(string name)
{
foreach (Fertilizer fertilizer in FertilizerType)
{
if (fertilizer.Name == name)
return fertilizer.ID;
}
return 0;
}
public Fertilizer GetFertilizer(string name)
{
foreach (Fertilizer fertilizer in FertilizerType)
{
if (fertilizer.Name == name)
return fertilizer;
}
return FertilizerType[0];
}
}

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
class Cargo
{
private Items[,] items = new Items[2, 30];
private Items[,] items = new Items[2, 351];
private int[] Count = new int[2];
@ -25,17 +25,17 @@ class Cargo
items[0, 6] = new Items("Urea", 1, 6);
//Crop Seed Storage
items[1, 0] = new Items("Barley", 1, 0);
items[1, 0] = new Items("Barley", 2, 0);
items[1, 1] = new Items("Cotton", 1, 1);
items[1, 2] = new Items("Ground Nuts", 1, 2);
items[1, 3] = new Items("Maize", 1, 3);
items[1, 4] = new Items("Millets", 1, 4);
items[1, 5] = new Items("Oil Seeds", 1, 5);
items[1, 6] = new Items("Paddy", 1, 6);
items[1, 7] = new Items("Pulses", 1, 7);
items[1, 8] = new Items("Sugarcane", 1, 8);
items[1, 9] = new Items("Tobacco", 1, 9);
items[1, 10] = new Items("Wheat", 1, 10);
items[1, 2] = new Items("Ground Nuts", 5, 2);
items[1, 3] = new Items("Maize", 3, 3);
items[1, 4] = new Items("Millets", 4, 4);
items[1, 5] = new Items("Oil Seeds", 4, 5);
items[1, 6] = new Items("Paddy", 5, 6);
items[1, 7] = new Items("Pulses", 5, 7);
items[1, 8] = new Items("Sugarcane", 3, 8);
items[1, 9] = new Items("Tobacco", 2, 9);
items[1, 10] = new Items("Wheat", 2, 10);
}
public void addItem(Items item, int Type)

View File

@ -11,7 +11,7 @@ using Microsoft.Xna.Framework.Input;
class Inventory
{
private int Weight = 0;
private int maxWeight = 25;
private int maxWeight = 350;
private Cargo cargo = new Cargo();
private Cargo itemStorage = new Cargo();
@ -101,6 +101,7 @@ class Inventory
public void removeItem(int Index, int Type)
{
Weight = Weight - itemStorage.getItemByIndex(Index, Type).getWeight();
cargo.removeItem(Index, Type);
}
@ -109,6 +110,37 @@ class Inventory
return itemStorage;
}
public void clearInventory()
{
for (int i = 0; i <= 6; i++)
while (useItem(i, 0)) ;
for (int i = 0; i <= 10; i++)
while (useItem(i, 1)) ;
}
public void fillWithFertilizer()
{
int i = 0;
while (getWeight() < getMaxWeight())
{
if (i > 6)
i = 0;
addItem(i, 0);
i++;
}
}
public bool isMissingFertilizer()
{
for (int i = 0; i <= 6; i++)
{
if (!itemExists(i, 0))
return true;
}
return false;
}
public void printItems(Input input, SpriteBatch spriteBatch, SpriteFont Bold)
{

View File

@ -15,6 +15,7 @@ class AI
private Vector2 Size;
private Vector2 targetPos;
private Inventory inventory = new Inventory();
private FertilizerHolder fertilizerHolder = new FertilizerHolder();
private int Rotation;
private Astar astar = new Astar();
@ -52,6 +53,9 @@ class AI
int count = 0;
int testsize = 2;
Vector2 newTarget;
if (tractorPos != housePos)
if (inventory.getWeight() == inventory.getMaxWeight() || inventory.isMissingFertilizer())
return housePos;
while (true)
{
for (int x = 0; x < Size.X; x++)
@ -59,38 +63,51 @@ class AI
{
if (farm.getCrop(x, y).getStatus() >= 2 && tractorPos != new Vector2(x, y))
{
score = calculateSoilScore(x, y);
queue.AddToQueue(x, y, score);
if (farm.getCrop(x, y).getCropTimer() == 1 || farm.getCrop(x, y).getStatus() == 2)
count++;
if (farm.getCrop(x, y).isSaturated() || !farm.getCrop(x, y).belowCapacity())
{
//do nothing
}
else
{
score = calculateSoilScore(x, y);
queue.AddToQueue(x, y, score);
if (farm.getCrop(x, y).getCropTimer() == 1 || farm.getCrop(x, y).getStatus() == 2)
count++;
}
}
}
if (count > 0)
break;
else if (tractorPos != housePos)
else //if (tractorPos != housePos)
return newTarget = GetMaxFNode(testsize, queue);
/*
else if (tractorPos == housePos)
{
List<Nodes> temp = astar.GetAdjacentNodes(tractorPos);
return temp[0].getCords();
}
*/
}
newTarget = GetMinFNode(Math.Min(testsize, count), queue);
queue = null;
return newTarget;
}
public Farm changeCropStatus()
{
if (farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getCropTimer() == 1)
int x = (int)tractorPos.X;
int y = (int)tractorPos.Y;
Fertilizer fertilizer = new Fertilizer();
fertilizerHolder.init();
if (farm.getCrop(x, y).getCropTimer() == 1)
{
farm.setCropStatus(tractorPos.X, tractorPos.Y);
if (farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getStatus() == 2)
if (farm.getCrop(x, y).getStatus() == 2)
{
inventory.addItem(farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getCropType() - 1, 1);
fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType())));
while (!(farm.getCrop(x, y).isSaturated()) && farm.getCrop(x, y).belowCapacity() && inventory.useItem(fertilizerHolder.GetFertilizerID(fertilizer.Name), 0))
{
farm.getCrop(x, y).Fertilize(fertilizer);
fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType())));
}
}
farm.setCropStatus(tractorPos.X, tractorPos.Y);
if (farm.getCrop(x, y).getStatus() == 2)
{
inventory.addItem(farm.getCrop(x, y).getCropType() - 1, 1);
}
}
@ -107,6 +124,7 @@ class AI
int score = 0;
int statusScore = 0;
int timerScore = 0;
int saturationScore = 0;
int aproxDistance = (int)(Math.Abs(x - tractorPos.X) + Math.Abs(y - tractorPos.Y));
CropTypesHolder holder = new CropTypesHolder();
holder.init();
@ -130,7 +148,14 @@ class AI
score = (int)(crop.getProductionRate(avgHold) * 10);
return score + (-aproxDistance * 5) + statusScore + timerScore;
if (!crop.isSaturated())
saturationScore = 5;
else
{
saturationScore = -100;
}
return score + (-aproxDistance * 5) + statusScore + timerScore + saturationScore;
}
private float norm(float min, float max, float val)
@ -200,6 +225,13 @@ class AI
return minEntry.Coordinates;
}
public void reloadCargo()
{
inventory.clearInventory();
inventory.fillWithFertilizer();
}
}

View File

@ -22,6 +22,8 @@ class SmartTractor
astar.update(farm.getCrops(), Size, tractorPos / (tileSize + Spacing), housePos / (tileSize + Spacing), Rotation);
getTargetPosition(ai.newTarget());
astar.update(farm.getCrops(), Size, tractorPos / (tileSize + Spacing), housePos / (tileSize + Spacing), Target / (tileSize + Spacing), Rotation);
if (tractorPos == housePos)
ai.reloadCargo();
return astar.FindPath(true);
}