Diseñamos un lenguaje de programación multiparadigma. Parte 4 - Construcciones básicas del lenguaje de modelado

Continuamos la historia sobre la creación de un lenguaje de programación multiparadigma que combina un estilo declarativo con un estilo orientado a objetos y funcional, lo que sería conveniente cuando se trabaja con datos semiestructurados e integrando datos de fuentes dispares. Finalmente, luego de la introducción y revisión de tecnologías y lenguajes de representación del conocimiento multi-paradigma existentes , llegamos a la descripción de esa parte del lenguaje híbrido que se encarga de describir el modelo de dominio. Lo llamé el componente de modelado .



El componente de modelado está destinado a una descripción declarativa de un modelo de dominio en forma de ontología: una red de instancias de datos (hechos) y conceptos abstractos interconectados a través de relaciones. Se basa en la lógica del marco, un híbrido de un enfoque orientado a objetos para la representación del conocimiento y la lógica de primer orden. Su elemento principal es un concepto que describe un objeto modelado utilizando un conjunto de atributos. El concepto se construye sobre la base de otros conceptos o hechos, los conceptos iniciales se denominarán parental , el derivado - hijo... Las relaciones unen los valores de los atributos de los conceptos hijo y padre o limitan sus valores posibles. Decidí incluir las relaciones en la definición del concepto, de modo que toda la información al respecto esté, si es posible, en un solo lugar. El estilo de sintaxis para las definiciones de conceptos será similar a SQL: los atributos, los conceptos principales y las relaciones entre ellos deben separarse en diferentes secciones.



En este post quiero presentar las principales formas de definir conceptos.



Primero, un concepto que se construye transformando los conceptos de los padres .

En segundo lugar, el estilo orientado a objetos implica herencia , lo que significa que necesita un mecanismo que le permita crear un concepto heredando los atributos y relaciones de los conceptos principales, expandiéndolos o estrechándolos.



En tercer lugar, creo que sería útil un mecanismo para definir la relación entre los conceptos de los pares, sin dividirse en conceptos de padres e hijos.

Ahora vayamos a una consideración detallada de los principales tipos de componentes de modelado.



Comencemos con los hechos



Los hechos representan una descripción del conocimiento específico sobre un dominio en forma de un conjunto de pares clave-valor con nombre:



fact < > {
	< > : < >
	...	
}


Por ejemplo:



fact  product {
	name: “Cabernet Sauvignon”,
	type: “red wine”,
	country: “Chile”
}


El nombre de hecho puede no ser único, por ejemplo, puede haber muchos productos con diferentes nombres, tipos y países de origen. Consideraremos que los hechos son idénticos si sus nombres y los nombres y valores de sus atributos coinciden.



Se puede establecer una analogía entre hechos en el componente de modelado y hechos en Prolog. Se diferencian únicamente en la sintaxis. En Prolog, los argumentos de hechos se identifican por su posición y los atributos de los hechos del componente de modelado se identifican por su nombre.



Conceptos



Un concepto es una estructura que describe una entidad abstracta y se basa en otros conceptos y hechos. La definición de un concepto incluye un nombre, listas de atributos y conceptos secundarios. Y también una expresión lógica que describe las dependencias entre sus atributos (concepto secundario) y los atributos de los conceptos principales, lo que le permite mostrar el valor de los atributos del concepto secundario:



concept < > < > (
		< > = <>,
		...	
) 
from 
	<  > <  > (
		< > = <> 
	   	...
	 ),
where < >


Un ejemplo de definición de ganancias basada en ingresos y costos :



concept profit p (
	value = r.value – c.value,
	date
) from revenue r, cost c
where p.date = r.date = c.date


