From 0dc8a53fcab06dd59a053f17cb3b3dab96fd5b43 Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Thu, 7 Jan 2021 20:47:10 +0100 Subject: [PATCH] Cartesian product as Stream --- pom.xml | 10 +- .../typeinference/constraints/Constraint.java | 1 + .../constraints/ConstraintSet2.java | 107 ++++++++++++++++++ .../constraints/ConstraintSetBuilder.java | 26 +++++ .../constraints/OderConstraint.java | 24 ++++ .../typeinference/ConstraintSetTests.java | 62 ++++++++++ 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet2.java create mode 100644 src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSetBuilder.java create mode 100644 src/main/java/de/dhbwstuttgart/typeinference/constraints/OderConstraint.java create mode 100644 src/test/java/typeinference/ConstraintSetTests.java diff --git a/pom.xml b/pom.xml index 95b20386..bb00efae 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,15 @@ http://maven.apache.org/maven-v4_0_0.xsd"> - + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java index 8715fe55..cbd5c8fa 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/Constraint.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +//TODO: Remove this class public class Constraint extends HashSet { private static final long serialVersionUID = 1L; private Boolean isInherited = false;//wird nur für die Method-Constraints benoetigt diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet2.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet2.java new file mode 100644 index 00000000..ded3ecfb --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSet2.java @@ -0,0 +1,107 @@ +package de.dhbwstuttgart.typeinference.constraints; + + +import java.util.*; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class ConstraintSet2 { + Set oderConstraints = new HashSet<>(); + + public ConstraintSet2(Set constraints){ + if(constraints.isEmpty())throw new RuntimeException("Empty constraint set"); + this.oderConstraints = constraints; + } + + @Override + public String toString(){ + BinaryOperator b = (x,y) -> x+y; + return "ODER:" + this.oderConstraints.stream().reduce("", (x,y) -> x.toString()+ "\n" +y, b); + } + + private class ConstraintSpliterator implements Spliterator> { + private List constraints; + private long i = 0; + private long max = 0; + private List sizes; + private List bases = new ArrayList<>(); + + ConstraintSpliterator(List constraints){ + this.constraints = constraints; + sizes = constraints.stream().map(OderConstraint::getSize).collect(Collectors.toList()); + long base = 1; + for(int size : sizes){ + bases.add(base); + base *= size; + } + i = 0; + max = estimateSize() - 1; + } + + ConstraintSpliterator(List constraints, long start, long end){ + this(constraints); + i = start; + max = end; + } + + @Override + public boolean tryAdvance(Consumer> consumer) { + if(i > max) return false; + consumer.accept(get(i)); + i++; + return true; + } + + private Set get(long num){ + Set ret = new HashSet<>(); + Iterator baseIt = bases.iterator(); + for(OderConstraint constraint : constraints){ + ret.addAll(constraint.get((int) ((num/baseIt.next())%constraint.getSize()))); + } + return ret; + } + + @Override + public Spliterator> trySplit() { + if(max - i < 2) return null; + long middle = i + ((max- i) / 2); + long maxOld = max; + max = middle - 1; + return new ConstraintSpliterator(constraints, middle, maxOld); + } + + @Override + public long estimateSize() { + long ret = 1; + for (int size : sizes)ret*=size; + return ret; + } + + @Override + public int characteristics() { + return ORDERED | SIZED | IMMUTABLE | NONNULL; + } + } + + public Stream> cartesianProductParallel(){ + return StreamSupport.stream(new ConstraintSpliterator(oderConstraints.stream().collect(Collectors.toList())), true); + } +/* + public Map generateTPHMap() { + HashMap ret = new HashMap<>(); + constraints.map((Pair p) -> { + if (p.TA1 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA1).getName(), (TypePlaceholder) p.TA1); + } + if (p.TA2 instanceof TypePlaceholder) { + ret.put(((TypePlaceholder) p.TA2).getName(), (TypePlaceholder) p.TA2); + } + return null; + }); + return ret; + } +*/ +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSetBuilder.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSetBuilder.java new file mode 100644 index 00000000..377e2214 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/ConstraintSetBuilder.java @@ -0,0 +1,26 @@ +package de.dhbwstuttgart.typeinference.constraints; + +import java.util.HashSet; +import java.util.Set; + +public class ConstraintSetBuilder { + private Set undConstraints = new HashSet<>(); + private Set oderConstraints = new HashSet<>(); + private boolean done = false; + + public void addUndConstraint(Pair p){ + undConstraints.add(p); + } + + public void addOderConstraint(OderConstraint orConstraint) { + oderConstraints.add(orConstraint); + } + + public ConstraintSet2 build(){ + if(done)throw new RuntimeException("Trying to build cartesian product twice"); + this.done = true; + if(!undConstraints.isEmpty()) + oderConstraints.add(new OderConstraint(Set.of(undConstraints))); + return new ConstraintSet2(oderConstraints); + } +} diff --git a/src/main/java/de/dhbwstuttgart/typeinference/constraints/OderConstraint.java b/src/main/java/de/dhbwstuttgart/typeinference/constraints/OderConstraint.java new file mode 100644 index 00000000..70d880c1 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/typeinference/constraints/OderConstraint.java @@ -0,0 +1,24 @@ +package de.dhbwstuttgart.typeinference.constraints; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class OderConstraint { + private final List> cons; + public OderConstraint(Set> orCons){ + if(orCons.isEmpty())throw new RuntimeException("Empty constraint set"); + for(Set c : orCons){ + if(c.isEmpty())throw new RuntimeException("Empty constraint set"); + } + this.cons = orCons.stream().collect(Collectors.toList()); + } + + public int getSize(){ + return cons.size(); + } + + public Set get(int l) { + return cons.get(l); + } +} diff --git a/src/test/java/typeinference/ConstraintSetTests.java b/src/test/java/typeinference/ConstraintSetTests.java new file mode 100644 index 00000000..99863c8e --- /dev/null +++ b/src/test/java/typeinference/ConstraintSetTests.java @@ -0,0 +1,62 @@ +package typeinference; + +import de.dhbwstuttgart.parser.NullToken; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.typeinference.constraints.ConstraintSetBuilder; +import de.dhbwstuttgart.typeinference.constraints.OderConstraint; +import de.dhbwstuttgart.typeinference.constraints.Pair; +import org.junit.Test; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class ConstraintSetTests { + @Test + public void cartesianProductTestSingleConstraint(){ + ConstraintSetBuilder builder = new ConstraintSetBuilder(); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair())))); + List> result = builder.build().cartesianProductParallel().collect(Collectors.toList()); + assert result.size() == 1; + } + + @Test + public void cartesianProductTestSingleOderConstraint(){ + ConstraintSetBuilder builder = new ConstraintSetBuilder(); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + List> result = builder.build().cartesianProductParallel().collect(Collectors.toList()); + assert result.size() == 2; + } + + @Test + public void cartesianProductTestTwoOderConstraint(){ + ConstraintSetBuilder builder = new ConstraintSetBuilder(); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + List> result = builder.build().cartesianProductParallel().collect(Collectors.toList()); + assert result.size() == 4; + } + + @Test + public void cartesianProductTestThreeOderConstraint(){ + ConstraintSetBuilder builder = new ConstraintSetBuilder(); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + builder.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair())))); + List> result = builder.build().cartesianProductParallel().collect(Collectors.toList()); + assert result.size() == 4; + + ConstraintSetBuilder builder2 = new ConstraintSetBuilder(); + builder2.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + builder2.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + builder2.addOderConstraint(new OderConstraint(Set.of(Set.of(generatePair()), Set.of(generatePair())))); + List> result2 = builder2.build().cartesianProductParallel().collect(Collectors.toList()); + + assert result2.stream().map( a -> a.stream().map(p -> p.TA1.toString()).reduce("", (x, y)-> x+" "+y)).collect(Collectors.toSet()).size() == 8; + assert result2.size() == 8; + } + + public Pair generatePair(){ + return new Pair(TypePlaceholder.fresh(new NullToken()), TypePlaceholder.fresh(new NullToken())); + } +}