DmitrMakeev commited on
Commit
f834392
·
verified ·
1 Parent(s): f9a03ae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -90
app.py CHANGED
@@ -18,7 +18,7 @@ import numpy as np
18
  from tabulate import tabulate
19
 
20
  from typing import Dict, Any, Union, List
21
-
22
 
23
  import traceback
24
  import logging
@@ -717,7 +717,8 @@ NUTRIENT_CONTENT_IN_FERTILIZERS = {
717
  "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
718
  "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
719
  "Монофосфат калия": {"P": 0.218, "K": 0.275},
720
- "Сульфат кальция": {"Ca": 0.23, "S": 0.186}
 
721
  }
722
 
723
  EC_COEFFICIENTS = {
@@ -726,6 +727,8 @@ EC_COEFFICIENTS = {
726
  'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
727
  }
728
 
 
 
729
  class NutrientCalculator:
730
  def __init__(self, volume_liters=1.0):
731
  self.volume = volume_liters
@@ -746,16 +749,8 @@ class NutrientCalculator:
746
  "NH4+": self.target_profile['N (NH4+)']
747
  }
748
 
749
- # Веса компенсации
750
- self.compensation_weights = {
751
- "Ca": {"weight": 0.3, "fert": "Сульфат кальция", "main_element": "Ca"},
752
- "K": {"weight": 0.2, "fert": "Калий азотнокислый", "main_element": "K"},
753
- "Mg": {"weight": 0.2, "fert": "Сульфат магния", "main_element": "Mg"},
754
- "P": {"weight": 0.1, "fert": "Монофосфат калия", "main_element": "P"},
755
- "S": {"weight": 0.1, "fert": "Калий сернокислый", "main_element": "S"},
756
- "N (NO3-)": {"weight": 0.05, "fert": "Калий азотнокислый", "main_element": "N (NO3-)"},
757
- "N (NH4+)": {"weight": 0.05, "fert": "Аммоний азотнокислый", "main_element": "N (NH4+)"}
758
- }
759
 
760
  def _label(self, element):
761
  """Форматирование названий элементов для вывода"""
@@ -767,103 +762,71 @@ class NutrientCalculator:
767
 
768
  def calculate(self):
769
  try:
770
- max_iterations = 100 # Максимальное количество итераций
771
- iteration = 0
772
- while iteration < max_iterations:
773
- iteration += 1
774
- print(f"Итерация {iteration} из {max_iterations}")
 
 
 
775
 
776
  # Сброс фактического профиля
777
  self._reset_actual_profile()
778
 
779
- # Применение удобрений
780
- self._apply_fertilizers()
781
-
782
- # Проверка результатов
783
- if self.validate_results():
784
  print("Успешная комбинация найдена!")
785
  return self.results
786
 
787
- # Корректировка перебора
788
- self._adjust_overages()
789
-
790
- raise ValueError("Не удалось найти подходящую комбинацию удобрений после максимального количества итераций.")
791
 
792
  except Exception as e:
793
  print(f"Ошибка при расчёте: {str(e)}")
794
  raise
795
 
 
 
 
 
796
  def _reset_actual_profile(self):
797
- """Сброс фактического профиля перед новой итерацией"""
798
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
799
  self.total_ec = 0.0
800
  self.results = {}
801
 
802
- def _apply_fertilizers(self):
803
- """Применение удобрений"""
804
- for fert_name, fert_data in self.fertilizers.items():
805
- for element, content in fert_data.items():
806
  required_ppm = self.target_profile[element] - self.actual_profile[element]
807
  if required_ppm > 0.1:
808
- grams = min((required_ppm * self.volume) / (content * 1000), 100) # Ограничение на граммы
809
- self._apply_with_limit(fert_name, element, grams, content)
810
-
811
- def _apply_with_limit(self, fert_name, element, grams, content):
812
- """Применение удобрения с ограничением"""
813
- if fert_name not in self.results:
814
- self.results[fert_name] = {
815
- 'граммы': 0.0,
816
- 'миллиграммы': 0,
817
- 'вклад в EC': 0.0
818
- }
819
- for elem in self.fertilizers[fert_name]:
820
- self.results[fert_name][f'внесет {self._label(elem)}'] = 0.0
821
-
822
- self.results[fert_name]['граммы'] += grams
823
- self.results[fert_name]['миллиграммы'] += int(grams * 1000)
824
-
825
- fert_ec = 0.0
826
- for elem, percent in self.fertilizers[fert_name].items():
827
- added_ppm = (grams * percent * 1000) / self.volume
828
- self.results[fert_name][f'внесет {self._label(elem)}'] += added_ppm
829
- self.actual_profile[elem] += added_ppm
830
- fert_ec += added_ppm * EC_COEFFICIENTS.get(elem, 0.0015)
831
-
832
- self.results[fert_name]['вклад в EC'] += fert_ec
833
- self.total_ec += fert_ec
834
-
835
- def _adjust_overages(self):
836
- """Корректировка перебора элементов"""
837
- for element in self.actual_profile:
838
- if self.actual_profile[element] > self.target_profile[element]:
839
- overage = self.actual_profile[element] - self.target_profile[element]
840
- print(f"Корректировка перебора: {element} уменьшен на {overage:.2f} ppm")
841
-
842
- # Уменьшаем фактическое значение
843
- self.actual_profile[element] -= overage
844
-
845
- # Обновляем результаты удобрений
846
- for fert_name, fert_data in self.results.items():
847
- if f'внесет {self._label(element)}' in fert_data:
848
- current_value = fert_data[f'внесет {self._label(element)}']
849
- if current_value > overage:
850
- fert_data[f'внесет {self._label(element)}'] -= overage
851
- overage = 0
852
- else:
853
- overage -= current_value
854
- fert_data[f'внесет {self._label(element)}'] = 0
855
-
856
- # Пересчитываем граммы удобрения
857
- if element in self.fertilizers[fert_name]:
858
- content = self.fertilizers[fert_name][element]
859
- grams_to_remove = (current_value * self.volume) / (content * 1000)
860
- fert_data['граммы'] -= grams_to_remove
861
- fert_data['миллиграммы'] -= int(grams_to_remove * 1000)
862
-
863
- # Убеждаемся, что граммы не отрицательны
864
- if fert_data['граммы'] < 0:
865
- fert_data['граммы'] = 0
866
- fert_data['миллиграммы'] = 0
867
 
