-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/genetic algorythm #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a ideia do controller é essa mesmo de validação, pegou certo porém tem algumas coisas aqui que precisamos mudar
exemplo da requisição original:
"body": {
'provas_que_tenho':[
{
'valor':6.0,
'peso':0.2
}
],
'trabalhos_que_tenho':[
{
'valor':6.0,
'peso':0.2
},
{
'valor':6.0,
'peso':0.2
},
],
'provas_que_quero':[
{
'valor':None,
'peso':0.2
},
{
'valor':None,
'peso':0.3
},
{
'valor':None,
'peso':0.3
},
],
'trabalhos_que_quero':[
{
'valor':None,
'peso':0.3
},
{
'valor':None,
'peso':0.3
}
],
'peso_prova':0.4,
'peso_trabalho':0.6,
'media_desejada':6
}
tipo nao a unica coisa que voce vai poder usar e extrair tirando as provas e trabalhos é peso_prova, peso_trabalho e media desejada. Nao vai ter um generations, spec_test_weight, etc... esses valores, se realmente necessários, podem ser hard-codados no usecase. Tipo generations da pra setar um valor padrão no usecase que nao vai vir da request.
| if request.data.get('max_grade') is not None: | ||
| if type(request.data.get('max_grade')) != float: | ||
| raise WrongTypeParameter( | ||
| fieldName="max_grade", | ||
| fieldTypeExpected="float", | ||
| fieldTypeReceived=request.data.get('max_grade').__class__.__name__ | ||
| ) | ||
| if request.data.get('max_grade') <= 0: | ||
| raise InvalidInput("max_grade", "Must be greater than 0") | ||
| max_grade = request.data.get('max_grade') | ||
| else: | ||
| max_grade = 10.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esse max grade existe no requisição original que vem pro grade_optimizer? lembra que vamos receber exatamente os mesmos dados que vem na requisição da rota antiga, nada mais nada menos
| if request.data.get('population_size') is not None: | ||
| if type(request.data.get('population_size')) != int: | ||
| raise WrongTypeParameter( | ||
| fieldName="population_size", | ||
| fieldTypeExpected="int", | ||
| fieldTypeReceived=request.data.get('population_size').__class__.__name__ | ||
| ) | ||
| if request.data.get('population_size') <= 0: | ||
| raise InvalidInput("population_size", "Must be greater than 0") | ||
| population_size = request.data.get('population_size') | ||
| else: | ||
| population_size = 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mesma coisa aqui, retira esse population size pq nao vem na requisição original. usa os testes de presenters que temos da rota antiga pra ter uma ideia de como é a requisição antiga
| if request.data.get('generations') is not None: | ||
| if type(request.data.get('generations')) != int: | ||
| raise WrongTypeParameter( | ||
| fieldName="generations", | ||
| fieldTypeExpected="int", | ||
| fieldTypeReceived=request.data.get('generations').__class__.__name__ | ||
| ) | ||
| if request.data.get('generations') <= 0: | ||
| raise InvalidInput("generations", "Must be greater than 0") | ||
| generations = request.data.get('generations') | ||
| else: | ||
| generations = 200 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aq tb
| if request.data.get('num_remaining_assignments') < 0: | ||
| raise InvalidInput("num_remaining_assignments", "Must be non-negative") | ||
|
|
||
| num_remaining_assignments = request.data.get('num_remaining_assignments') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tipo essa linha vai falhar pq a requisição não te manda essa informação, vamos ter que calcular isso dentro do usecase
| def __call__(self, | ||
| current_tests: list[float], | ||
| current_assignments: list[float], | ||
| num_remaining_tests: int, | ||
| num_remaining_assignments: int, | ||
| test_weight: float, | ||
| assignment_weight: float, | ||
| target_average: float, | ||
| max_grade: float = 10.0, | ||
| population_size: int = 150, | ||
| generations: int = 200, | ||
| spec_test_weight: Optional[list[float]] = None, | ||
| spec_assignment_weight: Optional[list[float]] = None | ||
| ) -> dict: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minha sugestão aqui para lidar com os num of remaining é passar o remaining_tests como uma lista dos trabalhos que voce quer e dentro do usecase pegar o len() dessa lista
da mesma forma acho melhor passar o current_tests/current_assignment/remaining_tests/remaining_assignments como uma lista de nota + peso (fazendo a devida validação no controller) e depois dentro do usecase separar (transformar os pesos nos spec_..._weight, num_remaining_tests....) fecho?
| #Validações das variáveis de entrada | ||
|
|
||
| if type(max_grade) != float: | ||
| raise InvalidInput("max_grade", "Deve ser um valor do tipo float") | ||
| if max_grade <= 0: | ||
| raise InvalidInput("max_grade", "Deve ser um valor maior que 0") | ||
|
|
||
| if type(target_average) != float: | ||
| raise InvalidInput("target_average", "Deve ser um valor do tipo float") | ||
| if target_average < 0 or target_average > max_grade: | ||
| raise InvalidInput("target_average", f"Deve estar entre 0 e {max_grade}") | ||
|
|
||
| if test_weight + assignment_weight != 1.0: | ||
| raise InvalidInput("test_weight and/or assignment_weight", "Devem somar 1.0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esse tipo de validação deve estar dentro da entidade do Boletim_GA, não precisa fazer aqui
| ga = GradeGeneticAlgorithm(boletim=boletim, target_average=target_average, max_grade=max_grade, population_size=population_size, generations=generations) | ||
| solution, fitness = ga.run() | ||
| response = { | ||
| "current_tests": current_tests, | ||
| "current_assignments": current_assignments, | ||
| "tests": solution['tests'], | ||
| "assignments": solution['assignments'], | ||
| "test_weight": test_weight, | ||
| "assignment_weight": assignment_weight, | ||
| "spec_test_weight": spec_test_weight, | ||
| "spec_assignment_weight": spec_assignment_weight, | ||
| "num_remaining_tests": num_remaining_tests, | ||
| "num_remaining_assignments": num_remaining_assignments, | ||
| "target_average": target_average | ||
| } | ||
|
|
||
| boletim.calculated_tests = solution['tests'] | ||
| boletim.calculated_assignments = solution['assignments'] | ||
| boletim.target_avg = target_average | ||
|
|
||
| if(response == None): | ||
| raise CombinationNotFound() | ||
| return response No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aqui ao invés de retornar o {} retorna o objeto da entidade BoletimGA (simplesmente return boletim)
essa transformação para um dicionário deve ser feita no viewmodel, o usecase vai ser responsável apenas por executar e chamar essa lógica do GA
depois que voce chamou o GA, voce passou as infos pro BoletimGA. Agora se precisa retornar ele e no controller passar ele pro viewmodel. Dentro do viewmodel voce acessa as infos dele e gera o json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aqui no viewmodel temos que simplificar bastante.
A função desse arquivo basicamente é o que voce fez no final do usecase.
Ajusta ele para receber uma entidade BoletimGA, colocar o parâmetro de entrada dentro de um self.BoletimGA, no to_dict() pegar os parametros da solução e transformar no dicionário que ta la no final
Implanted:
genetic_algorithm_solver, in src/shared;
genetic_algorithm_controler, in src/modules/genetic_algorithm/app;
genetic_algorithm_presenter, in src/modules/genetic_algorithm/app;
genetic_algorithm_usecase, in src/modules/genetic_algorithm/app;
genetic_algorithm_viewmode, in src/modules/genetic_algorithm/app;
boletim_ga, in src/shared/domain/entities;
and their respective tests, except genetic_algorithm_solver.