Code Monkey home page Code Monkey logo

2p-kt's People

Contributors

davidegreco avatar forrestone avatar gciatto avatar gilbocc avatar giordo94 avatar jasondellaluce avatar lanzonisilvia avatar lrizzato avatar mannbonn avatar paoloverdini1997 avatar renovate-bot avatar renovate[bot] avatar semantic-release-bot avatar siboxd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

2p-kt's Issues

Unification algorithm efficiency

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.

Clause isWellFormed

Actual implementation of Clauses 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.

Build failing because tests are failing

There are three jvm tests in TestReal class that are failing; their names are: creationAsNumbers2, comparisons, value.

This failure shold be investigated and solved.

Sets modelling is incorrect

Sadly, I modeled sets in a wrong way.

Currently, sets are modeled as follows:

  • N-Sized Set -> '{}'(Arg1, ..., ArgN), i.e., a struct whose functor is {} and whose arguments are the set items
    • for all N = 0, 1, 2, ...
  • the Empty Set is actually an Atom

But actually, their are modeled differently in Prolog:

  • Empty set -> Atom '{}'
  • 1-sized set with argument X -> Struct '{}'(X)
  • N-sized set with arguments X1, ..., Xn -> Struct '{}'(X) where X = (X1, ..., Xn) is a conjunction

So, for instance, unifying { 1, 2, 3 } with { 1, X }, is solved by X = (2, 3)

Using 2p-kt programmatically

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:

  1. Where is the programmatic entry point for adding a knowledge base and then querying the Prolog engine against this knowledge base. I have the knowledge base and the respective queries as a string representation.
  2. Which part of the library do I need for that (core, parser, theory, ...?)

Solve module: Signature vararg doesn't specify position

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.

Rename Scope.listOf to Scope.logicListOf

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.

strictlyEquals should check specific instance class

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.

ClauseDatabase clauses' checks

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 by call(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 in unification

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.

Hash maps should be used in RETE

Hashmaps are not currently used in it.unibo.tuprolog.theory.Rete but they should in order to reach better performances in accessing clauses

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.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
gitlabci
.gitlab-ci.yml
gradle
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/gradle-wrapper.properties
  • gradle 8.7
npm
package.json
  • semantic-release-preconfigured-conventional-commits 1.1.85
  • node 20.13

  • Check this box to trigger a request for Renovate to run again on this repository

NullPointerException when saving a file.

This popup shows up when trying to save a file.
image

Steps to reproduce:

  • create a new file
  • click File > Save As
  • save the file with .pl o .pro extension
  • click File > Save

Versions:

  • 2P-Kt v0.20.4-dev61+cbec54e9
  • JVM v17.0.3
  • JavaFX v19-ea+6
  • Kubuntu 21.10

Code Coverage reporting

Should be added a test code coverage tool to detect, in an automatic fashion, which parts of code are still not adequately tested.

Terms passing trough Scope should "absorb" variable bindings

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!

Support for user defined predicate true/1

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?

TuprologExceptions

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)

freshCopy() and same named variables

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.

RETE indexes should be finely tested

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 ClauseDatabases.

Let me here remark the intended meaning of the ReteTree API:

  • ReteTree.Companion.of should create a new tree out of the provided Clauses

    • The partial order among the provided clauses sharing the same functor & arity is of paramount importance
      • Such order affect the behaviour of 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.

    • An essential feature is that the partial ordering of clauses sharing the same functor & arity (w.r.t. insertion order) must be respected in the sequence.
  • 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.

    • An essential feature is that the partial ordering of clauses sharing the same functor & arity (w.r.t. insertion order) must be respected in the sequence.
  • 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 Clauses are returned within the sequence. Otherwise, if limit is non-negative the amount of Clauses actually returned by this method must be lower or equals to limit. In any case, all Clauses returned within the output sequence are removed from the current ReteTree and its internal nodes.

    • An essential feature is that the partial ordering of clauses sharing the same functor & arity (w.r.t. insertion order) must be respected.
  • ReteTree.clone(): ReteTree<*> produces a brand new deep copy of the current index---except for the indexed Clauses, for which only references are cloned. Each edit to returned index does not affect the original index.

Run JavaScript tests

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.

Example for reading prolog file, adding a clause and unifying

I am looking for an example of how to

  • Load a Prolog script,
  • Add few more facts to the load program programmatically
  • Find a solution to a resulting predicate

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

Substitution related method names

I think that more meaningful names should be given to methods that work with Substitutions

For example:

  1. In Substitution interface the method ground(term: Term) could be named substituteIn(term: Term) or applyIn(term: Term)
  2. In 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)

Unification bug, preventing it from termination

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.

Apply DRY principle in build.gradle files

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.

IDE: output box contents should be made copyable

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:

  • preferred approach: simply enable text selection and copying, in a standard way; OR
  • support mouse right-click with contextual menu providing a "copy" item; OR
  • just add a "copy" button (less general, somehow weird, but perhaps quicker to impement..?)

Total ordering of Terms

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:

  • All variables precede all floating-point numbers, which precede all integers, which precede all atoms, which precede all compound terms.
  • All variables are totally ordered but the order is implementation dependent and may vary during computations.
  • All numbers (of the same type) are ordered according to the usual arithmetic.
  • All atoms are ordered according to the characters forming their name and the character codes of the characters (an integer associated with each character). The null atom precedes all non-null atoms (hence 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 these
    values are equal, the tail character sequences are compared. Notice that the order induced by the character codes is implementation
    defined, except that the alphabetical order must be respected and the digits must be sequential. More details are provided in Section 9.1.3.
  • Compound terms are ordered according to their arity; if they have same arity, by the name of their functor. If they have same arity and same functor name, they are ordered by considering successively the order of their arguments starting from the first.
    • Example: g(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).

Indicator interface

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 a type, not a type alias

Substitution should be an interface, with maybe two implementations (to be studied how can be done):

  • an implementation SuccessSubstitution backed by a Map<Var, Term> with actual substitutions
  • a singleton implementation FailedSubstitution that will be "empty"

List.from and List.of should create different type of lists

There are two types of lists:

  • those terminated with an empty list terminator, also writeable as [E1, E2, E3]
  • those terminated with pipe operator [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 method

The 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)

KotlinTest testing suite

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.

Add some documentation comments

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.

Untested core changes

Some changes were made to core without testing them, and therefore:

  • Test the addition of method Substition.of(Iterable<Pair<Var, Term>>)
  • Test the addition of Constant interface
  • Test the addition of Term.isConstant property

Tests should be aligned.

Unifier.mgu infinite loop

I've found a problem that makes actual mgu implementation to go into infinite loop.

Steps to reproduce:

  1. Execute this code somewhere:
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!

Substitution.Success is a Unifier

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.