868
  def validate_results(self):
869
  """Проверка соответствия целевым значениям"""
 
18
  from tabulate import tabulate
19
 
20
  from typing import Dict, Any, Union, List
21
+ import itertools
22
 
23
  import traceback
24
  import logging
 
717
  "Аммоний азотнокислый": {"N (NO3-)": 0.17499, "N (NH4+)": 0.17499},
718
  "Сульфат магния": {"Mg": 0.09861, "S": 0.13010},
719
  "Монофосфат калия": {"P": 0.218, "K": 0.275},
720
+ "Сульфат кальция": {"Ca": 0.23, "S": 0.186},
721
+ "Кольцевая селитра": {"N (NO3-)": 0.15, "Ca": 0.20} # Новое удобрение
722
  }
723
 
724
  EC_COEFFICIENTS = {
 
727
  'N (NO3-)': 0.0017, 'N (NH4+)': 0.0019
728
  }
729
 
730
+
731
+
732
  class NutrientCalculator:
733
  def __init__(self, volume_liters=1.0):
734
  self.volume = volume_liters
 
749
  "NH4+": self.target_profile['N (NH4+)']
750
  }
751
 
752
+ # Список всех удобрений
753
+ self.fertilizer_list = list(self.fertilizers.keys())
 
 
 
 
 
 
 
 
754
 
755
  def _label(self, element):
756
  """Форматирование названий элементов для вывода"""
 
762
 
763
  def calculate(self):
764
  try:
765
+ max_attempts = 100 # Максимальное количество попыток
766
+ attempt = 0
767
+ while attempt < max_attempts:
768
+ attempt += 1
769
+ print(f"Попытка {attempt} из {max_attempts}")
770
+
771
+ # Генерация случайного порядка удобрений
772
+ fertilizer_order = self._shuffle_fertilizers()
773
 
774
  # Сброс фактического профиля
775
  self._reset_actual_profile()
776
 
777
+ # Пробуем рассчитать с текущим порядком удобрений
778
+ if self._try_combination(fertilizer_order):
 
 
 
779
  print("Успешная комбинация найдена!")
780
  return self.results
781
 
782
+ raise ValueError("Не удалось найти подходящую комбинацию удобрений после максимального количества попыток.")
 
 
 
783
 
784
  except Exception as e:
785
  print(f"Ошибка при расчёте: {str(e)}")
786
  raise
787
 
788
+ def _shuffle_fertilizers(self):
789
+ """Генерация случайного порядка удобрений"""
790
+ return list(itertools.permutations(self.fertilizer_list))[hash(str(self.target_profile)) % len(self.fertilizer_list)]
791
+
792
  def _reset_actual_profile(self):
793
+ """Сброс фактического профиля перед новой попыткой"""
794
  self.actual_profile = {k: 0.0 for k in BASE_PROFILE}
795
  self.total_ec = 0.0
796
  self.results = {}
797
 
798
+ def _try_combination(self, fertilizer_order):
799
+ """Попытка расчета с заданным порядко�� удобрений"""
800
+ for fert_name in fertilizer_order:
801
+ for element, content in self.fertilizers[fert_name].items():
802
  required_ppm = self.target_profile[element] - self.actual_profile[element]
803
  if required_ppm > 0.1:
804
+ grams = (required_ppm * self.volume) / (content * 1000)
805
+
806
+ if fert_name not in self.results:
807
+ self.results[fert_name] = {
808
+ 'граммы': 0.0,
809
+ 'миллиграммы': 0,
810
+ 'вклад в EC': 0.0
811
+ }
812
+ for elem in self.fertilizers[fert_name]:
813
+ self.results[fert_name][f'внесет {self._label(elem)}'] = 0.0
814
+
815
+ self.results[fert_name]['граммы'] += grams
816
+ self.results[fert_name]['миллиграммы'] += int(grams * 1000)
817
+
818
+ fert_ec = 0.0
819
+ for elem, percent in self.fertilizers[fert_name].items():
820
+ added_ppm = (grams * percent * 1000) / self.volume
821
+ self.results[fert_name][f'внесет {self._label(elem)}'] += added_ppm
822
+ self.actual_profile[elem] += added_ppm
823
+ fert_ec += added_ppm * EC_COEFFICIENTS.get(elem, 0.0015)
824
+
825
+ self.results[fert_name]['вклад в EC'] += fert_ec
826
+ self.total_ec += fert_ec
827
+
828
+ # Проверка результатов
829
+ return self.validate_results()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
830
 
831
  def validate_results(self):
832
  """Проверка соответствия целевым значениям"""