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 $name, bool $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 $name, int $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 $domain, string $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 $domain, string $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 $p, bool $q): bool {
return $p && $q;
}
/**
* Logical OR
*/
public function OR(bool $p, bool $q): bool {
return $p || $q;
}
/**
* Logical NOT
*/
public function NOT(bool $p): bool {
return !$p;
}
/**
* Logical IMPLIES
*/
public function IMPLIES(bool $p, bool $q): bool {
return !$p || $q;
}
}