Logical Representation in AI

Predicate Logic Representation with PHP

Predicate logic, also known as first-order logic (FOL), is a fundamental tool in AI used to represent complex relationships between objects and their properties. Unlike propositional logic, which deals with simple true/false statements, predicate logic allows reasoning about objects, their attributes, and their interconnections. This capability makes it an essential component in knowledge representation, expert systems, and automated reasoning.

Example of class Term:

 
<?php

namespace Apphp\MLKit\Reasoning\Logic\Predicate;

/**
 * Represents a term in predicate logic (variable or constant)
 */
class Term {
    private 
$name;
    private 
$isVariable;

    public function 
__construct(string $namebool $isVariable false) {
        
$this->name $name;
        
$this->isVariable $isVariable;
    }

    public function 
getName(): string {
        return 
$this->name;
    }

    public function 
isVariable(): bool {
        return 
$this->isVariable;
    }
}

Example of class Domain:

 
<?php

namespace Apphp\MLKit\Reasoning\Logic\Predicate;

/**
 * Represents a domain of discourse - the universe of objects
 */
class Domain {
    
/**
     * @var array
     */
    
private array $objects = [];

    
/**
     * @param string $name
     * @param array $properties
     * @return void
     * @psalm-suppress MixedArrayAssignment
     */
    
public function addObject(string $name, array $properties = []): void {
        
$this->objects[$name] = $properties;
    }

    
/**
     * @param string $name
     * @return array|null
     * @psalm-suppress MixedReturnStatement
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedInferredReturnType
     */
    
public function getObject(string $name): ?array {
        return 
$this->objects[$name] ?? null;
    }

    
/**
     * @return array
     * @psalm-suppress MixedReturnStatement
     * @psalm-suppress MixedInferredReturnType
     */
    
public function getAllObjects(): array {
        return 
$this->objects;
    }
}

Example of class Domain:

 
<?php

namespace Apphp\MLKit\Reasoning\Logic\Predicate;

/**
 * Represents a predicate (relation) in predicate logic
 */
class Predicate {
    private 
$name;
    private 
$arity;

    public function 
__construct(string $nameint $arity) {
        
$this->name $name;
        
$this->arity $arity;
    }

    public function 
getName(): string {
        return 
$this->name;
    }

    public function 
getArity(): int {
        return 
$this->arity;
    }
}

Example of class AtomicFormula:

 
<?php

namespace Apphp\MLKit\Reasoning\Logic\Predicate;

/**
 * Represents a predicate formula like P(x, y)
 */
class AtomicFormula {
    private 
Predicate $predicate;
    private array 
$terms = [];

    public function 
__construct(Predicate $predicate, array $terms) {
        
$this->predicate $predicate;

        
// Verify that the number of terms matches the predicate's arity
        
if (count($terms) !== $predicate->getArity()) {
            throw new 
\InvalidArgumentException(
                
"Predicate {$predicate->getName()} requires {$predicate->getArity()} terms, " .
                
count($terms) . ' provided.'
            
);
        }

        
$this->terms $terms;
    }

    public function 
getPredicate(): Predicate {
        return 
$this->predicate;
    }

    public function 
getTerms(): array {
        return 
$this->terms;
    }

    
/**
     * Evaluate the formula with variable assignments in a model
     */
    
public function evaluate(Domain $domain, array $assignment = []): bool {
        
$predicateName $this->predicate->getName();
        
$termValues = [];

        
// Resolve term values based on the assignment
        
foreach ($this->terms as $term) {
            if (
$term->isVariable()) {
                
// If it's a variable, get its value from the assignment
                
$termName $term->getName();
                if (!isset(
$assignment[$termName])) {
                    throw new 
\RuntimeException("No assignment for variable {$termName}");
                }
                
$termValues[] = $assignment[$termName];
            } else {
                
// If it's a constant, use it directly
                
$termValues[] = $term->getName();
            }
        }

        
// Custom evaluation logic based on predicate name
        
switch ($predicateName) {
            case 
'Human':
                
$object $domain->getObject($termValues[0]);
                return isset(
$object['type']) && $object['type'] === 'human';

            case 
'Mortal':
                
$object $domain->getObject($termValues[0]);
                return isset(
$object['mortal']) && $object['mortal'] === true;

            case 
'Dog':
                
$object $domain->getObject($termValues[0]);
                return isset(
$object['type']) && $object['type'] === 'dog';

            case 
'Mammal':
                
$object $domain->getObject($termValues[0]);
                return isset(
$object['mammal']) && $object['mammal'] === true;

            case 
'GreaterThan':
                return 
$termValues[0] > $termValues[1];

            case 
'Equals':
                return 
$termValues[0] === $termValues[1];

            default:
                throw new 
\RuntimeException("Unknown predicate: {$predicateName}");
        }
    }

    
/**
     * Render to string
     * @return string
     * @psalm-suppress MixedArgumentTypeCoercion
     * @psalm-suppress MixedMethodCall
     * @psalm-suppress MissingClosureReturnType
     */
    
public function __toString(): string {
        
$terms array_map(function ($term) {
            return 
$term->getName();
        }, 
$this->terms);

        return 
$this->predicate->getName() . '(' implode(', '$terms) . ')';
    }
}

Example of class PredicateLogic:

 
<?php

namespace Apphp\MLKit\Reasoning\Logic\Predicate;

/**
 * Logical connectives and quantifiers
 */
class PredicateLogic {
    
/**
     * Universal quantifier (∀x: P(x))
     * True if the formula is true for all possible values of the variable
     */
    
public function forAll(Domain $domainstring $varName, callable $formula): bool {
        
$objects $domain->getAllObjects();

        
/** @psalm-suppress MixedAssignment */
        
foreach ($objects as $objectName => $properties) {
            
$assignment = [$varName => $objectName];
            if (!
$formula($assignment)) {
                return 
false;
            }
        }

        return 
true;
    }

    
/**
     * Existential quantifier (∃x: P(x))
     * True if the formula is true for at least one value of the variable
     */
    
public function exists(Domain $domainstring $varName, callable $formula): bool {
        
$objects $domain->getAllObjects();

        
/** @psalm-suppress MixedAssignment */
        
foreach ($objects as $objectName => $properties) {
            
$assignment = [$varName => $objectName];
            if (
$formula($assignment)) {
                return 
true;
            }
        }

        return 
false;
    }

    
/**
     * Logical AND
     */
    
public function AND(bool $pbool $q): bool {
        return 
$p && $q;
    }

    
/**
     * Logical OR
     */
    
public function OR(bool $pbool $q): bool {
        return 
$p || $q;
    }

    
/**
     * Logical NOT
     */
    
public function NOT(bool $p): bool {
        return !
$p;
    }

    
/**
     * Logical IMPLIES
     */
    
public function IMPLIES(bool $pbool $q): bool {
        return !
$p || $q;
    }
}