Skip to content
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

Issue with comparing types in case of sets with units #1060

Open
psuzzi opened this issue Sep 17, 2024 · 1 comment
Open

Issue with comparing types in case of sets with units #1060

psuzzi opened this issue Sep 17, 2024 · 1 comment

Comments

@psuzzi
Copy link
Collaborator

psuzzi commented Sep 17, 2024

In a customer project, we have a issue with types related to comparing types when the type is a set<set<number>>

It looks like a set of set of numbers with units is not correctly matched to its type, but it is rather matched to a sort of interval.

image

In short, the function computeSupertype (in SimpleTypesPrimitiveTypeMapper) is not working as expected forthe function computeSupertype (in SimpleTypesPrimitiveTypeMapper) is not working as expected for this case.

Let's consider the iets3 open source code for the method:

@Override 
public node<> computeSupertype(nlist<> types, boolean goToInfinity, SubtypingManager mgr)  { 
   
  nlist<NumberType> numberTypes = types.ofConcept<NumberType>.toList; 
  nlist<TupleType> tupleTypes = types.ofConcept<TupleType>.toList; 
  nlist<> resultTypes = types.except(numberTypes).except(tupleTypes).toList; 
   
  nlist<> resultTupleTypes = new nlist<>; 
  if (tupleTypes.size > 0) { 
    resultTupleTypes.addAll(computeSupertypeOfTuples(tupleTypes, goToInfinity, mgr)); 
  } 
   
  if (numberTypes.size > 0) { 
    resultTypes.add(computeSupertypeOfNumberTypes(numberTypes, goToInfinity)); 
  } 
   
  // The next part is a hack:  
  // Because mgr.leastCommonSupertypes(set, false)  does only operate on sets containing 2 elements,  
  // we need to extract the elements from  resultTypes  and pass them to the function successively.  
  // s.a.: https://youtrack.jetbrains.com/issue/MPSI-45/leastCommonSupertypes-does-not-calculate-correctly-on-tuples-with-multiple-values  
  set<node<>> set = new hashset<node<>>; 
  set.add(resultTypes.first); 
  foreach type in resultTypes.where({~it => it != resultTypes.first; }) { 
    set.add(type); 
    Set<SNode> least = mgr.leastCommonSupertypes(set, false); 
    set.clear; 
    least.removeIf({SNode nn => nn.getConcept().isAbstract(); }); 
    // No common supertype available:  
    if (least.isEmpty()) { break; } 
    // More than one supertype should never occur:  
    if (least.size() > 1) { 
      // fall back to join-Type  
      break; 
    } else { 
      set.addAll(least); 
    } 
  } 
  //  END OF the hack.  
  //  Now the set contains the supertype as only element if there is one.  
   
  node<JoinType> jt = new node<JoinType>(); 
  if (set.size == 1) { 
    jt.types.add(set.iterator.next as Type); 
  } else { 
    jt.types.addAll(resultTypes.ofConcept<Type>); 
  } 
  if (resultTupleTypes.size > 0) { 
    jt.types.addAll(resultTupleTypes.ofConcept<Type>); 
  } 
  if (jt.types.size == 1) { 
    return jt.types.first; 
  } else { 
    return jt; 
  } 
}

And now, we consider how it works in this specific case:

set<set<number<m>>> input13 : default set(set(1 m, 2 m), set(2 m, 4 m)) optional false

The problem, in our case, is that

  • we would expect to have a set<set<number{0}<SIUnits.m>>>,
  • while we get a set<join<[set<number[1|2]{0}<SIUnits.m>>, set<number[2|4]{0}<SIUnits.m>>]>>

For our case, looking at the code in the computeSupertype we observe the following:

  • set<node<>> set = new hashset<node<>>; starts with a new set
  • then we add resultTypes.first to the set. In this case set(1 m, 2 m)
  • and then, for each type in resultType which is different w.r.t. the first result type, we add the type to the set

Now, I believe the problem lies in how the .where({~it => it != resultTypes.first; }) is unable to compare the types.
Indeed, in our case, we return a join type.

To me looks like the solution is refactoring the type-equality condition.

@psuzzi
Copy link
Collaborator Author

psuzzi commented Sep 18, 2024

The root cause of the issue is how the type is computed for a set of numbers with units.
E.g. set(1 m) type is number[1|1]{0}<SIUnits.m> so a set of numbers with min=1, max=1, precision=0, and unit=m.
Now, when constructing a set( set( 1 m), set( 2 m) ) the type of set( 1 m) and set( 2 m) are not matching because of the different min/max, so the resulting unit is a set< join<[ set<number[1|1]{0}<SIUnits.m>>, set<number[2|2]{0}<SIUnits.m>> ]>>

This can be fixed in iets3.opensource platform by changing computeSupertype, to specifically deal with sets

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant