From 27f900356beb3398ed449f74e89fdffa480a4af7 Mon Sep 17 00:00:00 2001 From: monsterkrampe Date: Thu, 29 Oct 2020 12:23:13 +0100 Subject: [PATCH 1/5] add very basic disjunction support in api model --- .../rulewerk/core/model/api/Disjunction.java | 40 ++++++++ .../rulewerk/core/model/api/Rule.java | 11 ++- .../model/implementation/DisjunctionImpl.java | 95 +++++++++++++++++++ .../model/implementation/Expressions.java | 19 +++- .../core/model/implementation/RuleImpl.java | 32 +++++-- .../core/model/implementation/Serializer.java | 45 ++++++--- 6 files changed, 216 insertions(+), 26 deletions(-) create mode 100644 rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java create mode 100644 rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java new file mode 100644 index 000000000..533569108 --- /dev/null +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java @@ -0,0 +1,40 @@ +package org.semanticweb.rulewerk.core.model.api; + +/*- + * #%L + * Rulewerk Core Components + * %% + * Copyright (C) 2018 - 2020 Rulewerk Developers + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.util.List; + +/** + * Interface for representing disjunctions of {@link Conjunctions}s. + * + * @author Lukas Gerlach + * + */ +public interface Disjunction> extends Iterable, SyntaxObject { + + /** + * Returns the list of conjunctions that are part of this disjunction. + * + * @return list of conjunctions + */ + List getConjunctions(); + +} diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java index 9187282eb..af93c63d8 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,18 +26,19 @@ * specifying quantifiers. All variables in the body are considered universally * quantified; all variables in the head that do not occur in the body are * considered existentially quantified. - * + * * @author Markus Krötzsch + * @author Lukas Gerlach * */ public interface Rule extends SyntaxObject, Statement { /** - * Returns the conjunction of head literals (the consequence of the rule). + * Returns the disjunction of conjunctions of head literals (the consequence of the rule). * * @return conjunction of literals */ - Conjunction getHead(); + Disjunction> getHead(); /** * Returns the conjunction of body literals (the premise of the rule). diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java new file mode 100644 index 000000000..8541cb692 --- /dev/null +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java @@ -0,0 +1,95 @@ +package org.semanticweb.rulewerk.core.model.implementation; + +/*- + * #%L + * Rulewerk Core Components + * %% + * Copyright (C) 2018 - 2020 Rulewerk Developers + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.Validate; +import org.semanticweb.rulewerk.core.model.api.Disjunction; +import org.semanticweb.rulewerk.core.model.api.Conjunction; +import org.semanticweb.rulewerk.core.model.api.Literal; +import org.semanticweb.rulewerk.core.model.api.Term; + +/** + * Simple implementation of {@link Disjunction}. + * + * @author Lukas Gerlach + */ +public class DisjunctionImpl> implements Disjunction { + + final List conjunctions; + + /** + * Constructor. + * + * @param conjunctions a non-null list of conjunctions, that cannot contain null + * elements. + */ + public DisjunctionImpl(List conjunctions) { + Validate.noNullElements(conjunctions); + this.conjunctions = conjunctions; + } + + @Override + public List getConjunctions() { + return Collections.unmodifiableList(this.conjunctions); + } + + @Override + public Stream getTerms() { + return this.conjunctions.stream().flatMap(c -> c.getTerms()).distinct(); + } + + @Override + public int hashCode() { + return this.conjunctions.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Disjunction)) { + return false; + } + final Disjunction other = (Disjunction) obj; + return this.conjunctions.equals(other.getConjunctions()); + } + + @Override + public Iterator iterator() { + return getConjunctions().iterator(); + } + + @Override + public String toString() { + return Serializer.getSerialization(serializer -> serializer.writeDisjunction(this)); + } + +} diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java index 1d465c4b1..0f01a9b73 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,6 +26,7 @@ import org.semanticweb.rulewerk.core.model.api.AbstractConstant; import org.semanticweb.rulewerk.core.model.api.Conjunction; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.DatatypeConstant; import org.semanticweb.rulewerk.core.model.api.ExistentialVariable; import org.semanticweb.rulewerk.core.model.api.Fact; @@ -43,6 +44,7 @@ * in Rulewerk. * * @author Markus Krötzsch + * @author Lukas Gerlach * */ @@ -330,7 +332,7 @@ public static Conjunction makePositiveConjunction(final Positiv * @return a {@link Rule} corresponding to the input */ public static Rule makeRule(final PositiveLiteral headLiteral, final Literal... bodyLiterals) { - return new RuleImpl(new ConjunctionImpl<>(Arrays.asList(headLiteral)), + return new RuleImpl(new DisjunctionImpl<>(Arrays.asList(new ConjunctionImpl<>(Arrays.asList(headLiteral)))), new ConjunctionImpl<>(Arrays.asList(bodyLiterals))); } @@ -345,6 +347,17 @@ public static Rule makeRule(final Conjunction head, final Conju return new RuleImpl(head, body); } + /** + * Creates a {@code Rule}. + * + * @param head disjunction of conjunctions of positive (non-negated) literals + * @param body conjunction of literals (negated or not) + * @return a {@link Rule} corresponding to the input + */ + public static Rule makeRule(final Disjunction> head, final Conjunction body) { + return new RuleImpl(head, body); + } + /** * Creates a {@link Rule}. * diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java index 15f35d27e..de63cfc8b 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java @@ -1,6 +1,7 @@ package org.semanticweb.rulewerk.core.model.implementation; import java.util.Set; +import java.util.Arrays; import java.util.stream.Collectors; /*- @@ -12,9 +13,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,6 +28,7 @@ import org.apache.commons.lang3.Validate; import org.semanticweb.rulewerk.core.model.api.Conjunction; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.Literal; import org.semanticweb.rulewerk.core.model.api.PositiveLiteral; import org.semanticweb.rulewerk.core.model.api.Rule; @@ -37,14 +39,15 @@ /** * Implementation for {@link Rule}. Represents rules with non-empty heads and * bodies. - * + * * @author Irina Dragoste + * @author Lukas Gerlach * */ public class RuleImpl implements Rule { final Conjunction body; - final Conjunction head; + final Disjunction> head; /** * Creates a Rule with a non-empty body and an non-empty head. All variables in @@ -57,11 +60,28 @@ public class RuleImpl implements Rule { * head conjuncts. */ public RuleImpl(final Conjunction head, final Conjunction body) { + this(new DisjunctionImpl<>(Arrays.asList(head)), body); + } + + /** + * Creates a Rule with a non-empty body and an non-empty head. All variables in + * the body must be universally quantified; all variables in the head that do + * not occur in the body must be existentially quantified. + * + * @param head list of conjunctions of Literals (negated or non-negated) representing the rule + * body conjuncts. + * @param body list of positive (non-negated) Literals representing the rule + * head conjuncts. + */ + public RuleImpl(final Disjunction> head, final Conjunction body) { Validate.notNull(head); Validate.notNull(body); Validate.notEmpty(body.getLiterals(), "Empty rule body not supported. Use Fact objects to assert unconditionally true atoms."); - Validate.notEmpty(head.getLiterals(), + // Validate.notEmpty(head.getConjunctions(), + // "Empty rule head not supported. To capture integrity constraints, use a dedicated predicate that represents a contradiction."); + // TODO: does this really suffice? + Validate.notEmpty(head.getConjunctions().stream().flatMap(c -> c.getLiterals().stream()).collect(Collectors.toList()), "Empty rule head not supported. To capture integrity constraints, use a dedicated predicate that represents a contradiction."); if (body.getExistentialVariables().count() > 0) { throw new IllegalArgumentException( @@ -109,7 +129,7 @@ public String toString() { } @Override - public Conjunction getHead() { + public Disjunction> getHead() { return this.head; } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java index 741aba0a5..fed2c4f53 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java @@ -12,9 +12,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -35,6 +35,7 @@ import org.semanticweb.rulewerk.core.model.api.Conjunction; import org.semanticweb.rulewerk.core.model.api.DataSourceDeclaration; import org.semanticweb.rulewerk.core.model.api.DatatypeConstant; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.ExistentialVariable; import org.semanticweb.rulewerk.core.model.api.Fact; import org.semanticweb.rulewerk.core.model.api.LanguageStringConstant; @@ -52,11 +53,11 @@ /** * Objects of this class are used to create string representations of syntactic * objects. - * + * * @see RuleWerk * rule syntax - * + * * @author Markus Kroetzsch * */ @@ -95,7 +96,7 @@ public interface SerializationWriter { /** * Runtime exception used to report errors that occurred in visitors that do not * declare checked exceptions. - * + * * @author Markus Kroetzsch * */ @@ -115,7 +116,7 @@ public IOException getIoException() { /** * Auxiliary class to visit {@link Term} objects for writing. - * + * * @author Markus Kroetzsch * */ @@ -185,7 +186,7 @@ public Void visit(NamedNull term) { /** * Auxiliary class to visit {@link Statement} objects for writing. - * + * * @author Markus Kroetzsch * */ @@ -225,7 +226,7 @@ public Void visit(DataSourceDeclaration statement) { /** * Construct a serializer that uses a specific function to serialize IRIs. - * + * * @param writer the object used to write serializations * @param iriTransformer a function used to abbreviate IRIs, e.g., if namespace * prefixes were declared @@ -238,7 +239,7 @@ public Serializer(final Writer writer, final Function iriTransfo /** * Construct a serializer that serializes IRIs without any form of * transformation or abbreviation. - * + * * @param writer the object used to write serializations */ public Serializer(final Writer writer) { @@ -248,7 +249,7 @@ public Serializer(final Writer writer) { /** * Construct a serializer that uses the given {@link PrefixDeclarationRegistry} * to abbreviate IRIs. - * + * * @param writer the object used to write serializations * @param prefixDeclarationRegistry the object used to abbreviate IRIs */ @@ -301,7 +302,7 @@ public void writeRule(Rule rule) throws IOException { * @throws IOException */ private void writeRuleNoStatment(Rule rule) throws IOException { - writeLiteralConjunction(rule.getHead()); + writeDisjunction(rule.getHead()); writer.write(" :- "); writeLiteralConjunction(rule.getBody()); } @@ -377,6 +378,26 @@ public void writeLiteralConjunction(final Conjunction literal } } + /** + * Writes a serialization of the given {@link Disjunction} of {@link Conjunction} + * objects. + * + * @param conjunctions a {@link Disjunction} + * @throws IOException + */ + public void writeDisjunction(final Disjunction conjunctions) throws IOException { + boolean first = true; + for (final Conjunction conjunction : conjunctions.getConjunctions()) { + if (first) { + first = false; + } else { + // TODO: think about notation again + writer.write("; "); + } + writeLiteralConjunction(conjunction); + } + } + /** * Writes a serialization of the given {@link Predicate}. This serialization * specifies the name and arity of the predicate. @@ -550,7 +571,7 @@ public void writeCommand(Command command) throws IOException { /** * Convenience method for obtaining serializations as Java strings. - * + * * @param writeAction a function that accepts a {@link Serializer} and produces * a string * @return serialization string From f96b7581e93f0994bfc6af9110aeabebe619a217 Mon Sep 17 00:00:00 2001 From: monsterkrampe Date: Fri, 30 Oct 2020 15:12:32 +0100 Subject: [PATCH 2/5] use inheritance structure instead of union interfaces --- .../rulewerk/core/model/api/Conjunction.java | 17 ++++++--- .../rulewerk/core/model/api/Disjunction.java | 3 +- .../rulewerk/core/model/api/Literal.java | 24 ++++++++++--- .../core/model/api/NegativeLiteral.java | 6 ++-- .../core/model/api/PositiveLiteral.java | 6 ++-- .../rulewerk/core/model/api/Rule.java | 2 +- .../implementation/AbstractLiteralImpl.java | 13 ++++--- .../model/implementation/ConjunctionImpl.java | 21 +++++++---- .../model/implementation/DisjunctionImpl.java | 12 ++++--- .../model/implementation/Expressions.java | 36 +++++++++++-------- .../implementation/NegativeLiteralImpl.java | 11 ++++-- .../implementation/PositiveLiteralImpl.java | 12 +++++-- .../core/model/implementation/RuleImpl.java | 23 +++--------- .../core/model/implementation/Serializer.java | 4 +-- 14 files changed, 118 insertions(+), 72 deletions(-) diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Conjunction.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Conjunction.java index f7b8b760f..95579814d 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Conjunction.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Conjunction.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,22 +21,29 @@ */ import java.util.List; +import java.util.Arrays; /** * Interface for representing conjunctions of {@link Literal}s, i.e., lists of * (negated or positive) atomic formulas that are connected with logical AND. * Conjunctions may have free variables, since they contain no quantifiers. - * + * * @author Markus Krötzsch + * @author Lukas Gerlach * */ -public interface Conjunction extends Iterable, SyntaxObject { +public interface Conjunction extends Disjunction>, Iterable { /** * Returns the list of literals that are part of this conjunction. - * + * * @return list of literals */ List getLiterals(); + @Override + default List> getConjunctions() { + return Arrays.asList(this); + } + } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java index 533569108..1cc0144a6 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java @@ -28,7 +28,8 @@ * @author Lukas Gerlach * */ -public interface Disjunction> extends Iterable, SyntaxObject { +// TODO: extend iterable over conjunctions too? (conflicts with Conjunction because this extends Iterable for Literal) +public interface Disjunction> extends SyntaxObject { /** * Returns the list of conjunctions that are part of this disjunction. diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java index b345b070d..acbf614aa 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,6 +21,8 @@ */ import java.util.List; +import java.util.Arrays; +import java.util.Iterator; /** * Interface for literals. A positive literal is simply an atomic formula, i.e., @@ -30,14 +32,18 @@ * * @author david.carral@tu-dresden.de * @author Irina Dragoste + * @author Lukas Gerlach */ -public interface Literal extends SyntaxObject { + +// TODO: this is not ideal since PositiveLiteral now also extends Conjunction +// while it should really extend Conjunction (but maybe this is not too much of an issue...) +public interface Literal extends Conjunction { boolean isNegated(); /** * The literal predicate. - * + * * @return the literal predicate. */ Predicate getPredicate(); @@ -50,4 +56,14 @@ public interface Literal extends SyntaxObject { */ List getArguments(); + // @Override + // default List getLiterals() { + // return Arrays.asList(this); + // } + + @Override + default Iterator iterator() { + return getLiterals().iterator(); + } + } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java index df5c6e6b0..c2f4f15c5 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,7 @@ * #L% */ -public interface NegativeLiteral extends Literal { +public interface NegativeLiteral extends Literal { @Override default boolean isNegated() { diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java index 6c4598a77..966a57826 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,7 @@ * #L% */ -public interface PositiveLiteral extends Literal { +public interface PositiveLiteral extends Literal { @Override default boolean isNegated() { diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java index af93c63d8..4ca4fdf6d 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java @@ -45,6 +45,6 @@ public interface Rule extends SyntaxObject, Statement { * * @return conjunction of literals */ - Conjunction getBody(); + Disjunction> getBody(); } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/AbstractLiteralImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/AbstractLiteralImpl.java index 4ee1b98e0..e9a05596c 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/AbstractLiteralImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/AbstractLiteralImpl.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,6 +26,7 @@ import java.util.stream.Stream; import org.apache.commons.lang3.Validate; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.Literal; import org.semanticweb.rulewerk.core.model.api.Predicate; import org.semanticweb.rulewerk.core.model.api.Term; @@ -38,8 +39,9 @@ * * @author david.carral@tu-dresden.de * @author Markus Krötzsch + * @author Lukas Gerlach */ -public abstract class AbstractLiteralImpl implements Literal { +public abstract class AbstractLiteralImpl implements Literal { private final Predicate predicate; private final List terms; @@ -82,9 +84,12 @@ public boolean equals(final Object obj) { if (obj == null) { return false; } - if (!(obj instanceof Literal)) { + if (!(obj instanceof Disjunction)) { return false; } + if (!(obj instanceof Literal)) { + return obj.equals(this); + } final Literal other = (Literal) obj; return this.isNegated() == other.isNegated() && this.getPredicate().equals(other.getPredicate()) diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java index 6da458d75..7f1fd23af 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,12 +27,13 @@ import org.apache.commons.lang3.Validate; import org.semanticweb.rulewerk.core.model.api.Conjunction; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.Literal; import org.semanticweb.rulewerk.core.model.api.Term; /** * Simple implementation of {@link Conjunction}. - * + * * @author Markus Krötzsch */ public class ConjunctionImpl implements Conjunction { @@ -41,7 +42,7 @@ public class ConjunctionImpl implements Conjunction { /** * Constructor. - * + * * @param literals a non-null list of literals, that cannot contain null * elements. */ @@ -62,7 +63,9 @@ public Stream getTerms() { @Override public int hashCode() { - return this.literals.hashCode(); + return this.literals.size() == 1 + ? this.literals.get(0).hashCode() + : this.literals.hashCode(); } @Override @@ -73,9 +76,15 @@ public boolean equals(Object obj) { if (obj == null) { return false; } - if (!(obj instanceof Conjunction)) { + if (!(obj instanceof Disjunction)) { return false; } + if (!(obj instanceof Conjunction)) { + // final Disjunction> disjunction = (Disjunction>) obj; + // final List> disjuncts = disjunction.getConjunctions(); + // return disjuncts.size() == 1 && this.equals(disjuncts.get(0)); + return obj.equals(this); + } final Conjunction other = (Conjunction) obj; return this.literals.equals(other.getLiterals()); } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java index 8541cb692..80c6aca46 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java @@ -64,7 +64,9 @@ public Stream getTerms() { @Override public int hashCode() { - return this.conjunctions.hashCode(); + return this.conjunctions.size() == 1 + ? this.conjunctions.get(0).hashCode() + : this.conjunctions.hashCode(); } @Override @@ -82,10 +84,10 @@ public boolean equals(Object obj) { return this.conjunctions.equals(other.getConjunctions()); } - @Override - public Iterator iterator() { - return getConjunctions().iterator(); - } + // @Override + // public Iterator iterator() { + // return getConjunctions().iterator(); + // } @Override public String toString() { diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java index 0f01a9b73..4992c2cea 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java @@ -303,6 +303,26 @@ public static Conjunction makeConjunction(final Literal... literals) { return new ConjunctionImpl<>(Arrays.asList(literals)); } + /** + * Creates a {@link Disjunction} of {@code T} ({@link Conjunction} type) objects. + * + * @param conjunctions list of non-null conjunctions + * @return a {@link Disjunction} corresponding to the input + */ + public static > Disjunction makeDisjunction(final List conjunctions) { + return new DisjunctionImpl<>(conjunctions); + } + + /** + * Creates a {@code Disjunction} of {@link Conjunction} objects. + * + * @param conjunctions list of non-null conjunctions + * @return a {@link Disjunction} corresponding to the input + */ + public static > Disjunction makeDisjunction(final T... conjunctions) { + return new DisjunctionImpl<>(Arrays.asList(conjunctions)); + } + /** * Creates a {@code Conjunction} of {@code T} ({@link PositiveLiteral} type) * objects. @@ -332,19 +352,7 @@ public static Conjunction makePositiveConjunction(final Positiv * @return a {@link Rule} corresponding to the input */ public static Rule makeRule(final PositiveLiteral headLiteral, final Literal... bodyLiterals) { - return new RuleImpl(new DisjunctionImpl<>(Arrays.asList(new ConjunctionImpl<>(Arrays.asList(headLiteral)))), - new ConjunctionImpl<>(Arrays.asList(bodyLiterals))); - } - - /** - * Creates a {@code Rule}. - * - * @param head conjunction of positive (non-negated) literals - * @param body conjunction of literals (negated or not) - * @return a {@link Rule} corresponding to the input - */ - public static Rule makeRule(final Conjunction head, final Conjunction body) { - return new RuleImpl(head, body); + return new RuleImpl(headLiteral, new ConjunctionImpl<>(Arrays.asList(bodyLiterals))); } /** @@ -354,7 +362,7 @@ public static Rule makeRule(final Conjunction head, final Conju * @param body conjunction of literals (negated or not) * @return a {@link Rule} corresponding to the input */ - public static Rule makeRule(final Disjunction> head, final Conjunction body) { + public static Rule makeRule(final Disjunction> head, final Disjunction> body) { return new RuleImpl(head, body); } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java index d4efc8496..fcb01d744 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,15 +21,20 @@ */ import java.util.List; +import java.util.Arrays; import org.semanticweb.rulewerk.core.model.api.NegativeLiteral; import org.semanticweb.rulewerk.core.model.api.Predicate; import org.semanticweb.rulewerk.core.model.api.Term; -public class NegativeLiteralImpl extends AbstractLiteralImpl implements NegativeLiteral { +public class NegativeLiteralImpl extends AbstractLiteralImpl implements NegativeLiteral { public NegativeLiteralImpl(final Predicate predicate, final List terms) { super(predicate, terms); } + @Override + public List getLiterals() { + return Arrays.asList(this); + } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java index dc0892e78..b81332723 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,14 +21,20 @@ */ import java.util.List; +import java.util.Arrays; import org.semanticweb.rulewerk.core.model.api.PositiveLiteral; import org.semanticweb.rulewerk.core.model.api.Predicate; import org.semanticweb.rulewerk.core.model.api.Term; -public class PositiveLiteralImpl extends AbstractLiteralImpl implements PositiveLiteral { +public class PositiveLiteralImpl extends AbstractLiteralImpl implements PositiveLiteral { public PositiveLiteralImpl(final Predicate predicate, final List terms) { super(predicate, terms); } + + @Override + public List getLiterals() { + return Arrays.asList(this); + } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java index de63cfc8b..a8c8539af 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java @@ -46,23 +46,9 @@ */ public class RuleImpl implements Rule { - final Conjunction body; + final Disjunction> body; final Disjunction> head; - /** - * Creates a Rule with a non-empty body and an non-empty head. All variables in - * the body must be universally quantified; all variables in the head that do - * not occur in the body must be existentially quantified. - * - * @param head list of Literals (negated or non-negated) representing the rule - * body conjuncts. - * @param body list of positive (non-negated) Literals representing the rule - * head conjuncts. - */ - public RuleImpl(final Conjunction head, final Conjunction body) { - this(new DisjunctionImpl<>(Arrays.asList(head)), body); - } - /** * Creates a Rule with a non-empty body and an non-empty head. All variables in * the body must be universally quantified; all variables in the head that do @@ -73,10 +59,11 @@ public RuleImpl(final Conjunction head, final Conjunction> head, final Conjunction body) { + public RuleImpl(final Disjunction> head, final Disjunction> body) { Validate.notNull(head); Validate.notNull(body); - Validate.notEmpty(body.getLiterals(), + // Validate.notEmpty(body.getLiterals(), + Validate.notEmpty(body.getConjunctions().stream().flatMap(c -> c.getLiterals().stream()).collect(Collectors.toList()), "Empty rule body not supported. Use Fact objects to assert unconditionally true atoms."); // Validate.notEmpty(head.getConjunctions(), // "Empty rule head not supported. To capture integrity constraints, use a dedicated predicate that represents a contradiction."); @@ -134,7 +121,7 @@ public Disjunction> getHead() { } @Override - public Conjunction getBody() { + public Disjunction> getBody() { return this.body; } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java index fed2c4f53..8073daf34 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java @@ -304,7 +304,7 @@ public void writeRule(Rule rule) throws IOException { private void writeRuleNoStatment(Rule rule) throws IOException { writeDisjunction(rule.getHead()); writer.write(" :- "); - writeLiteralConjunction(rule.getBody()); + writeDisjunction(rule.getBody()); } /** @@ -392,7 +392,7 @@ public void writeDisjunction(final Disjunction conjunctio first = false; } else { // TODO: think about notation again - writer.write("; "); + writer.write(" | "); } writeLiteralConjunction(conjunction); } From 9a9eb78f9962e0564669f22de8398282dbd1618c Mon Sep 17 00:00:00 2001 From: monsterkrampe Date: Fri, 30 Oct 2020 15:33:26 +0100 Subject: [PATCH 3/5] adjust other packages according to core changes --- .../parser/RuleParserParseFactTest.java | 2 +- .../reasoner/vlog/ModelToVLogConverter.java | 18 ++++++++++++++---- .../reasoner/vlog/VLogKnowledgeBase.java | 17 ++++++++++------- .../rulewerk/reasoner/vlog/VLogReasoner.java | 9 ++++++--- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/rulewerk-parser/src/test/java/org/semanticweb/rulewerk/parser/RuleParserParseFactTest.java b/rulewerk-parser/src/test/java/org/semanticweb/rulewerk/parser/RuleParserParseFactTest.java index 378382700..7e3a674c3 100644 --- a/rulewerk-parser/src/test/java/org/semanticweb/rulewerk/parser/RuleParserParseFactTest.java +++ b/rulewerk-parser/src/test/java/org/semanticweb/rulewerk/parser/RuleParserParseFactTest.java @@ -90,7 +90,7 @@ public void parseRule_namedNullInBody_throws() throws ParsingException { public void parseRule_namedNullInHead_succeeds() throws ParsingException { String input = "q(_:head) :- p(\"a\") ."; Rule result = RuleParser.parseRule(input); - Literal literal = result.getHead().getLiterals().get(0); + Literal literal = result.getHead().getConjunctions().get(0).getLiterals().get(0); assertArgumentIsNamedNull(literal, 1); } } diff --git a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java index 3fe63160a..d67998272 100644 --- a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java +++ b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,6 +26,7 @@ import org.semanticweb.rulewerk.core.exceptions.RulewerkRuntimeException; import org.semanticweb.rulewerk.core.model.api.Conjunction; import org.semanticweb.rulewerk.core.model.api.Constant; +import org.semanticweb.rulewerk.core.model.api.Disjunction; import org.semanticweb.rulewerk.core.model.api.Fact; import org.semanticweb.rulewerk.core.model.api.Literal; import org.semanticweb.rulewerk.core.model.api.NamedNull; @@ -126,8 +127,17 @@ static karmaresearch.vlog.Atom[] toVLogAtomArray(final Conjunction conjunctio } static karmaresearch.vlog.Rule toVLogRule(final Rule rule) { - final karmaresearch.vlog.Atom[] vLogHead = toVLogAtomArray(rule.getHead()); - final karmaresearch.vlog.Atom[] vLogBody = toVLogAtomArray(rule.getBody()); + // TODO: what to do for disjunctions? + final Disjunction headDisjunction = rule.getHead(); + final Disjunction bodyDisjunction = rule.getBody(); + if (!(headDisjunction instanceof Conjunction) || !(bodyDisjunction instanceof Conjunction)) { + throw new IllegalArgumentException("Disjunctions are currently not supported for vlog bindings."); + } + final Conjunction headConjunction = (Conjunction) headDisjunction; + final Conjunction bodyConjunction = (Conjunction) bodyDisjunction; + + final karmaresearch.vlog.Atom[] vLogHead = toVLogAtomArray(headConjunction); + final karmaresearch.vlog.Atom[] vLogBody = toVLogAtomArray(bodyConjunction); return new karmaresearch.vlog.Rule(vLogHead, vLogBody); } diff --git a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogKnowledgeBase.java b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogKnowledgeBase.java index 9f41cc7c9..dd1cfb8ed 100644 --- a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogKnowledgeBase.java +++ b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogKnowledgeBase.java @@ -32,6 +32,7 @@ import java.util.Set; import org.semanticweb.rulewerk.core.exceptions.RulewerkRuntimeException; +import org.semanticweb.rulewerk.core.model.api.Conjunction; import org.semanticweb.rulewerk.core.model.api.DataSource; import org.semanticweb.rulewerk.core.model.api.DataSourceDeclaration; import org.semanticweb.rulewerk.core.model.api.Fact; @@ -193,14 +194,16 @@ public Void visit(final Fact fact) { @Override public Void visit(final Rule statement) { VLogKnowledgeBase.this.rules.add(statement); - for (final PositiveLiteral positiveLiteral : statement.getHead()) { - final Predicate predicate = positiveLiteral.getPredicate(); - if (!VLogKnowledgeBase.this.idbPredicates.contains(predicate)) { - if (VLogKnowledgeBase.this.edbPredicates.containsKey(predicate)) { - addEdbAlias(VLogKnowledgeBase.this.edbPredicates.get(predicate)); - VLogKnowledgeBase.this.edbPredicates.remove(predicate); + for (final Conjunction conjunction : statement.getHead().getConjunctions()) { + for (final PositiveLiteral positiveLiteral : conjunction) { + final Predicate predicate = positiveLiteral.getPredicate(); + if (!VLogKnowledgeBase.this.idbPredicates.contains(predicate)) { + if (VLogKnowledgeBase.this.edbPredicates.containsKey(predicate)) { + addEdbAlias(VLogKnowledgeBase.this.edbPredicates.get(predicate)); + VLogKnowledgeBase.this.edbPredicates.remove(predicate); + } + VLogKnowledgeBase.this.idbPredicates.add(predicate); } - VLogKnowledgeBase.this.idbPredicates.add(predicate); } } return null; diff --git a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogReasoner.java b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogReasoner.java index 7547ae05c..0a52704c4 100644 --- a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogReasoner.java +++ b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/VLogReasoner.java @@ -32,6 +32,7 @@ import org.semanticweb.rulewerk.core.exceptions.IncompatiblePredicateArityException; import org.semanticweb.rulewerk.core.exceptions.ReasonerStateException; import org.semanticweb.rulewerk.core.exceptions.RulewerkRuntimeException; +import org.semanticweb.rulewerk.core.model.api.Conjunction; import org.semanticweb.rulewerk.core.model.api.DataSource; import org.semanticweb.rulewerk.core.model.api.DataSourceDeclaration; import org.semanticweb.rulewerk.core.model.api.Fact; @@ -429,7 +430,7 @@ private void warnUnknownPredicate(final PositiveLiteral query) { /** * Utility method copied from {@link karmaresearch.vlog.VLog}. - * + * * @FIXME This should be provided by VLog and made visible to us rather than * being copied here. * @param terms @@ -677,8 +678,10 @@ public void onStatementsRemoved(List statementsRemoved) { Set getKnowledgeBasePredicates() { final Set toBeQueriedHeadPredicates = new HashSet<>(); for (final Rule rule : this.knowledgeBase.getRules()) { - for (final Literal literal : rule.getHead()) { - toBeQueriedHeadPredicates.add(literal.getPredicate()); + for (final Conjunction conjunction : rule.getHead().getConjunctions()) { + for (final Literal literal : conjunction) { + toBeQueriedHeadPredicates.add(literal.getPredicate()); + } } } for (final DataSourceDeclaration dataSourceDeclaration : this.knowledgeBase.getDataSourceDeclarations()) { From 9acefa05dd4d62f6d0a279e345f08547c6daf50e Mon Sep 17 00:00:00 2001 From: monsterkrampe Date: Tue, 3 Nov 2020 16:26:08 +0100 Subject: [PATCH 4/5] clean up and explain previous adjustments some more --- .../rulewerk/core/model/api/Disjunction.java | 3 +- .../rulewerk/core/model/api/Literal.java | 15 ++++--- .../core/model/api/NegativeLiteral.java | 7 ++++ .../core/model/api/PositiveLiteral.java | 8 ++++ .../rulewerk/core/model/api/Rule.java | 6 +-- .../model/implementation/ConjunctionImpl.java | 3 -- .../model/implementation/DisjunctionImpl.java | 6 --- .../model/implementation/Expressions.java | 41 +++++++------------ .../implementation/NegativeLiteralImpl.java | 6 --- .../implementation/PositiveLiteralImpl.java | 6 --- .../core/model/implementation/RuleImpl.java | 4 +- .../core/model/implementation/Serializer.java | 2 +- 12 files changed, 46 insertions(+), 61 deletions(-) diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java index 1cc0144a6..1dd7299c0 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Disjunction.java @@ -23,12 +23,11 @@ import java.util.List; /** - * Interface for representing disjunctions of {@link Conjunctions}s. + * Interface for representing disjunctions of {@link Conjunction}s. * * @author Lukas Gerlach * */ -// TODO: extend iterable over conjunctions too? (conflicts with Conjunction because this extends Iterable for Literal) public interface Disjunction> extends SyntaxObject { /** diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java index acbf614aa..157d5790f 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Literal.java @@ -35,8 +35,16 @@ * @author Lukas Gerlach */ -// TODO: this is not ideal since PositiveLiteral now also extends Conjunction +// this would also be possible (including other changes) +// but it is not ideal since PositiveLiteral now also extends Conjunction // while it should really extend Conjunction (but maybe this is not too much of an issue...) +// +// public interface Literal extends Conjunction { + +// this produces a so called RawType when used without type argument, which seems to be generally considered +// bad practice because some type checking is not done for such types +// maybe this would not be an issue for us... +// what we actually would need is a self referential type that we can pass to Conjunction... public interface Literal extends Conjunction { boolean isNegated(); @@ -56,11 +64,6 @@ public interface Literal extends Conjunction { */ List getArguments(); - // @Override - // default List getLiterals() { - // return Arrays.asList(this); - // } - @Override default Iterator iterator() { return getLiterals().iterator(); diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java index c2f4f15c5..80f9cd76d 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/NegativeLiteral.java @@ -20,6 +20,9 @@ * #L% */ +import java.util.List; +import java.util.Arrays; + public interface NegativeLiteral extends Literal { @Override @@ -27,4 +30,8 @@ default boolean isNegated() { return true; } + @Override + default List getLiterals() { + return Arrays.asList(this); + } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java index 966a57826..fce744b4d 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/PositiveLiteral.java @@ -20,10 +20,18 @@ * #L% */ +import java.util.List; +import java.util.Arrays; + public interface PositiveLiteral extends Literal { @Override default boolean isNegated() { return false; } + + @Override + default List getLiterals() { + return Arrays.asList(this); + } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java index 4ca4fdf6d..60fab00c0 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/api/Rule.java @@ -36,14 +36,14 @@ public interface Rule extends SyntaxObject, Statement { /** * Returns the disjunction of conjunctions of head literals (the consequence of the rule). * - * @return conjunction of literals + * @return disjunction of conjunctions of positive literals */ Disjunction> getHead(); /** - * Returns the conjunction of body literals (the premise of the rule). + * Returns the disjunction of conjunctions of body literals (the premise of the rule). * - * @return conjunction of literals + * @return disjunction of conjunctions of literals */ Disjunction> getBody(); diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java index 7f1fd23af..3599afd08 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/ConjunctionImpl.java @@ -80,9 +80,6 @@ public boolean equals(Object obj) { return false; } if (!(obj instanceof Conjunction)) { - // final Disjunction> disjunction = (Disjunction>) obj; - // final List> disjuncts = disjunction.getConjunctions(); - // return disjuncts.size() == 1 && this.equals(disjuncts.get(0)); return obj.equals(this); } final Conjunction other = (Conjunction) obj; diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java index 80c6aca46..1a7b641e6 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/DisjunctionImpl.java @@ -21,7 +21,6 @@ */ import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.stream.Stream; import java.util.stream.Collectors; @@ -84,11 +83,6 @@ public boolean equals(Object obj) { return this.conjunctions.equals(other.getConjunctions()); } - // @Override - // public Iterator iterator() { - // return getConjunctions().iterator(); - // } - @Override public String toString() { return Serializer.getSerialization(serializer -> serializer.writeDisjunction(this)); diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java index 4992c2cea..f9173f56b 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.semanticweb.rulewerk.core.model.api.AbstractConstant; import org.semanticweb.rulewerk.core.model.api.Conjunction; @@ -303,26 +304,6 @@ public static Conjunction makeConjunction(final Literal... literals) { return new ConjunctionImpl<>(Arrays.asList(literals)); } - /** - * Creates a {@link Disjunction} of {@code T} ({@link Conjunction} type) objects. - * - * @param conjunctions list of non-null conjunctions - * @return a {@link Disjunction} corresponding to the input - */ - public static > Disjunction makeDisjunction(final List conjunctions) { - return new DisjunctionImpl<>(conjunctions); - } - - /** - * Creates a {@code Disjunction} of {@link Conjunction} objects. - * - * @param conjunctions list of non-null conjunctions - * @return a {@link Disjunction} corresponding to the input - */ - public static > Disjunction makeDisjunction(final T... conjunctions) { - return new DisjunctionImpl<>(Arrays.asList(conjunctions)); - } - /** * Creates a {@code Conjunction} of {@code T} ({@link PositiveLiteral} type) * objects. @@ -359,7 +340,7 @@ public static Rule makeRule(final PositiveLiteral headLiteral, final Literal... * Creates a {@code Rule}. * * @param head disjunction of conjunctions of positive (non-negated) literals - * @param body conjunction of literals (negated or not) + * @param body disjunction of conjunctions of literals (negated or not) * @return a {@link Rule} corresponding to the input */ public static Rule makeRule(final Disjunction> head, final Disjunction> body) { @@ -373,11 +354,19 @@ public static Rule makeRule(final Disjunction> head * @param body conjunction of positive (non-negated) literals * @return a {@link Rule} corresponding to the input */ - public static Rule makePositiveLiteralsRule(final Conjunction head, - final Conjunction body) { - final List bodyLiteralList = new ArrayList<>(body.getLiterals()); - final Conjunction literalsBody = makeConjunction(bodyLiteralList); - return new RuleImpl(head, literalsBody); + public static Rule makePositiveLiteralsRule(final Disjunction> head, + final Disjunction> body) { + + // TODO: can we find a better solution? + // already spent quite some time here, though... + // one idea was to make Rule Generic, but this is not really nice it seems... + final List> bodyDisjuncts = body.getConjunctions().stream() + .map(c -> makeConjunction(c.getLiterals())) + .collect(Collectors.toList()); + + final Disjunction> bodyDisjunction = new DisjunctionImpl(bodyDisjuncts); + + return makeRule(head, bodyDisjunction); } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java index fcb01d744..3e67b4928 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/NegativeLiteralImpl.java @@ -21,7 +21,6 @@ */ import java.util.List; -import java.util.Arrays; import org.semanticweb.rulewerk.core.model.api.NegativeLiteral; import org.semanticweb.rulewerk.core.model.api.Predicate; @@ -32,9 +31,4 @@ public class NegativeLiteralImpl extends AbstractLiteralImpl im public NegativeLiteralImpl(final Predicate predicate, final List terms) { super(predicate, terms); } - - @Override - public List getLiterals() { - return Arrays.asList(this); - } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java index b81332723..fcdcad8eb 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/PositiveLiteralImpl.java @@ -21,7 +21,6 @@ */ import java.util.List; -import java.util.Arrays; import org.semanticweb.rulewerk.core.model.api.PositiveLiteral; import org.semanticweb.rulewerk.core.model.api.Predicate; @@ -32,9 +31,4 @@ public class PositiveLiteralImpl extends AbstractLiteralImpl im public PositiveLiteralImpl(final Predicate predicate, final List terms) { super(predicate, terms); } - - @Override - public List getLiterals() { - return Arrays.asList(this); - } } diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java index a8c8539af..57755f0cb 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/RuleImpl.java @@ -55,9 +55,9 @@ public class RuleImpl implements Rule { * not occur in the body must be existentially quantified. * * @param head list of conjunctions of Literals (negated or non-negated) representing the rule - * body conjuncts. - * @param body list of positive (non-negated) Literals representing the rule * head conjuncts. + * @param body list of conjunctions of positive (non-negated) Literals representing the rule + * body conjuncts. */ public RuleImpl(final Disjunction> head, final Disjunction> body) { Validate.notNull(head); diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java index 8073daf34..120dae709 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Serializer.java @@ -387,7 +387,7 @@ public void writeLiteralConjunction(final Conjunction literal */ public void writeDisjunction(final Disjunction conjunctions) throws IOException { boolean first = true; - for (final Conjunction conjunction : conjunctions.getConjunctions()) { + for (final Conjunction conjunction : conjunctions.getConjunctions()) { if (first) { first = false; } else { From 4fcc03a267c33e17f3cb2e338250d13067f5a34f Mon Sep 17 00:00:00 2001 From: monsterkrampe Date: Tue, 24 Nov 2020 19:40:15 +0100 Subject: [PATCH 5/5] implement basic disjunction support for rulewerk-parser --- .../model/implementation/Expressions.java | 13 ++++++++ .../rulewerk/parser/javacc/JavaCCParser.jj | 32 ++++++++++++++++--- .../reasoner/vlog/ModelToVLogConverter.java | 6 ++-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java index f9173f56b..3a3c11b3f 100644 --- a/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java +++ b/rulewerk-core/src/main/java/org/semanticweb/rulewerk/core/model/implementation/Expressions.java @@ -304,6 +304,19 @@ public static Conjunction makeConjunction(final Literal... literals) { return new ConjunctionImpl<>(Arrays.asList(literals)); } + /** + * Creates a {@link Disjunction} of {@link Conjunction}s of {@code T} ({@link Literal} type) objects. + * + * @param literals list of lists of non-null literals + * @return a {@link Disjunction} corresponding to the input + */ + public static Disjunction> makeDisjunction(final List> literals) { + final List> disjuncts = literals.stream() + .map(c -> makeConjunction(c)) + .collect(Collectors.toList()); + return new DisjunctionImpl<>(disjuncts); + } + /** * Creates a {@code Conjunction} of {@code T} ({@link PositiveLiteral} type) * objects. diff --git a/rulewerk-parser/src/main/java/org/semanticweb/rulewerk/parser/javacc/JavaCCParser.jj b/rulewerk-parser/src/main/java/org/semanticweb/rulewerk/parser/javacc/JavaCCParser.jj index cc7568888..fb229f651 100644 --- a/rulewerk-parser/src/main/java/org/semanticweb/rulewerk/parser/javacc/JavaCCParser.jj +++ b/rulewerk-parser/src/main/java/org/semanticweb/rulewerk/parser/javacc/JavaCCParser.jj @@ -174,7 +174,7 @@ Command command() throws PrefixDeclarationException : { | LOOKAHEAD(predicateName() < ARITY >) predicateName = predicateName() arity = < ARITY > < COLON > arguments = Arguments() < DOT > { arguments.addFirst(Argument.term(Expressions.makeDatatypeConstant(predicateName + "[" + arity.image + "]:", PrefixDeclarationRegistry.XSD_STRING))); return new Command(name.image,arguments); - } + } | arguments = Arguments() < DOT > { return new Command(name.image,arguments); } | pn = < PNAME_NS > arguments = Arguments() < DOT > { arguments.addFirst(Argument.term(Expressions.makeDatatypeConstant(pn.image, PrefixDeclarationRegistry.XSD_STRING))); @@ -204,10 +204,10 @@ Rule rule() throws PrefixDeclarationException : { } Rule ruleNoDot() throws PrefixDeclarationException : { - List < PositiveLiteral > head; - List < Literal > body; + List < List < PositiveLiteral > > head; + List < List < Literal > > body; } { - head = listOfPositiveLiterals(FormulaContext.HEAD) < ARROW > body = listOfLiterals(FormulaContext.BODY) { + head = listOfPositiveConjunctions(FormulaContext.HEAD) < ARROW > body = listOfConjunctions(FormulaContext.BODY) { // check that the intersection between headExiVars and BodyVars is empty for (String variable : headExiVars) { if (bodyVars.contains(variable)) @@ -220,10 +220,28 @@ Rule ruleNoDot() throws PrefixDeclarationException : { throw new ParseException("Unsafe rule " + head + " :- " + body + "\nUniversal variable " + variable + " occurs in head but not in body."); } - return Expressions.makeRule(Expressions.makePositiveConjunction(head), Expressions.makeConjunction(body)); + return Expressions.makeRule(Expressions.makeDisjunction(head), Expressions.makeDisjunction(body)); } } +List < List < PositiveLiteral > > listOfPositiveConjunctions(FormulaContext context) throws PrefixDeclarationException : { + List < PositiveLiteral > l; + List < List < PositiveLiteral > > list = new ArrayList < List < PositiveLiteral > > (); +} { + l = listOfPositiveLiterals(context) { list.add(l); } ( < LOGICAL_OR > l = listOfPositiveLiterals(context) { list.add(l); } )* { + return list; + } +} + +List < List < Literal > > listOfConjunctions(FormulaContext context) throws PrefixDeclarationException : { + List < Literal > l; + List < List < Literal > > list = new ArrayList < List < Literal > > (); +} { + l = listOfLiterals(context) { list.add(l); } ( < LOGICAL_OR > l = listOfLiterals(context) { list.add(l); } )* { + return list; + } +} + List < PositiveLiteral > listOfPositiveLiterals(FormulaContext context) throws PrefixDeclarationException : { PositiveLiteral l; List < PositiveLiteral > list = new ArrayList < PositiveLiteral > (); @@ -557,6 +575,10 @@ MORE : { < ARROW : ":-" > } +< DEFAULT, BODY > TOKEN : { + < LOGICAL_OR : "|" > +} + < DEFAULT, BODY, DIRECTIVE_ARGUMENTS > TOKEN : { < TILDE : "~" > } diff --git a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java index d67998272..61719b0db 100644 --- a/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java +++ b/rulewerk-vlog/src/main/java/org/semanticweb/rulewerk/reasoner/vlog/ModelToVLogConverter.java @@ -130,11 +130,11 @@ static karmaresearch.vlog.Rule toVLogRule(final Rule rule) { // TODO: what to do for disjunctions? final Disjunction headDisjunction = rule.getHead(); final Disjunction bodyDisjunction = rule.getBody(); - if (!(headDisjunction instanceof Conjunction) || !(bodyDisjunction instanceof Conjunction)) { + if (headDisjunction.getConjunctions().size() != 1 || bodyDisjunction.getConjunctions().size() != 1) { throw new IllegalArgumentException("Disjunctions are currently not supported for vlog bindings."); } - final Conjunction headConjunction = (Conjunction) headDisjunction; - final Conjunction bodyConjunction = (Conjunction) bodyDisjunction; + final Conjunction headConjunction = headDisjunction.getConjunctions().get(0); + final Conjunction bodyConjunction = bodyDisjunction.getConjunctions().get(0); final karmaresearch.vlog.Atom[] vLogHead = toVLogAtomArray(headConjunction); final karmaresearch.vlog.Atom[] vLogBody = toVLogAtomArray(bodyConjunction);