git init
Some checks failed
linter / quality (push) Failing after 6m40s
tests / ci (8.4) (push) Failing after 10s
tests / ci (8.5) (push) Failing after 11s

This commit is contained in:
2026-03-03 11:10:38 +01:00
commit 650cf56045
282 changed files with 27333 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
<?php
namespace App\Http\Controllers;
use App\Models\SimplePerceptron;
use App\Services\DataSetReader;
use App\Services\ISynapticWeights;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class PerceptronController extends Controller
{
/**
* Display the specified resource.
*/
public function index(Request $request)
{
$perceptronType = $request->query('type', 'simple');
$dataSet = $request->input('data_set', 'logic_and');
$dataSetReader = $this->getDataSetReader($dataSet);
return inertia('PerceptronViewer', [
'type' => $perceptronType,
'sessionId' => session()->getId(),
'dataset' => $dataSetReader->lines,
'csrf_token' => csrf_token(),
]);
}
private function getDataSetReader(string $dataSet): DataSetReader
{
$dataSetFileName = "data_sets/{$dataSet}.csv";
return new DataSetReader($dataSetFileName);
}
public function run(Request $request, ISynapticWeights $synapticWeightsProvider)
{
$perceptronType = $request->query('type', 'simple');
$minError = $request->query('min_error', 0.01);
$dataSet = $request->input('data_set', 'logic_and');
$learningRate = $request->input('learning_rate', 0.1);
$sessionId = $request->input('session_id', session()->getId());
$dataSetReader = $this->getDataSetReader($dataSet);
$MAX_ITERATIONS = 100;
$stopCondition;
$trainFunction;
$trainFunctionState = [];
switch ($perceptronType) {
case 'simple':
$stopCondition = function($iteration, $iterationErrorCounter) use ($sessionId) {
$condition = $iterationErrorCounter == 0;
if ($condition === true) {
Log::info("Perceptron training ended after {$iteration} iterations with no errors.");
event(new \App\Events\PerceptronTrainingEnded('Le perceptron ne commet plus d\'erreurs sur aucune des données', $sessionId));
}
return $iterationErrorCounter == 0;
};
$iterationFunction = function(&$state) use ($synapticWeightsProvider, $learningRate, $minError) {
if (!isset($state['perceptron'])) {
$state['perceptron'] = new SimplePerceptron($synapticWeightsProvider->generate(2));
}
$perceptron = $state['perceptron'];
$inputs = $state['inputs'];
$correctOutput = $state['correctOutput'];
$iterationErrorCounter = $state['iterationErrorCounter'] ?? 0;
$output = $perceptron->test($inputs);
$error = $correctOutput - $output;
if (abs($error) > $minError) {
$iterationErrorCounter++;
}
if ($error !== 0) { // Update synaptic weights if needed
$synaptic_weights = $perceptron->getSynapticWeights();
$inputs_with_bias = array_merge([1], $inputs); // Add bias input
$new_weights = array_map(fn($weight, $input) => $weight + $learningRate * $error * $input, $synaptic_weights, $inputs_with_bias);
$perceptron->setSynapticWeights($new_weights);
}
return [$error, $perceptron->getSynapticWeights(), $iterationErrorCounter, $state];
};
break;
default:
return response()->json(['error' => 'Invalid perceptron type'], 400);
}
$iteration = 0;
$error = 1.0; // Initial error
do {
$iterationErrorCounter = 0;
$iteration++;
while ($nextRow = $dataSetReader->getRandomLine()) {
$inputs = array_slice($nextRow, 0, -1);
$correctOutput = end($nextRow);
$trainFunctionState['inputs'] = $inputs;
$trainFunctionState['correctOutput'] = $correctOutput;
$trainFunctionState['iterationErrorCounter'] = $iterationErrorCounter;
[$error, $synaptic_weights, $iterationErrorCounter, $trainFunctionState] = $iterationFunction($trainFunctionState);
$error = abs($error); // Use absolute error
// Broadcast the training iteration event
event(new \App\Events\PerceptronTrainingIteration($iteration, $dataSetReader->getLastReadLineIndex(), $error, $synaptic_weights, $sessionId));
}
$dataSetReader->reset(); // Reset the dataset for the next iteration
} while ($iteration < $MAX_ITERATIONS && !$stopCondition($iteration, $iterationErrorCounter));
if ($iteration >= $MAX_ITERATIONS) {
event(new \App\Events\PerceptronTrainingEnded('Le nombre maximal d\'itérations a été atteint', $sessionId));
}
return response()->json([
'message' => 'Training completed',
'iterations' => $iteration,
'final_error' => $error,
'final_synaptic_weights' => isset($trainFunctionState['perceptron']) ? $trainFunctionState['perceptron']->getSynapticWeights() : [0],
]);
}
}