La definición de un concepto es similar en forma a una consulta SQL, pero en lugar del nombre de la tabla, debe especificar los nombres de los conceptos principales y, en lugar de las columnas devueltas, los atributos del concepto secundario. Además, un concepto tiene un nombre por el que se puede hacer referencia a él en las definiciones de otros conceptos o en las consultas de modelos. El concepto padre puede ser el concepto mismo o los hechos. La expresión relacional de la cláusula where es una expresión booleana que puede incluir operadores lógicos, condiciones de igualdad, operadores aritméticos, llamadas a funciones, etc. Sus argumentos pueden ser variables, constantes y referencias a atributos de conceptos padre e hijo. Las referencias de atributo tienen el siguiente formato:



< >.< >


En comparación con la lógica del marco, en la definición de un concepto, su estructura (atributos) se combina con relaciones con otros conceptos (conceptos padres y expresión de relaciones). Desde mi punto de vista, esto te permite hacer el código más comprensible, ya que toda la información sobre el concepto se recopila en un solo lugar. También cumple con el principio de encapsulación en el sentido de que los detalles de implementación de un concepto están ocultos dentro de su definición. A modo de comparación, se puede encontrar un pequeño ejemplo en el lenguaje de la lógica de marcos en la publicación anterior .



La expresión de relaciones tiene una forma conjuntiva (consiste en expresiones conectadas por operaciones lógicas "Y") y debe incluir condiciones de igualdad para todos los atributos del concepto hijo, suficientes para determinar sus valores. Además, puede incluir condiciones que limitan el significado de los conceptos principales o los conectan entre sí. Si no todos los conceptos principales están relacionados en la cláusula where , el motor de inferencia devolverá todas las combinaciones posibles de sus valores como resultado (similar a la operación FULL JOIN en SQL).



Por conveniencia, algunas de las condiciones para la igualdad de atributos se pueden colocar en la sección de atributos de los conceptos hijo y padre. Por ejemplo, en la definición de beneficio, la condición del atributoel valor se mueve a la sección de atributos, y para el atributo de fecha se deja en la sección where . También puede transferirlos a la de la sección :



concept profit p (
	value = r.value – c.value,
	date = r.date
) from revenue r, cost c (date = r.date)


Este azúcar sintáctico le permite hacer más explícitas las dependencias entre atributos y distinguirlas de otras condiciones.



Los conceptos siguen las reglas de Prolog pero tienen una semántica ligeramente diferente. Prolog se centra en la construcción de afirmaciones y preguntas relacionadas lógicamente. Los conceptos están destinados principalmente a estructurar datos de entrada y extraer información de ellos. Los atributos de concepto corresponden a los argumentos de los términos de Prolog. Pero si en Prolog el término argumentos se enlazan mediante variables, en nuestro caso se puede acceder directamente a los atributos por sus nombres.



Dado que la lista de conceptos principales y las condiciones de la relación se separan en secciones separadas, la inferencia será ligeramente diferente a la de Prolog. Describiré en general su algoritmo. Los conceptos principales se generarán en el orden en que se especifican en la sección from . La búsqueda de una solución para el siguiente concepto se realiza para cada solución parcial de los conceptos anteriores de la misma forma que en la resolución SLD. Pero para cada solución parcial, se comprueba la validez de la expresión de relación de la cláusula where .... Dado que esta expresión está en forma de conjunción, cada subexpresión se prueba por separado. Si la subexpresión es falsa, esta solución parcial se rechaza y la búsqueda pasa a la siguiente. Si algunos de los argumentos de subexpresión aún no están definidos (no asociados con valores), se pospone su validación. Si la subexpresión es un operador de igualdad y solo se define uno de sus argumentos, entonces el sistema de inferencia encontrará su valor e intentará asociarlo con el argumento restante. Esto es posible si el argumento libre es un atributo o variable.



Por ejemplo, al mostrar las entidades del concepto de lucro , las entidades del concepto de ingresos y, en consecuencia, los valores de sus atributos se encontrarán primero . Entonces la igualdad p.date = r.date = c.dateen la sección where le permitirá asociar atributos de fecha y otros conceptos con valores . Cuando la búsqueda lógica llegue al concepto de costo , el valor de su atributo de fecha ya será conocido y será el argumento de entrada para esta rama del árbol de búsqueda. Planeo hablar en detalle sobre los algoritmos de inferencia en una de las próximas publicaciones.



