{"id":25209472,"url":"https://github.com/alexiush/logq","last_synced_at":"2025-10-25T09:31:29.055Z","repository":{"id":59018544,"uuid":"523230051","full_name":"Alexiush/LOGQ","owner":"Alexiush","description":"Logical programming tool that works similar to Prolog program. It's goal to simplify and extend prolog features and provide easy integration with mapping tool.","archived":false,"fork":false,"pushed_at":"2022-10-24T14:15:28.000Z","size":301,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-19T08:04:43.424Z","etag":null,"topics":["backtracking","csharp","dotnet","logic-programming"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alexiush.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-10T06:38:21.000Z","updated_at":"2024-01-27T11:22:31.000Z","dependencies_parsed_at":"2023-01-20T10:30:19.282Z","dependency_job_id":null,"html_url":"https://github.com/Alexiush/LOGQ","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexiush%2FLOGQ","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexiush%2FLOGQ/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexiush%2FLOGQ/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexiush%2FLOGQ/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alexiush","download_url":"https://codeload.github.com/Alexiush/LOGQ/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238117361,"owners_count":19419223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backtracking","csharp","dotnet","logic-programming"],"created_at":"2025-02-10T13:17:35.745Z","updated_at":"2025-10-25T09:31:23.631Z","avatar_url":"https://github.com/Alexiush.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LOGQ\n\nLOGQ stands for LOGical Query - it's logical programming tool that works similar to Prolog program. \nIt's goal to simplify and extend Prolog features and provide easy integration with mapping tool.\n\n[Documentation](https://alexiush.github.io/LOGQ/)  \n[NuGet package](https://www.nuget.org/packages/LOGQ)\n\n## Usage\n### Logical query\nMain feature is creating logical queries. They're built as trees with nodes represented by logical actions.\nLogical actions can be added using With method, some predefined logical actions can be added using Cut, Fail, Succed, WithScoped methods.\n```csharp\nLogicalQuery query = new LogicalQuery()\n  .With(() =\u003e true) \n  .Cut()\n  .Fail()\n  .OrWith(() =\u003e Console.WriteLine(\"Action!\"))\n  .Succed();\n```\n\n### Logical action\nLogical actions are abstractions used for query nodes, they define some sort of condition \nand created by specifying a backtrack iterator that provides them with predicates to check.\n```csharp\nLogicalQuery query = new LogicalQuery()\n  .With(() =\u003e 3 \u003e 1);\n  \n// In this case predicate will be converted to list with one predicate\n// Then it will be converted to backtrack iterator which will iterate through that list\n```\nLogical actions can be created by passing bactrack iterator, action, predicate or collection of predicates to the logical query using With.\nIf some of the given predicates is successful - logical action returns true, if each predicate fails - action returns false.\n\n### Backtrack iterator\nBacktrack iterator is used to replace Prolog's predicate types with single abstraction.\nIt consists of generator function and reset action:\n- Generator generates predicates for logical actions until it meets some terminal condition after which it returns null that means it's out of predicates.\n- Reset action returns generator back to it's initial state.\n\n```csharp\n// Backtrack iterator constructor for previous example\n\ninternal BacktrackIterator(ICollection\u003cPredicate\u003cList\u003cIBound\u003e\u003e\u003e initializer)\n{\n    bool enumeratorIsUpToDate = false;\n    var enumerator = initializer.GetEnumerator();\n\n    _generator = () =\u003e\n    {\n        if (!enumeratorIsUpToDate)\n        {\n            enumerator = initializer.GetEnumerator();\n            enumeratorIsUpToDate = true;\n        }\n\n        if (!enumerator.MoveNext())\n        {\n            return null;\n        }\n\n        Predicate\u003cList\u003cIBound\u003e\u003e predicate = enumerator.Current;\n        return predicate;\n    };\n\n    _reset = () =\u003e enumeratorIsUpToDate = false;\n}\n```\n\n### Knowledge base\nKnowledge bases are storing facts and rules and can provide backtrack iterators that would do fact-checking or rule-checking on base contents.\n\n```csharp\n// Let's say we have some records about school students\nKnowledgeBase students = new KnowledgeBase();\n\n// There is a record about student named Andrew in 7th grade\nstudents.DeclareFact(new FactStudent(\"Andrew\", 7))\n\n// Also we know that if we have a record about student in higher grade we also have records about that student in lesser grades\nstudents.DeclareRule(new RuleWithBody\u003cBoundRuleStudent\u003e(\n    new RuleStudent(new AnyValue\u003cstring\u003e(), new AnyValue\u003cint\u003e()),\n    bound =\u003e new LogicalQuery()\n        .With(new BoundFactStudent(bound.Name, bound.Grade), students)\n        .OrWith(context =\u003e bound.Grade.Value \u003c= 12)\n        .With(new BoundRuleStudent(bound.Name, bound.Grade.Value + 1), students)\n    ));\n```\n\n### Facts \nFacts are plain data stored in knowledge base.\n```csharp\nLogicalQuery query = new LogicalQuery()\n  .With(new BoundFactStudent(\"Andrew\", 1), students)\n  .With(new BoundFactStudent(\"Alex\", new UnboundVariable\u003cint\u003e()), students)\n```\nTo make a fact-check bound facts are created. Bound facts are facts using bound variables, \nthat stands for variables which mutation is controlled by backtracking (their values are restored to preaction state on the way back).\n\n### Rules\nRules are data with associated logical query which returns true only if that data exists.\nThey made with two parts:\n- Rule head that consists of patterns to check if this rule applies\n- Rule body that consists of query\n```csharp\nLogicalQuery query = new LogicalQuery()\n  .With(new BoundRuleStudent(\"Alex\", 3), students);\n```\nTo make a rule-check bound rules are created. Like bound facts that's rule heads made of bound variables.\n\n### Objects mapping\nObjects are mapped by marking them with Fact attribute.\nMarked objects are processed by source generator that creates their Fact, BoundFact, Rule and BoundRule analogues \nand adds static method to convert objects to their representations\n```csharp\n// Marking student class used in previous examples\n// That will generate FactStudent, BoundFactStudent, RuleStudent and BoundRuleStudentClasses \n\n[LOGQ.Fact(\"Student\")]\npublic class Student\n{\n    public string Name { get; set; }\n    public int Grade { get; set; }\n\n    public Student(string name, int grade)\n    {\n        Name = name;\n        Grade = grade;\n    }\n}\n```\n## Credits\n[Andrew Lock's source generator series](https://andrewlock.net/creating-a-source-generator-part-1-creating-an-incremental-source-generator/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexiush%2Flogq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexiush%2Flogq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexiush%2Flogq/lists"}