• Stars
    star
    199
  • Rank 196,105 (Top 4 %)
  • Language
    Ruby
  • Created almost 16 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A pure Ruby gem implemention of a Prolog-like DSL for AI and logical programming.

ruby-prolog :: The Prolog-like DSL for Ruby

ruby-prolog allows you to solve complex logic problems on the fly using a dynamic, Prolog-like DSL inline with your normal Ruby code. Basic use is encompassed by stating basic facts using your data, defining rules, and then asking questions. Why is this cool? Because ruby-prolog allows you to leave your normal object-oriented vortex on demand and step into the alternate reality of declarative languages.

ruby-prolog has been used in projects ranging from complex realtime access control authorization in Rails apps, to headless 3D layout engines, and many other use cases.

With ruby-prolog:

  • There are no classes.
  • There are no functions.
  • There are no variables.
  • There are no control flow statements.

You can use all these wonder things -- it’s still Ruby after all -- but they’re not needed, and mainly useful for getting data and results into/out of the interpreter. Declarative langugaes like Prolog are often favored heavily in artificial intelligence and theorem proving applications and is also taught in computer science curricula, so I hope this updated release proves useful for your logic evaluation needs!

ruby-prolog is written using object-oriented-ish pure Ruby, and should work under all modern Ruby interpreters. Please report compatibility problems. The core engine is largely based on tiny_prolog, though numerous additional enhancements have been made such as object-oriented refactorings and integration of ideas from the interwebs. Unfortunately I cannot read Japanese and cannot give proper attribution to the original tiny_prolog author. (If you can, let me know and I'll update this document!)

Usage

Say you want to write the following Prolog code:

implication(a, b).
implication(b, c).
implication(c, d).
implication(c, x).

implies(A, B) :- implication(A, B).
implies(A, B) :- implication(A, Something), implies(Something, B).

Here's the equivalent Ruby code using this library:

db = RubyProlog.new do
  implication['a', 'b'].fact
  implication['b', 'c'].fact
  implication['c', 'd'].fact
  implication['c', 'x'].fact

  implies[:A, :B] << implication[:A, :B]
  implies[:A, :B] << [
    implication[:A, :Something],
    implies[:Something, :B]
  ]
end

Now you can run some queries:

# What are all the direct implications of 'c'?
db.query{ implication['c', :X] }
#=> [{ X: 'd' }, { X: 'x' }]

# What are all the things that can directly imply?
db.query{ implication[:X, :_] }
#=> [{ X: 'a' }, { X: 'b' }, { X: 'c' }, { X: 'c' }]

# What are all the things 'a' implies?
db.query{ implies['a', :X] }
#=> [{ X: 'b' }, { X: 'c' }, { X: 'd' }, { X: 'x' }]

Unfortunately if you have two predicates in a query, you can't just use a comma. There two ways to solve this problem:

# Solution 1: Use an array
db.query{[ implication['b', :S], implies[:S, :B] ]}

# Solution 2: Use a beneign assignment
db.query{_= implication['b', :S], implies[:S, :B] }

If you need to add to your database, you can call instance_eval:

db = RubyProlog.new do
  implication['a', 'b'].fact
  implication['b', 'c'].fact
end

# Later...
db.instance_eval do
  implication['c', 'd'].fact
  implication['c', 'x'].fact
end

This will mutate your database. If you want to "fork" your database instead, you can call db.clone, which will return a new instance with all stored data. Cloning like this is optimized to copy as little as possible.

to_prolog

If you're loading rules from a database, you might be generating predicates like this:

rules = Ruleset.find_by(org: ...).rules
db = RubyProlog.new do
  rules['permissions'].map do |role, perm|
    permission[role, perm].fact
  end
end

However, if something doesn't work, how do find out why?

This is where #to_prolog comes in handy. Just run it on your instance:

puts db.to_prolog

and you'll get something that looks like this:

permission('admin', 'invite').
permission('admin', 'ban').
permission('membe', 'create_post').

Then you can do a quick copy/paste into an environment like Tau Prolog's sandbox or SWISH and run some queries.

Examples

gem install ruby-prolog

Two runnable examples are included in the 'bin' directory. The first..

ruby-prolog-acls

..shows the ruby-prolog dynamic DSL used to trivially implement access control checks. The second..

ruby-prolog-hanoi

..is a ruby-prolog solution to the well-known "Towers of Hanoi" problem in computer science. It's not clear, but something Prolog hackers will be interested in. If you have other useful or clever examples, please send a pull request!

See the test/ directory for additional examples.

Features

  • Pure Ruby.
  • No wacko dependencies.
  • Tested with Ruby 2.0.0!
  • Object-oriented.
  • Multiple Prolog environments can be created and manipulated simultaneously.
  • Concurrent access to different core instances should be safe.
  • Concurrent access to a single core instance might probably explode in odd ways.

Development

$ git clone https://github.com/preston/ruby-prolog
$ cd ruby-prolog
$ bundle
$ rake test

License

Released under the Apache 2.0 license. Copyright (c) 2013-2022 Preston Lee. All rights reserved. https://prestonlee.com

More Repositories

1

journeta

A dirt simple library for peer discovery and message passing between Ruby applications on a LAN.
HTML
58
star
2

bittorious

An open source BitTorrent tracker and user management portal, supporting automatic RSS feed generation, role-based management, and real-time network monitoring.
HTML
55
star
3

homeboy

Homeboy is a set of small, plain BASH scripts to synchronize your personal config files, update system packages, upgrade development libraries, and pull git clones every morning in one shot by running `homeboy'.
Shell
34
star
4

space_elevator

Client for integrating a ruby application with a remote ActionCable-based backend provided by Rails 5 or compatible framework.
Ruby
32
star
5

projectx

Team project template for CST 200 at Arizona State University, Polytechnic campus.
16
star
6

asset_tracker

A simple web-based asset tracking system for small businesses written in Ruby on Rails (RoR). New equipment is assigned to a specific location and person who is notified of the responsibility. You may optionally add serial numbers and an arbitrary amount of notes to each asset. Configured to run on top of PostgreSQL and sendmail by default, though both are reconfigurable.
Ruby
15
star
7

angular-on-fhir

Angular 14 + bootstrap base project for SMART and other FHIR-based UIs.
TypeScript
14
star
8

youandme

Data comparison and analysis tools for 23andme raw data files.
Ruby
12
star
9

xweb

Project files for CST 533.
Ruby
8
star
10

kindle-drm

A Ruby library for performing DRM-related operations on .mobi files, know as DRM'd .azw files on the Amazon Kindle.
Ruby
7
star
11

user_story_kit

Turns simple user stories defined in .CSV files into human-readable, sorted Markdown documents.
Ruby
6
star
12

bibler-server

The RESTful JSON bible API and full-text search service.
Ruby
6
star
13

java-sorting

Java
5
star
14

Starfield

A 3D starfield simulation for OS X. Written in Ruby using ruby-processing. Distributed as a .app bundle running on jruby.
Ruby
5
star
15

railroady-web

Website source code for the RailRoady project.
HTML
4
star
16

alignment

A JavaScript pairwise sequence aligner demonstration using dynamic programming.
JavaScript
4
star
17

github-lab

In-class demo on getting a project set up with git! :)
3
star
18

snippets

Personal code snippets.
Java
3
star
19

tastyterm

Web-based SMART-on-FHIR terminology services client.
CSS
2
star
20

emphasays

An Open Source Java library of string distance calculators, phoneme reducers, and tools for combining said algorithms into weighted metrics for tailored name-entity recognition.
Java
2
star
21

Twiverse

A 3D Twitter client for OS X. Written in Ruby, distributed as a .app bundle running on jruby.
Ruby
2
star
22

pfastqcount

pfastqcount is an optimized C implementation of a FASTQ sequence prefix counter. The program counts the number of times every four-nucleotide prefix is encountered via the sequential memory mapping of each ASCII-encoded FASTQ file into the process space. This is useful as part of a genomic data sequencing pipeline to sanity check that barcodes used in multiplexed sample experiments occur as expected. An alternative Ruby implementation is provided (pfastqcount.rb) for maximum portability and validation. The C implementation has been written for 64-bit Unix-like systems only. The output of the program is valid comma-separated value (CSV) data that may be opened in your favorite spreadsheet software such as Excel, OpenOffice, R etc.
C
2
star
23

acraf

Aberration/Compound Response Annotation Format
1
star
24

preston.github.com

JavaScript
1
star
25

pipecleaner

Real-time workflow tracker web application for desktop and mobile devices.
Ruby
1
star
26

kindletools

A Ruby on Rails web application providing various services for Amazon Kindle owners.
Ruby
1
star
27

campus_manager

A simple web application for managing course enrollment. A project for CST 533 at ASU Polytechnic campus.
Ruby
1
star
28

idclight

A Ruby gem for accessing the freely available IDClight (IDConverter Light) web service, which convert between different types of gene IDs such as Hugo and Entrez. Queries are screen scraped from http://idclight.bioinfo.cnio.es.
Ruby
1
star