La diferencia con Prolog es que en las reglas de Prolog todo son predicados, y llamadas a otras reglas y predicados incorporados de igualdad, comparación, etc. Y el orden de su verificación debe especificarse explícitamente, por ejemplo, primero deben ir dos reglas y luego la igualdad de variables:



profit(value,date) :- revenue(rValue, date), cost(cValue, date), value = rValue – cValue


En este orden, se ejecutarán. El componente de modelado asume que todos los cálculos de condiciones en la cláusula where son deterministas, es decir, no requieren un buceo recursivo en la siguiente rama de búsqueda. Dado que su cálculo depende solo de sus argumentos, se pueden calcular en orden arbitrario ya que los argumentos están ligados a valores.



Como resultado de la inferencia, todos los atributos del concepto hijo deben asociarse con valores. Y también la expresión de las relaciones debe ser verdadera y no contener subexpresiones indefinidas. Vale la pena señalar que la derivación de conceptos parentales no tiene por qué ser exitosa. Hay casos en los que se requiere verificar el fallo de la derivación del concepto padre a partir de los datos originales, por ejemplo, en operaciones de negación. El orden de los conceptos de padres en el de la sección determina el orden en el que se recorre el árbol de decisión. Esto permite optimizar la búsqueda de una solución, partiendo de aquellos conceptos que limitan más fuertemente el espacio de búsqueda.



La tarea de la inferencia lógica es encontrar todas las posibles sustituciones de atributos del concepto de niño y representar cada uno de ellos como un objeto. Dichos objetos se consideran idénticos si sus nombres de conceptos, nombres y valores de atributos coinciden.



Se considera aceptable crear varios conceptos con el mismo nombre, pero con diferentes implementaciones, incluido un conjunto diferente de atributos. Pueden ser diferentes versiones del mismo concepto, conceptos relacionados que se pueden combinar convenientemente bajo un nombre, conceptos idénticos de diferentes fuentes, etc. En la conclusión lógica, se considerarán todas las definiciones existentes del concepto y se combinarán los resultados de su búsqueda. Varios conceptos con el mismo nombre son análogos a la regla en Prolog, en la que una lista de términos tiene una forma disyuntiva (los términos están en OR).



Herencia de conceptos



Una de las relaciones más comunes entre conceptos son las relaciones jerárquicas como género-especie. Su peculiaridad es que las estructuras de los conceptos de niño y padre serán muy similares. Por tanto, el soporte del mecanismo de herencia a nivel de sintaxis es muy importante, sin él, los programas estarán llenos de código repetitivo. Al construir una red de conceptos sería conveniente reutilizar tanto sus atributos como sus relaciones. Si bien la lista de atributos es fácil de ampliar, acortar o redefinir algunos de ellos, la situación con la modificación de relaciones es más complicada. Dado que son una expresión lógica en forma conjuntiva, es fácil agregarle subexpresiones adicionales. Sin embargo, eliminar o cambiar puede requerir una complicación de sintaxis significativa. Los beneficios de esto no son tan obviospor tanto, pospondremos esta tarea para el futuro.



Puede declarar un concepto basado en la herencia utilizando la siguiente construcción:



concept < > < > is 
	<  > <  > ( 
		< > = <>, 
		...
	 ),
	...
with < > = <>, ...
without <  >, ...
where < >


La sección is contiene una lista de conceptos heredados. Sus nombres se pueden especificar directamente en esta sección. O bien, especifique la lista completa de conceptos principales en la sección from , y en is - alias de solo aquellos que serán heredados:



concept < > < > is 
	<  >,
from 
	<  > <  > ( 
		< > = <> 
		   ...
	 ),
with < > = <>, ...
without <  >, ...
where < >


La sección con le permite expandir la lista de atributos de conceptos heredados o anular algunos de ellos, la sección sin - para acortar.



