-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #210 from VirtusLab/sorting
Sorting
- Loading branch information
Showing
20 changed files
with
423 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
.../src/main/scala/org/virtuslab/inkuire/engine/common/service/BaseMatchQualityService.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.virtuslab.inkuire.engine.common.service | ||
|
||
import org.virtuslab.inkuire.engine.common.model._ | ||
|
||
trait BaseMatchQualityService { | ||
|
||
def sortMatches(functions: Seq[(ExternalSignature, Signature)]): Seq[(ExternalSignature, Int)] = | ||
functions | ||
.map { | ||
case (fun, matching) => fun -> matchQualityMetric(fun, matching) | ||
} | ||
.sortBy(_._2) | ||
|
||
def matchQualityMetric(externalSignature: ExternalSignature, matching: Signature): Int | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
...in/scala/org/virtuslab/inkuire/engine/common/service/IsomorphismMatchQualityService.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package org.virtuslab.inkuire.engine.common.service | ||
|
||
import org.virtuslab.inkuire.engine.common.model._ | ||
|
||
class IsomorphismMatchQualityService(val db: InkuireDb) extends BaseMatchQualityService with MatchingOps { | ||
|
||
def matchQualityMetric(externalSignature: ExternalSignature, matching: Signature): Int = | ||
variancesMatchQualityMetric( | ||
externalSignature.signature.typesWithVariances, | ||
matching.typesWithVariances | ||
) | ||
|
||
def variancesMatchQualityMetric(typVariances: Seq[Variance], suprVariances: Seq[Variance]): Int = | ||
typVariances.zip(suprVariances).map { case (v1, v2) => varianceMatchQualityMetric(v1, v2) }.sum | ||
|
||
def varianceMatchQualityMetric(typVariance: Variance, suprVariance: Variance): Int = | ||
(typVariance, suprVariance) match { | ||
case (Covariance(typParam), Covariance(suprParam)) => | ||
typeMatchQualityMetric(typParam, suprParam) | ||
case (Contravariance(typParam), Contravariance(suprParam)) => | ||
typeMatchQualityMetric(suprParam, typParam) | ||
case (Invariance(typParam), Invariance(suprParam)) => | ||
typeMatchQualityMetric(typParam, suprParam) + typeMatchQualityMetric(suprParam, typParam) | ||
case (v1, v2) => // Treating not matching variances as invariant | ||
val typParam = v1.typ | ||
val suprParam = v2.typ | ||
typeMatchQualityMetric(typParam, suprParam) + typeMatchQualityMetric(suprParam, typParam) | ||
} | ||
|
||
/** Classes thet generally mean loss of some information */ | ||
final val avoid = Set( | ||
"Any", | ||
"Object", | ||
"AnyVal", | ||
"AnyRef", | ||
"Matchable" | ||
).map(TypeName.apply) | ||
|
||
/** Matching constants */ | ||
final val aLotCost = 1000000 | ||
final val losingInformationCost = 10000 | ||
final val losingVarInformationCost = 3000 | ||
final val varToConcreteCost = 200 | ||
final val concreteToVarCost = 5000 | ||
final val andOrOrTypeCost = 50 | ||
final val dealiasCost = 2 | ||
final val subTypeCost = 4 | ||
final val typeLambdaCost = 1 | ||
final val varToVarCost = 1 | ||
|
||
val p = new ScalaExternalSignaturePrettifier | ||
|
||
/** Returns match quality metric for two typelikes | ||
* the lower the metric value, the better the match | ||
*/ | ||
def typeMatchQualityMetric(typ: TypeLike, supr: TypeLike): Int = { | ||
(typ, supr) match { | ||
case (t: Type, s: Type) if t.isStarProjection && s.isStarProjection => | ||
varToVarCost | ||
case (t: Type, _) if t.isStarProjection => | ||
varToConcreteCost | ||
case (_, s: Type) if s.isStarProjection => | ||
concreteToVarCost | ||
case (AndType(left, right), supr) => | ||
andOrOrTypeCost + (typeMatchQualityMetric(left, supr) min typeMatchQualityMetric(right, supr)) | ||
case (typ, AndType(left, right)) => | ||
andOrOrTypeCost + (typeMatchQualityMetric(typ, left) min typeMatchQualityMetric(typ, right)) | ||
case (OrType(left, right), supr) => | ||
andOrOrTypeCost + (typeMatchQualityMetric(left, supr) min typeMatchQualityMetric(right, supr)) | ||
case (typ, OrType(left, right)) => | ||
andOrOrTypeCost + (typeMatchQualityMetric(typ, left) min typeMatchQualityMetric(typ, right)) | ||
case (typ: TypeLambda, supr: TypeLambda) => | ||
val dummyTypes = genDummyTypes(typ.args.size) | ||
val typResult = substituteBindings(typ.result, typ.args.flatMap(_.itid).zip(dummyTypes).toMap) | ||
val suprResult = substituteBindings(supr.result, supr.args.flatMap(_.itid).zip(dummyTypes).toMap) | ||
typeLambdaCost + typeMatchQualityMetric(typResult, suprResult) | ||
case (_: TypeLambda, _) => | ||
aLotCost | ||
case (_, _: TypeLambda) => | ||
aLotCost | ||
case (typ: Type, supr: Type) if typ.isVariable && typ.isGeneric && supr.isVariable && supr.isGeneric => | ||
varToVarCost + variancesMatchQualityMetric(typ.params, supr.params) | ||
case (typ: Type, supr: Type) if typ.isVariable && typ.isGeneric && supr.isGeneric => | ||
varToConcreteCost + variancesMatchQualityMetric(typ.params, supr.params) | ||
case (typ: Type, supr: Type) if supr.isVariable && supr.isGeneric && typ.isGeneric => | ||
concreteToVarCost + variancesMatchQualityMetric(typ.params, supr.params) | ||
case (typ: Type, supr: Type) if typ.isVariable && typ.isGeneric => | ||
losingVarInformationCost | ||
case (typ: Type, supr: Type) if supr.isVariable && supr.isGeneric => | ||
losingVarInformationCost | ||
case (typ: Type, supr: Type) if typ.isVariable && supr.isVariable => | ||
varToVarCost | ||
case (typ: Type, supr: Type) if typ.isVariable && supr.isGeneric => | ||
losingVarInformationCost | ||
case (typ: Type, supr: Type) if supr.isVariable && typ.isGeneric => | ||
losingVarInformationCost | ||
case (typ: Type, supr: Type) if supr.isVariable => | ||
concreteToVarCost | ||
case (typ: Type, supr: Type) if typ.isVariable => | ||
varToConcreteCost | ||
case (typ: Type, supr: Type) if typ.itid == supr.itid => | ||
variancesMatchQualityMetric(typ.params, supr.params) | ||
case (typ: Type, supr: Type) => | ||
db.typeAliases | ||
.get(typ.itid.get) | ||
.toList | ||
.flatMap(alias => dealias(typ, alias)) | ||
.map((_, supr, dealiasCost)) | ||
.++( | ||
db.typeAliases.get(supr.itid.get).toList.flatMap(alias => dealias(supr, alias)).map((typ, _, dealiasCost)) | ||
) | ||
.++(db.types.get(typ.itid.get).toList.flatMap(node => specializeParents(typ, node)).map { | ||
case t: Type if t.isGeneric != typ.isGeneric || avoid.contains(t.name) => | ||
(t, supr, losingInformationCost) | ||
case t => (t, supr, subTypeCost) | ||
}) | ||
.map { | ||
case (t, s, cost) => cost + typeMatchQualityMetric(t, s) | ||
} | ||
.minOption | ||
.getOrElse(aLotCost) | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.