4 ClassOf(Manuscript): Class
8 IndirectAncestor(Manuscript,Manuscript)
15 ! x : (ClassOf(x)=Copy) <=> ? y : CopiedBy(y,x) & VariantOf(y) = VariantOf(x).
16 ! x : (ClassOf(x)=Revert) <=> (ClassOf(x)~=Copy) & ? y : IndirectAncestor(y,x) & VariantOf(y) = VariantOf(x).
18 { !x y: IndirectAncestor(x,y) <- ?z: CopiedBy(x,z) & IndirectAncestor(z,y).
19 !x y: IndirectAncestor(x,y) <- ?z: CopiedBy(x,z) & CopiedBy(z,y). }
21 NbOfSources = #{x: ClassOf(x)=Source}.
22 NbOfReverts = #{x: ClassOf(x)=Revert}.
26 3 * NbOfSources + NbOfReverts
29 procedure minSourcesAndReverts(sample) {
30 stdoptions.groundwithbounds=false
31 stdoptions.symmetrybreaking="static"
32 stdoptions.cpsupport=true
34 return minimize(T3, sample, TotalCost)[1]
37 structure SClass : V3 {
38 Class = { copy; revert; source }
44 procedure addClasses(struct) {
45 idpintern.setvocabulary(struct,V3)
46 struct[V3::Class.type] = SClass[V3::Class.type]
47 struct[V3::Copy] = SClass[V3::Copy]
48 struct[V3::Revert] = SClass[V3::Revert]
49 struct[V3::Source] = SClass[V3::Source]
50 struct[V3::N.type] = range(0,#totable(struct[V::Manuscript.type]))
53 procedure findClasses(samples) {
55 for _,sample in ipairs(samples) do
56 local model = minSourcesAndReverts(sample)
58 table.insert(result,{ getGrouping(model), getClasses(model) })
60 table.insert(result,{ getGrouping(sample), {} })
66 procedure getClasses(model) {
68 for tuple in tuples(model[V3::ClassOf].graph.ct) do
69 local manuscript, class = tuple[1], tuple[2]
70 if classes[class] == nil then
71 classes[class] = {manuscript}
73 table.insert(classes[class],manuscript)