El algoritmo de inferencia de un concepto basado en la herencia es el mismo que el del concepto discutido anteriormente. La única diferencia es que la lista de atributos se genera automáticamente en base a la lista de atributos del concepto padre, y la expresión de relaciones se complementa con operaciones de igualdad de atributos de los conceptos hijo y padre.



Consideremos varios ejemplos del uso del mecanismo de herencia. La herencia le permite crear un concepto basado en uno existente, deshaciéndose de aquellos atributos que son significativos solo para el concepto padre, pero no para el hijo. Por ejemplo, si los datos de origen se presentan en forma de tabla, entonces las celdas de ciertas columnas pueden recibir sus propios nombres (eliminando el atributo con el número de columna):



concept revenue is tableCell without columnNum where columnNum = 2


También es posible transformar varios conceptos relacionados en una forma generalizada. Se necesita la sección with para convertir algunos de los atributos al formato general y agregar los que faltan. Por ejemplo, los datos de origen pueden ser documentos de diferentes versiones, cuya lista de campos ha cambiado con el tiempo:



concept resume is resumeV1 with skills = 'N/A'
concept resume is resumeV2 r with skills = r.coreSkills


Supongamos que la primera versión del concepto "Reanudar" no tenía un atributo con habilidades y la segunda versión tenía un nombre diferente.



En muchos casos, puede ser necesario ampliar la lista de atributos. Las tareas comunes son cambiar el formato de los atributos, agregar atributos que dependen funcionalmente de atributos existentes o datos externos, etc. Por ejemplo:



concept price is basicPrice with valueUSD = valueEUR * getCurrentRate('USD', 'EUR')


También es posible combinar simplemente varios conceptos bajo un nombre sin cambiar su estructura. Por ejemplo, para indicar que son del mismo género:



concept webPageElement is webPageLink
concept webPageElement is webPageInput


O cree un subconjunto de un concepto filtrando algunas de sus entidades:



concept exceptionalPerformer is employee where performanceEvaluationScore > 0.95


También es posible la herencia múltiple, en la que un concepto hijo hereda los atributos de todos los conceptos padre. Si hay nombres de atributos idénticos, se le dará prioridad al concepto padre a la izquierda de la lista. También puede resolver este conflicto manualmente anulando explícitamente el atributo deseado en la sección with. Por ejemplo, este tipo de herencia sería conveniente si necesita recopilar varios conceptos relacionados en una estructura "plana":



concept employeeInfo is employee e, department d where e.departmentId = d.id 


La herencia sin cambiar la estructura de los conceptos complica la verificación de la identidad de los objetos. Como ejemplo, considere la definición de artista excepcional . Las consultas sobre los conceptos de padre ( empleado ) e hijo ( ejecutante excepcional ) devolverán la misma entidad de empleado. Los objetos que lo representan serán idénticos en significado. Tendrán una fuente de datos común, la misma lista y valores de atributo, para un nombre de concepto diferente, según el concepto al que se haya realizado la consulta. Por tanto, la operación de igualdad de objetos debe tener en cuenta esta característica. Los nombres de concepto se consideran iguales si coinciden o están vinculados por una relación de herencia transitiva sin cambiar la estructura.



La herencia es un mecanismo útil que le permite expresar explícitamente relaciones entre conceptos como clase-subclase, privado-común y conjunto-subconjunto. Y también elimine el código duplicado en las definiciones de conceptos y haga que el código sea más comprensible. El mecanismo de herencia se basa en agregar / quitar atributos, combinar varios conceptos bajo un nombre y agregar condiciones de filtrado. No hay una semántica especial incrustada en él, todos pueden percibirlo y aplicarlo como quieran. Por ejemplo, cree una jerarquía de lo particular a lo general como en los ejemplos con los conceptos resume , price y webPageElement . O, a la inversa, de lo general a lo específico, como en los ejemplos con los conceptos de ingresos y artista excepcional.... Esto le permitirá ajustarse de manera flexible a las características específicas de las fuentes de datos.



Concepto para describir relaciones



