103 lines
3.0 KiB
Python
103 lines
3.0 KiB
Python
from typing import List, Union
|
|
from api.models.docit2mf_models import DoCIT2MFRequest
|
|
from api.models.docmf_models import DoCMFRequest
|
|
from api.services.docmf_build_service import build_doc_mf_level
|
|
|
|
|
|
def _extract_bounds(values: List[Union[int, List[int], tuple]], mode: str) -> List[int]:
|
|
"""
|
|
Devuelve una lista de enteros:
|
|
- Si el valor es un entero → se usa tal cual para LMF y UMF
|
|
- Si es un intervalo [min,max] → se usa min o max según mode
|
|
"""
|
|
result = []
|
|
for item in values:
|
|
if isinstance(item, int):
|
|
result.append(item)
|
|
else:
|
|
lo, hi = item
|
|
result.append(lo if mode == "min" else hi)
|
|
return result
|
|
|
|
|
|
def _sort_nodes(nodes):
|
|
"""Ordena los nodos por su coordenada X."""
|
|
return sorted([list(p) for p in nodes], key=lambda p: p[0])
|
|
|
|
|
|
def _enforce_upper_ge_lower(lower, upper):
|
|
"""
|
|
Garantiza que la UMF (upper) nunca quede por debajo de la LMF (lower).
|
|
Ajusta los valores de pertenencia si es necesario.
|
|
"""
|
|
for i in range(len(lower["left_nodes"])):
|
|
ly = lower["left_nodes"][i][1]
|
|
uy = upper["left_nodes"][i][1]
|
|
upper["left_nodes"][i][1] = max(uy, ly)
|
|
|
|
for i in range(len(lower["right_nodes"])):
|
|
ly = lower["right_nodes"][i][1]
|
|
uy = upper["right_nodes"][i][1]
|
|
upper["right_nodes"][i][1] = max(uy, ly)
|
|
|
|
return upper
|
|
|
|
|
|
def build_it2mf_from_level(level: DoCIT2MFRequest):
|
|
"""
|
|
Construye una función IT2MF a partir de un nivel con intervalos de cartas blancas.
|
|
Devuelve:
|
|
{
|
|
"term": ...,
|
|
"lower": {...},
|
|
"upper": {...}
|
|
}
|
|
"""
|
|
|
|
left_min = _extract_bounds(level.left_blank_cards, "min")
|
|
right_min = _extract_bounds(level.right_blank_cards, "min")
|
|
|
|
lower_level = DoCMFRequest(
|
|
term=level.term,
|
|
core=level.core,
|
|
support=level.support,
|
|
left_nodes_x=level.left_nodes_x,
|
|
left_blank_cards=left_min,
|
|
right_nodes_x=level.right_nodes_x,
|
|
right_blank_cards=right_min,
|
|
)
|
|
|
|
lower = build_doc_mf_level(lower_level)
|
|
if hasattr(lower, "model_dump"):
|
|
lower = lower.model_dump()
|
|
|
|
lower["left_nodes"] = _sort_nodes(lower["left_nodes"])
|
|
lower["right_nodes"] = _sort_nodes(lower["right_nodes"])
|
|
|
|
left_max = _extract_bounds(level.left_blank_cards, "max")
|
|
right_max = _extract_bounds(level.right_blank_cards, "max")
|
|
|
|
upper_level = DoCMFRequest(
|
|
term=level.term,
|
|
core=level.core,
|
|
support=level.support,
|
|
left_nodes_x=level.left_nodes_x,
|
|
left_blank_cards=left_max,
|
|
right_nodes_x=level.right_nodes_x,
|
|
right_blank_cards=right_max,
|
|
)
|
|
|
|
upper = build_doc_mf_level(upper_level)
|
|
if hasattr(upper, "model_dump"):
|
|
upper = upper.model_dump()
|
|
|
|
upper["left_nodes"] = _sort_nodes(upper["left_nodes"])
|
|
upper["right_nodes"] = _sort_nodes(upper["right_nodes"])
|
|
|
|
upper = _enforce_upper_ge_lower(lower, upper)
|
|
|
|
return {
|
|
"term": level.term,
|
|
"lower": lower,
|
|
"upper": upper
|
|
} |