luni, 12 august 2024

Building with Gradle

1. Problem

Failed to calculate the value of task ':compileJava' property 'javaCompiler'.

Cannot find a Java installation on your machine matching this tasks requirements: {languageVersion=21, vendor=any, implementation=vendor-specific} for WINDOWS on x86_64.

No locally installed toolchains match and toolchain download repositories have not been configured.

Solution:

File > Setting > Build, Execution, Deployment > Build Tools > Gradle > Gradle JVM: <choose naother JDK> 


luni, 3 iunie 2024

Set-theoretical approach to Open-Closed Principle

Let's state the principle: "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" (see https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle).

Here are my personal thoughts on how to achieve that. 

Let's consider a "set-theoretical" approach. If we view a class as a set $A$ of lines of code. Then we must not modify the content of $A$. This represents the closure aspect.

However, to extend the functionality of $A$, we will need to modify certain parts of $A$.
Therefore, we must (1) extract those parts from $A$ as external sets, such as $B$, $C$, and so on.
Next, (2) establish relationships $R_1$, $R_2$ ... between the parts of $A$ where code was extracted and the new sets $B$ and $C$.

At this point, we have two options:

  1. Extending the functionality by modifying $B$, $C$, etc., would contradict the Open-Closed Principle for $B$, $C$, etc.
  2. Extending the functionality by introducing new sets (classes) such as $B'$, $C'$, etc., and defining relations $R_1$, $R_2$, etc., in a manner that allows seamless switching between $B$ and $B'$, $C$ and $C'$, etc.


I think option 2 aligns closely with the concept of "decoupling".

Mathematically, to enable the flexibility to switch between $B$ and $B'$, $C$ and $C'$, etc., the relations $R_1$, $R_2$, etc.,
must establish links between set $A$ and families of sets ${B, B', B'', ...}$, ${C, C', C'', ...}$, and so forth. Like set-valued mappings.

For example, the relation "use an object b of extendable class $B"$ is a solution. Because if we have inside $A$ the line

b.method1();
where b is of type B, then we can always replace b with an object of type B', where B' extends B.

A more explicit relationship might be described as "use an object b of interface B" or "use an object b of abstract class B". In light of the above, an interface serves as a relationship to a family or hierarchy of interfaces and classes that implement it.

A specific type of relation is the mapping, or function. If we put inside A the line

method1();
To extend the functionality of method1(), it must relate not only to its own body but also to a family of methods named method1(). This can be achieved using the template method pattern.

Possibly, the last part involving the mapping concept could be refined to "use a method that can be overridden".

Some links:

https://www.cs.utexas.edu/users/downing/papers/OCP-1996.pdf

joi, 23 mai 2024

GPT-2 in about 150 lines of Java

Found a very interesting post "GPT in 500 lines of SQL" (https://explainextended.com/2023/12/31/happy-new-year-15/) which was inspired from "GPT in 60 Lines of NumPy" (https://jaykmody.com/blog/gpt-from-scratch/). And of course I could not resist the temptation to do the same but in Java :-) In addition, "all I saw" in the source code were mostly matrix operations, which I like a lot.

image from https://www.mathsisfun.com/algebra/matrix-multiplying.html  

Thanks to Nd4j library which offers the same flexibility of working with matrices as NumPy, I managed to convert the source code from https://jaykmody.com/blog/gpt-from-scratch/ into about 150 lines of Java (https://github.com/Streeling/RD_Archive/tree/main/ams/gpt2-in-about-150-lines-of-nd4j).