Se decidió que, para la conveniencia de comprender el código y facilitar la integración del componente de modelado con el modelo OOP, la relación del concepto hijo con el padre debería incluirse en su definición. Así, estas relaciones definen la forma de obtener un concepto hijo de los padres. Si el modelo de dominio está construido en capas, y cada nueva capa se basa en la anterior, esto está justificado. Pero en algunos casos, la relación entre conceptos debe declararse por separado y no incluirse en la definición de uno de los conceptos. Puede ser una relación universal que desee definir en términos generales y aplicar a diferentes conceptos, por ejemplo, la relación Padre-Hijo. O una relación que conecta dos conceptos debe incluirse en la definición de ambos conceptos, de modo que sea posible encontrar tanto la esencia del primer concepto con los atributos conocidos del segundo, y viceversa.Luego, para evitar la duplicación de código, será conveniente establecer la relación por separado.



En la definición de una relación, es necesario enumerar los conceptos incluidos en ella y establecer una expresión lógica que los conecte entre sí:



relation < > 
between <  > <  > (
	< > = <>,
 	 ...	
),
...
where < >


Por ejemplo, una relación que describe rectángulos anidados se puede definir de la siguiente manera:



relation insideSquareRelation between square inner, square outer 
where inner.xLeft > outer.xLeft and inner.xRight < outer.xRight 
and inner.yBottom > outer.yBottom and inner.yUp < outer.yUp


Tal relación, de hecho, es un concepto común, cuyos atributos son las esencias de conceptos anidados:



concept insideSquare (
	inner = i
	outer = o												
) from square i, square o
where i.xLeft > o.xLeft and i.xRight < o.xRight 
and i.yBottom > o.yBottom and i.yUp < o.yUp


Una relación se puede utilizar en las definiciones de conceptos junto con otros conceptos principales. Los conceptos incluidos en la relación serán accesibles desde el exterior y jugarán el papel de sus atributos. Los nombres de los atributos coincidirán con los alias de conceptos anidados. El siguiente ejemplo indica que un formulario HTML incluye los elementos HTML que se encuentran dentro de él en una página HTML:



oncept htmlFormElement is e 
from htmlForm f, insideSquareRelation(inner = e, outer = f), htmlElement e


Al buscar una solución, primero se encontrarán todos los valores del concepto htmlForm , luego se asociarán con el concepto anidado externo de la relación insideSquare y se encontrarán los valores de su atributo interno . Al final, se filtrarán aquellos valores internos que estén relacionados con el concepto de htmlElement .



La relación también puede recibir semántica funcional; se puede usar como una función de un tipo booleano para verificar si la relación se cumple para las entidades de concepto anidadas dadas:



oncept htmlFormElement is e 
from htmlElement e, htmlForm f
where  insideSquareRelation(e, f)


A diferencia del caso anterior, aquí la relación se trata como una función, lo que afectará al orden de inferencia. La evaluación de la función se aplazará hasta el momento en que todos sus argumentos estén asociados a valores. Es decir, primero se encontrarán todas las combinaciones de valores de los conceptos htmlElement y htmlForm , y luego se filtrarán aquellas que no correspondan a la relación insideSquareRelation . Planeo hablar con más detalle sobre la integración de paradigmas de programación lógica y funcional en una de las próximas publicaciones.



Ahora es el momento de ver un pequeño ejemplo.



Las definiciones de hechos y tipos básicos de conceptos son suficientes para implementar el ejemplo con deudores de la primera publicación. Supongamos que tenemos dos archivos CSV que almacenan información del cliente (ID de cliente, nombre y dirección de correo electrónico) y facturas (ID de cuenta, ID de cliente, fecha, monto adeudado, monto pagado).



Y también existe un cierto procedimiento que lee el contenido de estos archivos y los convierte en un conjunto de hechos:



