2017-02-27 2 views
0

Je voudrais implémenter une sorte de "base de données" dans Prolog.Implémenter des bases de données dans prolog

J'ai deux idées pour modéliser des tables et des rangs:

% First one 
client('B069','Laurent','769, rue de la LALALA','LLN','A1',10000). 

% Second one 
data(client,'B069',name,'Laurent'). 
data(client,'B069',adress,'69, rue de la LALALA'). 
data(client,'B069',town,'LLN'). 
data(client,'B069',cat,'A1'). 
data(client,'B069',amount,10000). 

Avec les deux modèles que je peux par exemple faire respectivement un « SELECT ID du client WHERE quantité> 0 » pour le client avec montant positif:

% First one 
client1_positive(Client) :- findall(ID,(data(client,ID,compte,Amount),Amount>0),Client). 

% Second one 
client2_positive(Client) :- findall(ID,(client(ID,_,_,_,_,Amount),Amount>0),Client). 

Ils ont tous deux la même sortie;

?- client1_positive(Clients). 
Client = ['B069']. 

?- client2_positive(Clients). 
Client = ['B069']. 

Mais voici mon problème, puisque je suis très nouveau pour Prolog Je ne sais absolument pas comment je peux faire cette dynamique, comme « SELECT nom du client WHERE ID = « B069 » ». Je peux implémenter une règle pour cette requête SQL spécifique mais je ne peux pas trouver un moyen d'implémenter une règle plus abstraite pour que chaque requête puisse être interprétée.

Existe-t-il une meilleure pratique pour modéliser ce type de données dans Prolog? Et quelques idées (pas une réponse détaillée à mon problème) sur la façon de rendre une demande plus abstraite dans Prolog?

Merci beaucoup

Répondre

2

Pensez à la façon dont vous le faire avec une base de données relationnelle. Vous auriez probablement une table Client avec des enregistrements composés d'un ID client (clé), du nom du client, de l'adresse, du téléphone, d'autres informations de contact. Vous ne voudriez pas un enregistrement séparé pour le nom, l'adresse, le téléphone, etc. Ce serait trop lourd.

Vous auriez des tables séparées pour les données des clients qui ont une relation avec le client (un à un, plusieurs à un, plusieurs à plusieurs, ...). Si comme clé primaire un client devait éventuellement avoir plus d'un ensemble d'informations de contact, alors c'est une relation many-to-one entre les informations de contact et le client, donc vous devriez mettre en place une table ContactInfo séparée avec un « contact_info_id » et aurait des enregistrements avec le contenu contact_info_id, l'ID du client, les informations de contact. Dans le cas des montants dans votre exemple, vous auriez une table Montant avec des enregistrements qui se composent du montant ID (clé), ID client, montant. Pour ce faire, dans Prolog, vous le structurez fondamentalement de la même manière. Configuration des client données et amount données:

% clients 
client('B069', 'John Doe', '123 Main St', 123-456-1234). 
client('B070', 'Jane Smith', '100 West Elm', 999-999-8888). 
... 

% amounts 
amount('A010', 'B069', 10000). 
amount('A010', 'B070', 10100). 
... 

ci-dessus pourrait être un à un ou plusieurs à un.

L'équivalent de la requête: SELECT name FROM client WHERE ID = 'B069' serait:

?- client('B069', Name, Address, Phone). 

Votre sélection de montants positifs serait:

client_positive(Clients) :- 
    findall(ClientId, (amount(_, ClientId, Amount), Amount > 0), Clients). 
+0

Merci qui m'a aidé. Et savez-vous avec ce modèle comment je peux obtenir par exemple le deuxième argument dans le client, une règle comme 'nth_arg (+ Predicate, + Nth, -Argument)'. Est-ce que ce genre de règle existe? – tomatediabolik

+0

@tomatediabolik Dans ce cas, vous connaissez la signification de chaque position d'argument. Quel est le cas d'utilisation pour choisir l'argument par index? Normalement, vous pourriez avoir quelque chose comme 'client_phone (ClientId, Phone): - client (CllientId, _, _, Phone).» Ou quelque chose comme ça. Si vous avez vraiment besoin de le sélectionner par index, vous pouvez utiliser 'arg/3' (' arg (+ Nth, + Term, -Argument) ') qui obtiendra le nième argument d'un terme. Sans plus d'informations sur votre cas d'utilisation, je ne sais pas trop quoi en dire. – lurker

0

Votre première approche est très bien. Vous pourriez avoir besoin de la seconde si, par exemple, une personne peut avoir plus d'une adresse.

Une requête est juste un terme avec des variables:

| ?- client('B069',Name,Adress,Town,Cat,Amount). 
Cat = 'A1', 
Name = 'Laurent', 
Town = 'LLN', 
Adress = '769, rue de la LALALA', 
Amount = 10000 ? 

Vous pouvez utiliser l'un des paramètres comme la clé dans la requête. Votre Prolog peut ne pas indexer tous les éléments, ce qui peut ou non poser un problème.

| ?- client(Key,'Laurent',_,_,_,_). 
Key = 'B069' ? 

S'il y a plusieurs réponses, elles sont renvoyées par retour arrière. Findall les rassemble dans une liste, qui peut être ou ne pas être ce que vous voulez.

Si par "dynamique" vous vouliez ajouter et supprimer du contenu de la base de données, alors vous pouvez assert/1 et retract/1.