tuprolog / 2p-kt Goto Github PK
View Code? Open in Web Editor NEWA Kotlin Multi-Platform ecosystem for symbolic AI
Home Page: http://tuprolog.unibo.it
License: Apache License 2.0
A Kotlin Multi-Platform ecosystem for symbolic AI
Home Page: http://tuprolog.unibo.it
License: Apache License 2.0
The actual implementation of the unification algorithm was made following the first definition in this paper.
But after Section 3 in this paper, more efficient versions of the algorithm are proposed; in some future, will be a good thing to implement the more efficient version proposed.
Actual implementation of Clause
s sintactically allows any Term
as its body, but the Standard Prolog states that:
A well-formed body cannot contain a number.
So it would be nice to add a property isWellFormed
to Clause
that will detect if it's well formed or not.
There are three jvm tests in TestReal
class that are failing; their names are: creationAsNumbers2
, comparisons
, value
.
This failure shold be investigated and solved.
Sadly, I modeled sets in a wrong way.
Currently, sets are modeled as follows:
'{}'(Arg1, ..., ArgN)
, i.e., a struct whose functor is {}
and whose arguments are the set items
N = 0, 1, 2, ...
But actually, their are modeled differently in Prolog:
'{}'
X
-> Struct '{}'(X)
X1
, ..., Xn
-> Struct '{}'(X)
where X = (X1, ..., Xn)
is a conjunctionSo, for instance, unifying { 1, 2, 3 }
with { 1, X }
, is solved by X = (2, 3)
I wanted to use the library programmatically from Java. Sadly I couldn't find any specific information regarding this in the readme.md
or in the projects documentation (the respective page is empty).
So my questions are:
I think that Signature
is missing that in kotlin vararg
parameters can be in all positions of a method signature, not only in last position like in java.
So if vararg
support is for invoking even kotlin vararg methods, this class should be enhanched with a position of the vararg
.
Using A scope with method listOf
is misleading to Kotlin user that really wanted to create a kotlin List
.
Methods such as listOf()
and setOf()
that clash with library method names should be changed to logicListOf()
and logicSetOf()
.
Currently if you want to construct a tuple with tupleOf(Iterable<Term>)
you can't write tupleOf(listOf(atomOf("a"), atomOf("b")))
inside Scope scope, because the outermost argument is considered as a logic list, so it is one Term
an so Tuple
constructor complains throwing exception... But the user didn't want to create a logical list.
Now method stricltyEquals
checks if passed class is of one type or a subclass of it.
As it should be a strict check, we maybe should add a check to limit correct classes to the specific instance class.
From the Prolog Standard:
In a database all the clauses are well-formed (Section 2.2.3) and transformed, i.e. all variables
X
in the position of a predication in the body of the clauses have been replaced bycall(X)
and all the facts also have the form of a rule whose body is true. Thus all the clauses in a database have the form of a rule.
For example, the Clause
product (A) : - A, A
is stored in the database, after preparation for execution, as the term:product(A) :- call(A) , call(A)
Those transformation should be made during Clause
addition and/or Database creation.
A check on Clause
insertion should be added, to ensure that all contained clauses are well-formed
Anonymous variables during the unification process should be considered different even using the non-strict identity matcher.
They should always be considered different from each other unless they are the same instance.
Hashmaps are not currently used in it.unibo.tuprolog.theory.Rete
but they should in order to reach better performances in accessing clauses
Recently added TermVisitor
was not tested... tests for it should be added to ensure its correct functionality.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
org.jetbrains.kotlinx:kotlinx-coroutines-test
, org.jetbrains.kotlinx:kotlinx-coroutines-core
).github/workflows/build-and-deploy.yml
DanySK/are-secrets-available 1.0.0
actions/checkout v4.1.5
nicolasfara/precompute-semantic-release-version-action 1.0.2
DanySK/build-check-deploy-gradle-action 2.4.19
DanySK/action-checkout 0.2.17
DanySK/build-check-deploy-gradle-action 2.4.19
actions/checkout v4.1.5
DanySK/build-check-deploy-gradle-action 2.4.19
actions/checkout v4.1.5
actions/setup-node v4.0.2
DanySK/build-check-deploy-gradle-action 2.4.19
ubuntu 22.04
ubuntu 22.04
ubuntu 22.04
ubuntu 22.04
ubuntu 22.04
ubuntu 22.04
.github/workflows/dispatcher.yml
ubuntu 22.04
.github/workflows/test-extensively.yml
DanySK/action-checkout 0.2.17
DanySK/build-check-deploy-gradle-action 2.4.19
DanySK/action-checkout 0.2.17
DanySK/build-check-deploy-gradle-action 2.4.19
.gitlab-ci.yml
gradle.properties
settings.gradle.kts
com.gradle.enterprise 3.17.3
org.danilopianini.gradle-pre-commit-git-hooks 2.0.5
org.gradle.toolchains.foojay-resolver-convention 0.8.0
build.gradle.kts
bdd/gradle.properties
bdd/build.gradle.kts
core/gradle.properties
core/build.gradle.kts
datalog/gradle.properties
datalog/build.gradle.kts
documentation/gradle.properties
documentation/build.gradle.kts
dsl-core/gradle.properties
dsl-core/build.gradle.kts
dsl-solve/gradle.properties
dsl-solve/build.gradle.kts
dsl-theory/gradle.properties
dsl-theory/build.gradle.kts
dsl-unify/gradle.properties
dsl-unify/build.gradle.kts
full/gradle.properties
full/build.gradle.kts
gradle/libs.versions.toml
org.openjfx:javafx-base 19.0.2.1
org.openjfx:javafx-fxml 19.0.2.1
org.openjfx:javafx-controls 19.0.2.1
org.openjfx:javafx-graphics 19.0.2.1
com.fasterxml.jackson.core:jackson-core 2.17.1
com.fasterxml.jackson.dataformat:jackson-dataformat-xml 2.17.1
com.fasterxml.jackson.dataformat:jackson-dataformat-yaml 2.17.1
com.fasterxml.jackson.datatype:jackson-datatype-jsr310 2.17.1
com.github.ajalt.clikt:clikt 3.5.4
guru.nidi:graphviz-java 0.18.1
io.github.gciatto:kt-math 0.10.0
io.github.javaeden.orchid:OrchidDocs 0.21.1
io.github.javaeden.orchid:OrchidKotlindoc 0.21.1
io.github.javaeden.orchid:OrchidPluginDocs 0.21.1
net.sourceforge.plantuml:plantuml 1.2024.4
org.antlr:antlr4 4.13.1
org.antlr:antlr4-runtime 4.13.1
org.fxmisc.richtext:richtextfx 0.11.2
org.jetbrains.kotlinx:kotlinx-coroutines-core 1.6.4
org.jetbrains.kotlinx:kotlinx-coroutines-test 1.6.4
org.jetbrains.kotlin:kotlin-stdlib 1.9.24
org.jetbrains.kotlin:kotlin-stdlib-jdk8 1.9.24
org.jetbrains.kotlin:kotlin-stdlib-js 1.9.24
org.jetbrains.kotlin:kotlin-reflect 1.9.24
org.jetbrains.kotlin.jvm 1.9.24
org.danilopianini.git-sensitive-semantic-versioning 3.1.5
io.github.gciatto.kt-mpp.bug-finder 4.1.3
io.github.gciatto.kt-mpp.documentation 4.1.3
io.github.gciatto.kt-mpp.linter 4.1.3
io.github.gciatto.kt-mpp.maven-publish 4.1.3
io.github.gciatto.kt-mpp.npm-publish 4.1.3
io.github.gciatto.kt-mpp.versions 4.1.3
io.github.gciatto.kt-mpp.js-only 4.1.3
io.github.gciatto.kt-mpp.jvm-only 4.1.3
io.github.gciatto.kt-mpp.multiplatform 4.1.3
io.github.gciatto.kt-mpp.multi-project-helper 4.1.3
io.github.gciatto.kt-mpp.fat-jar 4.1.3
io.github.gciatto.gradle-mock-service 1.0.8
com.eden.orchidPlugin 0.21.1
ide/gradle.properties
ide/build.gradle.kts
ide-plp/gradle.properties
ide-plp/build.gradle.kts
io-lib/gradle.properties
io-lib/build.gradle.kts
oop-lib/gradle.properties
oop-lib/build.gradle.kts
parser-core/gradle.properties
parser-core/build.gradle.kts
parser-js/gradle.properties
parser-js/build.gradle.kts
parser-jvm/gradle.properties
parser-jvm/build.gradle.kts
parser-theory/gradle.properties
parser-theory/build.gradle.kts
repl/gradle.properties
repl/build.gradle.kts
serialize-core/gradle.properties
serialize-core/build.gradle.kts
serialize-theory/gradle.properties
serialize-theory/build.gradle.kts
solve/gradle.properties
solve/build.gradle.kts
solve-classic/gradle.properties
solve-classic/build.gradle.kts
solve-concurrent/gradle.properties
solve-concurrent/build.gradle.kts
solve-plp/gradle.properties
solve-plp/build.gradle.kts
solve-problog/gradle.properties
solve-problog/build.gradle.kts
solve-streams/gradle.properties
solve-streams/build.gradle.kts
test-dsl/gradle.properties
test-dsl/build.gradle.kts
test-solve/gradle.properties
test-solve/build.gradle.kts
theory/gradle.properties
theory/build.gradle.kts
unify/gradle.properties
unify/build.gradle.kts
utils/gradle.properties
utils/build.gradle.kts
gradle/wrapper/gradle-wrapper.properties
gradle 8.7
package.json
semantic-release-preconfigured-conventional-commits 1.1.85
node 20.13
Should be added a test code coverage tool to detect, in an automatic fashion, which parts of code are still not adequately tested.
I think that all Terms manipulated inside a Scope should absorb current variable bindings.
Actual situation:
val scope = Scope.of("X")
val scopeExternalStructWithXVariable = Struct.of("f", Var.of("X"))
println("Two different variables with same name should only be equals.")
println(scope["X"] === scopeExternalStructWithXVariable[0]) // false, correct
println(scope["X"] == scopeExternalStructWithXVariable[0]) // true, correct
println(scope["X"]?.strictlyEquals(scopeExternalStructWithXVariable[0])) // false, correct
val myFactCreatedTroughXScope = with(scope){
factOf(scopeExternalStructWithXVariable)
}
val structWithXVariableThatWalkedTroughXScope = myFactCreatedTroughXScope.head
println("\nExternal terms manipulated inside a scope, doesn't absorb variable bindings; is that misleading for final users?")
println(scope["X"] === structWithXVariableThatWalkedTroughXScope[0]) // false, maybe *expected* true by an API user??
println(scope["X"] == structWithXVariableThatWalkedTroughXScope[0]) // true, correct
println(scope["X"]?.strictlyEquals(structWithXVariableThatWalkedTroughXScope[0])) // false, maybe *expected* true by an API user??
Expected:
In my opinion all three last println
should print true!
A logging framework should be adopted to help debugging, of critical software parts. It should work in common code to be compiled in all destinaton platform languages.
Hello,
First of all, thanks for a great portable Prolog implementation.
I'm experimenting with reasoning in GDL. It's a subset of Prolog that is used to specify games for an AI to play.
The issue is that it requires the ability to assert some statements about a game using true/1
predicate, but it seems like even a simple example can't be handled by tuProlog.
If I create a file example.pdb
with the following contents:
true(_).
I'm getting the output:
# 2P-Kt version 0.18.1
# Error while parsing theory file: example.pdb
# Message: mismatched input '(' expecting {SIGN, ',', '|', FULL_STOP, OPERATOR}
# Line : 1
# Column : 5
# Clause : 0
# Successfully loaded library `prolog.io`
# Successfully loaded library `prolog.lang`
?-
I'm using 2p-repl-0.18.1-redist.jar
.
Can this issue be somehow solved?
In core
subproject there are two exceptions TuprologException
and TuprologRuntimeException
that extend the same base class Exception
.
Why they're not exteding one from each other? And why there are two exceptions?
In Kotlin all exceptions are unchecked an so in my opinion there's no need for a TuprologException
(checked exceptions only raise management problems, when used in Java, with no true benefit)
The method freshCopy()
for now doesn't take into account that if a Variable occurs multiple times in a Term
, then the same copied instance should be placed multiple times in the copy, to avoid creating diverging variables.
It is of paramount importance that RETE indexes (i.e. it.unibo.tuprolog.theory.ReteTree
) are finely tested in order to ensure each method work as intended.
Thus we should not merely test RETE indexes indirectly by testing ClauseDatabase
s.
Let me here remark the intended meaning of the ReteTree
API:
ReteTree.Companion.of
should create a new tree out of the provided Clause
s
ReteTree.get
, ReteTree.clauses
, ReteTree.remove
ReteTree.clauses: Sequence<Clause>
should return a sequence lazily iterating over all the clauses indexed by the current tree, there including directives.
ReteTree.get(Clause): Sequence<Clause>
should return a sequence lazily iterating over all the clauses indexed by the current tree which unify with Clause
according to the default unifier.
ReteTree.remove(Clause, Int): Sequence<Clause>
should return a sequence lazily iterating over all the clauses indexed by the current tree which unify with Clause
according to the default unifier. In case the second argument, namely limit
, is negative, then all possible Clause
s are returned within the sequence. Otherwise, if limit
is non-negative the amount of Clause
s actually returned by this method must be lower or equals to limit
. In any case, all Clause
s returned within the output sequence are removed from the current ReteTree
and its internal nodes.
ReteTree.clone(): ReteTree<*>
produces a brand new deep copy of the current index---except for the indexed Clause
s, for which only references are cloned. Each edit to returned index does not affect the original index.
Common code of each sub-project, should run tests on each target platform.
Running tests on JavaScript platform is not out-of-the-box like JVM testing.
A custom way to run tests over a JavaScript test framework should be found and integrated into the project.
More tests should be added for already present classes, to stress single methods and cover as much as possible all relevant lines of code.
I am looking for an example of how to
In details, let say I have a script main.pl
:
increment(A, B) :-
diff(C),
B is A + C.
Then I'd like to enhance it on Java side
Struct.of("diff", Integer.of(15));
and then run
Struct.of("increment", Atom.of(15), Integer.of("X"));
... something that the returns the value of X as an int
I think that more meaningful names should be given to methods that work with Substitution
s
For example:
Substitution
interface the method ground(term: Term)
could be named substituteIn(term: Term)
or applyIn(term: Term)
Term
interface the methods groundTo(substitution: Substitution)
could be named simply apply(substitution: Substitution)
Code before:
val substitutedTerm = myStruct.groundTo(mySubstitution)
val substitutedTerm = mySubstitution.ground(myStruct)
Code after:
val substitutedTerm = myStruct.apply(mySubstitution)
val substitutedTerm = mySubstitution.applyIn(myStruct) // mySubstitution.substituteIn(myStruct)
Var
default equals
should check complete name to help management of variables in Set
s and Map
s.
Should solve #180.
I've found a BUG in the implementation of AbstractUnificationStrategy
, in particular the implementation of applySubstitutionToEquations(...)
The bug prevents simple unification like (f(a,b(X)) :- b) = (f(A,B) :- C)
from being "solved", making the Unification strategy go into infinite loop.
The problem is due the use of ===
(aka referential equality) that is used to check if changes are made during Substitution
application; in fact applying a Substitution
always results in creation of new Struct
for example (because of the support to immutability); so even if actually no change is made, the function returns true
signaling changes and making the algorithm continue indefinitely.
The solution could be simply the change of referential equality with simple equality check, in that function.
Furthermore, a new test for this unification should be added to prevent future regression.
All of the build.gradle.kts
files now share an identical part that should be moved in a common place, to make changes consistent within all subprojects.
For example there is already an inconsistency between the multiplatform plugin version in core
subproject (1.3.31) and other subprojects (1.3.21); to avoid this, the common part could be placed in project root gradle file.
For some reason Gitlab CI is still using Gradle 5.4
version despite its updated to Gradle 5.5.1
in project gradle-wrapper.properties
In the 2p-kt IDE, the content of the solution box (and most likely of other similar boxes) cannot be copied for later pasting elsewhere. This is a pity, copying solutions (but also output, etc.) is often needed for documentation, debug, reports, etc.
Should be fixed in one of the following ways:
Now VarImpl
uses Int
as type for it's internal identifier field.
In intensive usage cases, the Int
value can overflow... BigInteger
would solve those problems once for all.
According to section 2.1.2 (page 6) of the Prolog standard, terms are totally ordered in a non-trivial way:
In Standard Prolog the terms are totally ordered according to the following rules which define the binary relation
term_precedes
.
More precisely:
z
precedes z_a
). An atom a1
precedes an atom a2
if the character code of the first character of a1
is less than the character code of the first character of a2
. If theseg(X)
precedes f(X, V)
, f(Z,b)
precedes f(a,A)
, according to the ASCII table given in Annex 11.3, but is after f(Z, a)
. f(Z, Z)
precedes f(X, X, X)
but its comparison with f(X, X)
depends on the processor (implementation dependent).There is yet another notable sort of structures that may deserve their own interface in core
: indicators.
A well formed indicator is a struct in the form '/'(F, N)
where F
is an atom and N
is a non negative integer.
Of course, variables may be accepted too in some cases.
Substitution
should be an interface, with maybe two implementations (to be studied how can be done):
SuccessSubstitution
backed by a Map<Var, Term>
with actual substitutionsFailedSubstitution
that will be "empty"There are two types of lists:
[E1, E2, E3]
[H1, H2 | T]
For creating lists now we have two factory methods in List
companion object:
List.of
: creates always an empty terminated list with given arguments (e.g the first type described above)List.from
: that can create both list types passing, or not, a terminal Term
to the methodThe second method should always create a "piped list" with last item, and leave the creation of empty terminated lists to List.of
only, to better separate their responsibilities (Single Responsibility Principle)
Scope.varOf("_")
should be treated as Scope.anonymous()
in my opinion.
Am I right?
KotlinTest is a powerful testing suite that could be adopted to make project tests more readable and expressive.
Among other feature it supports Property Based testing and Data Driven testing, two important features to be more declarative in testing.
Adopting this suite will mean migrating to JUnit 5 and therefore also rewriting part of the existing test structure to adapt to it.
In code there's no documtation, it would be better to document at least non-trivial/domain-specific "things" (methods, properties and classes) to shortly explain what they stand for.
https://www.quora.com/What-is-the-difference-between-the-integer-and-integral
We need another name, e.g. Int or Integer.
Avoiding clashes with standard libraries is also desired, but not strictly required
Some changes were made to core
without testing them, and therefore:
Substition.of(Iterable<Pair<Var, Term>>)
Constant
interfaceTerm.isConstant
propertyTests should be aligned.
A Constant
interface should be added, as shown in this UML, to be a superinterface of Atom
and Numeric
interfaces.
I've found a problem that makes actual mgu
implementation to go into infinite loop.
Steps to reproduce:
fun main() {
val myBuggyUnifier = Unifier.naive(Substitution.of("X", Atom.of("a")))
myBuggyUnifier.mgu(Atom.of("b"), Var.of("X"))
println("You'll never see this printed, until issue solved")
}
Expected behaviour: mgu
should return null
and the println
should be executed!
Since in this paper is stated
A solution of an equation, called a unifier, is any substitution ฯ, if it exists, which makes the two terms identical
So a Success
Substitution
should be called Unifier
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.