fact cell {
	table: “TableClients”,
	value: 1,
	rowNum: 1,
	columnNum: 1
};
fact cell {
	table: “TableClients”,
	value: “John”,
	rowNum: 1,
	columnNum: 2
};
fact cell {
	table: “TableClients”,
	value: “john@somewhere.net”,
	rowNum: 1,
	columnNum: 3
};
fact cell {
	table: “TableBills”,
	value: 1,
	rowNum: 1,
	columnNum: 1
};
fact cell {
	table: “TableBills”,
	value: 1,
	rowNum: 1,
	columnNum: 2
};
fact cell {
	table: “TableBills”,
	value: 2020-01-01,
	rowNum: 1,
	columnNum: 3
};
fact cell {
	table: “TableBills”,
	value: 100,
	rowNum: 1,
	columnNum: 4
};
fact cell {
	table: “TableBills”,
	value: 50,
	rowNum: 1,
	columnNum: 5
};


Primero, démosle a las celdas de la tabla nombres significativos:



concept clientId is cell where table = “TableClients” and columnNum = 1;
concept clientName is cell where table = “TableClients” and columnNum = 2;
concept clientEmail is cell where table = “TableClients” and columnNum = 3;
concept billId is cell where table = “TableBills” and columnNum = 1;
concept billClientId is cell where table = “TableBills” and columnNum = 2;
concept billDate is cell where table = “TableBills” and columnNum = 3;
concept billAmountToPay is cell where table = “TableBills” and columnNum = 4;
concept billAmountPaid is cell where table = “TableBills” and columnNum = 5;


Ahora puede combinar celdas de una fila en un solo objeto:



concept client (
	id = id.value,
	name = name.value,
	email = email.value
) from clientId id, clientName name, clientEmail email
where id.rowNum = name.rowNum = email.rowNum;


concept bill (
	id = id.value,
	clientId = clientId.value,
	date = date.value,
	amountToPay = toPay.value,
	amountPaid = paid.value
) from billId id, billClientId clientId, billDate date, billAmountToPay  toPay,  billAmountPaid  paid
where id.rowNum = clientId.rowNum = date.rowNum = toPay.rowNum = paid.rowNum;


Introducimos los conceptos "Factura impaga" y "Deudor":



concept unpaidBill is bill where amountToPay >  amountPaid;
concept debtor is client c where exist(unpaidBill {clientId: c.id});


Ambas definiciones usan herencia, el concepto unpaidBill es un subconjunto de los conceptos factura , deudor - el concepto de cliente . La definición de deudor contiene una subconsulta para el concepto de factura impaga . Consideraremos en detalle el mecanismo de consultas anidadas más adelante en una de las siguientes publicaciones.



Como ejemplo de un concepto "plano", definamos también el concepto de "Deuda del cliente", en el que combinamos algunos campos de los conceptos "Cliente" y "Cuenta":



concept clientDebt (
	clientName = c.name,
	billDate = b.date,
	debt = b. amountToPay – b.amountPaid
) from unpaidBill b, client c(id = b.client); 


La dependencia entre los atributos de los conceptos cliente y factura se traslada a la sección from , y las dependencias del concepto hijo clientDebt , a la sección de sus atributos. Si lo desea, todos se pueden colocar en la sección where ; el resultado será el mismo. Pero desde mi punto de vista, la versión actual es más concisa y enfatiza mejor el propósito de estas dependencias: definir relaciones entre conceptos.



Ahora intentemos definir el concepto de un moroso malicioso que tiene al menos 3 facturas pendientes de pago seguidas. Para hacer esto, necesita una relación que le permita ordenar las facturas de un cliente por su fecha. Una definición genérica se vería así:



relation billsOrder between bill next, bill prev
where next.date > prev.date and next.clientId = prev.clientId and not exist(
    bill inBetween 
    where  next.clientId = inBetween.clientId 
    and  next.date > inBetween.date  > prev.date
);


Establece que dos facturas van seguidas si pertenecen al mismo cliente, la fecha de una es mayor que la fecha de la otra y no hay otra factura entre ellas. En esta etapa, no quiero detenerme en la complejidad computacional de tal definición. Pero si, por ejemplo, sabemos que todas las facturas se emiten con un intervalo de 1 mes, entonces se puede simplificar enormemente:



relation billsOrder between bill next, bill prev
where next.date = prev.date + 1 month and next.clientId = prev.clientId;


La secuencia de 3 facturas impagas se verá así:



concept unpaidBillsSequence (clientId = b1.clientId, bill1 = b1, bill2 = b2, bill3 = b3) 
from 
    unpaidBill b1, 
    billsOrder next1 (next = b1, prev = b2)
    unpaidBill b2
    billsOrder next2 (next = b2, prev = b3)
    unpaidBill b3;


En este concepto, primero se encontrarán todas las facturas impagas, luego para cada una de ellas se encontrará la siguiente factura usando la relación next1 . La noción b2 le permitirá verificar que esta factura está impaga. Por el mismo principio, utilizando next2 y b3 , se encontrará la tercera factura pendiente de pago consecutiva. El identificador de cliente se ha agregado a la lista de atributos por separado, con el fin de facilitar aún más la vinculación de este concepto con el concepto de clientes:



concept hardCoreDefaulter is client c where exist(unpaidBillsSequence{clientId: c.id});


El ejemplo del deudor demuestra cómo se puede describir completamente un modelo de dominio en un estilo declarativo. Comparado con la implementación de este ejemplo en OOP o estilo funcional, el código resultante es muy conciso, comprensible y cercano a describir el problema en un lenguaje natural.



Breves conclusiones.



Entonces, propuse tres tipos principales de conceptos del componente de modelado de lenguaje híbrido:



  • conceptos creados a partir de la transformación de otros conceptos;
  • conceptos que heredan la estructura y las relaciones de otros conceptos;
  • conceptos que definen relaciones entre otros conceptos.


Estos tres tipos de conceptos tienen diferentes formas y propósitos, pero la lógica interna de encontrar soluciones es la misma para ellos, solo difiere el método de formar la lista de atributos.



Las definiciones de conceptos se asemejan a las consultas SQL, tanto en la forma como en la lógica interna de ejecución. Por lo tanto, espero que el lenguaje propuesto sea comprensible para los desarrolladores y tenga un umbral de entrada relativamente bajo. Y características adicionales como el uso de conceptos en otras definiciones de conceptos, herencia, relaciones derivadas y definiciones recursivas le permitirán ir más allá de SQL y hacer que su código sea más fácil de estructurar y reutilizar.



A diferencia de RDF y OWL, el componente de modelado no distingue entre conceptos y relaciones: todo son conceptos. En contraste con los lenguajes de la lógica de marcos, los marcos que describen la estructura de un concepto y las reglas que definen las conexiones entre ellos se combinan. A diferencia de los lenguajes de programación lógica tradicionales como Prolog, el elemento principal del modelo son los conceptos que tienen una estructura orientada a objetos y no las reglas que tienen una estructura plana. Este diseño de lenguaje puede no ser tan conveniente para crear ontologías a gran escala o un conjunto de reglas, pero es mucho mejor para trabajar con datos semiestructurados y para integrar fuentes de datos dispares. Los conceptos del componente de modelado se acercan a las clases del modelo POO, lo que debería facilitar la tarea de incluir una descripción declarativa del modelo en el código de la aplicación.



La descripción del componente de modelado aún no está completa. En el próximo artículo, planeo discutir temas del mundo de la lógica informática como las variables booleanas, la negación y los elementos de la lógica de orden superior. Y después de eso, definiciones anidadas de conceptos, agregaciones y conceptos que generan sus entidades usando una función determinada.



El texto completo en estilo científico en inglés está disponible en: papers.ssrn.com/sol3/papers.cfm?abstract_id=3555711



Enlaces a publicaciones anteriores:



Diseño de un lenguaje de programación multiparadigma. Parte 1 - ¿Para qué sirve?

Diseñamos un lenguaje de programación multiparadigma. Parte 2 - Comparación de la construcción de modelos en PL / SQL, LINQ y GraphQL

Diseñamos un lenguaje de programación multiparadigma. Parte 3: descripción general de los lenguajes de representación del conocimiento



All Articles